Skip to content

Commit

Permalink
refactor: Replacing http_requests return type hint
Browse files Browse the repository at this point in the history
  • Loading branch information
lmilbaum committed Mar 13, 2023
1 parent 14e0f65 commit 5be9523
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 37 deletions.
10 changes: 5 additions & 5 deletions docs/api-levels.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Lower-lower-level API - HTTP requests
higher-level APIs. To lessen the chances of a change to the interface impacting your code, we
recommend using keyword arguments when calling the interfaces.

At the lowest level, HTTP methods call ``http_request()``, which performs the actual request and takes
At the lowest level, HTTP methods call ``backend_request()``, which performs the actual request and takes
care of details such as timeouts, retries, and handling rate-limits.

This method can be invoked directly to or customize this behavior for a single request, or to call custom
Expand All @@ -87,19 +87,19 @@ For example, if for whatever reason you want to fetch allowed methods for an end
>>> gl = gitlab.Gitlab(private_token=private_token)
>>>
>>> response = gl.http_request(verb="OPTIONS", path="/projects")
>>> response.headers["Allow"]
>>> backend_response = gl.backend_request(verb="OPTIONS", path="/projects")
>>> backend_response.headers["Allow"]
'OPTIONS, GET, POST, HEAD'
Or get the total number of a user's events with a customized HEAD request:

.. code-block:: python
>>> response = gl.http_request(
>>> backend_response = gl.backend_request(
verb="HEAD",
path="/events",
query_params={"sudo": "some-user"},
timeout=10
)
>>> response.headers["X-Total"]
>>> backend_response.headers["X-Total"]
'123'
117 changes: 85 additions & 32 deletions gitlab/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ def _check_redirects(result: requests.Response) -> None:
)
)

def http_request(
def backend_request(
self,
verb: str,
path: str,
Expand All @@ -653,7 +653,7 @@ def http_request(
retry_transient_errors: Optional[bool] = None,
max_retries: int = 10,
**kwargs: Any,
) -> requests.Response:
) -> _backends.DefaultResponse:
"""Make an HTTP request to the Gitlab server.
Args:
Expand Down Expand Up @@ -722,7 +722,7 @@ def http_request(
cur_retries = 0
while True:
try:
result = self._backend.http_request(
backend_response = self._backend.http_request(
method=verb,
url=url,
json=send_data.json,
Expand All @@ -744,20 +744,26 @@ def http_request(

raise

self._check_redirects(result.response)
self._check_redirects(backend_response.response)

if 200 <= result.status_code < 300:
return result.response
if 200 <= backend_response.status_code < 300:
return backend_response

def should_retry() -> bool:
if result.status_code == 429 and obey_rate_limit:
if backend_response.status_code == 429 and obey_rate_limit:
return True

if not retry_transient_errors:
return False
if result.status_code in gitlab.const.RETRYABLE_TRANSIENT_ERROR_CODES:
if (
backend_response.status_code
in gitlab.const.RETRYABLE_TRANSIENT_ERROR_CODES
):
return True
if result.status_code == 409 and "Resource lock" in result.reason:
if (
backend_response.status_code == 409
and "Resource lock" in backend_response.reason
):
return True

return False
Expand All @@ -767,36 +773,74 @@ def should_retry() -> bool:
# https://docs.gitlab.com/ee/user/admin_area/settings/user_and_ip_rate_limits.html#response-headers
if max_retries == -1 or cur_retries < max_retries:
wait_time = 2**cur_retries * 0.1
if "Retry-After" in result.headers:
wait_time = int(result.headers["Retry-After"])
elif "RateLimit-Reset" in result.headers:
wait_time = int(result.headers["RateLimit-Reset"]) - time.time()
if "Retry-After" in backend_response.headers:
wait_time = int(backend_response.headers["Retry-After"])
elif "RateLimit-Reset" in backend_response.headers:
wait_time = (
int(backend_response.headers["RateLimit-Reset"])
- time.time()
)
cur_retries += 1
time.sleep(wait_time)
continue

error_message = result.content
error_message = backend_response.content
try:
error_json = result.json()
error_json = backend_response.json()
for k in ("message", "error"):
if k in error_json:
error_message = error_json[k]
except (KeyError, ValueError, TypeError):
pass

if result.status_code == 401:
if backend_response.status_code == 401:
raise gitlab.exceptions.GitlabAuthenticationError(
response_code=result.status_code,
response_code=backend_response.status_code,
error_message=error_message,
response_body=result.content,
response_body=backend_response.content,
)

raise gitlab.exceptions.GitlabHttpError(
response_code=result.status_code,
response_code=backend_response.status_code,
error_message=error_message,
response_body=result.content,
response_body=backend_response.content,
)

def http_request(
self,
verb: str,
path: str,
query_data: Optional[Dict[str, Any]] = None,
post_data: Optional[Union[Dict[str, Any], bytes]] = None,
raw: bool = False,
streamed: bool = False,
files: Optional[Dict[str, Any]] = None,
timeout: Optional[float] = None,
obey_rate_limit: bool = True,
retry_transient_errors: Optional[bool] = None,
max_retries: int = 10,
**kwargs: Any,
) -> requests.Response:
utils.warn(
"`http_request()` is deprecated and will be removed in a future version.\n"
"Please use `backend_request()` instead.",
category=DeprecationWarning,
)
return self.backend_request(
verb,
path,
query_data,
post_data,
raw,
streamed,
files,
timeout,
obey_rate_limit,
retry_transient_errors,
max_retries,
**kwargs,
).response

def http_get(
self,
path: str,
Expand Down Expand Up @@ -825,10 +869,11 @@ def http_get(
GitlabParsingError: If the json data could not be parsed
"""
query_data = query_data or {}
result = self.http_request(
backend_response = self.backend_request(
"get", path, query_data=query_data, streamed=streamed, **kwargs
)
content_type = utils.get_content_type(result.headers.get("Content-Type"))
content_type = utils.get_content_type(backend_response.headers.get("Content-Type"))
result = backend_response.response

if content_type == "application/json" and not streamed and not raw:
try:
Expand Down Expand Up @@ -861,8 +906,10 @@ def http_head(
"""

query_data = query_data or {}
result = self.http_request("head", path, query_data=query_data, **kwargs)
return result.headers
backend_response = self.http_request(
"head", path, query_data=query_data, **kwargs
)
return backend_response.headers

def http_list(
self,
Expand Down Expand Up @@ -1018,7 +1065,7 @@ def http_post(
query_data = query_data or {}
post_data = post_data or {}

result = self.http_request(
backend_response = self.backend_request(
"post",
path,
query_data=query_data,
Expand All @@ -1027,7 +1074,8 @@ def http_post(
raw=raw,
**kwargs,
)
content_type = utils.get_content_type(result.headers.get("Content-Type"))
content_type = utils.get_content_type(backend_response.headers.get("Content-Type"))
result = backend_response.response

try:
if content_type == "application/json":
Expand Down Expand Up @@ -1072,7 +1120,7 @@ def http_put(
query_data = query_data or {}
post_data = post_data or {}

result = self.http_request(
backend_response = self.http_request(
"put",
path,
query_data=query_data,
Expand All @@ -1082,7 +1130,7 @@ def http_put(
**kwargs,
)
try:
json_result = result.json()
json_result = backend_response.json()
if TYPE_CHECKING:
assert isinstance(json_result, dict)
return json_result
Expand Down Expand Up @@ -1121,7 +1169,7 @@ def http_patch(
query_data = query_data or {}
post_data = post_data or {}

result = self.http_request(
backend_response = self.http_request(
"patch",
path,
query_data=query_data,
Expand All @@ -1130,7 +1178,7 @@ def http_patch(
**kwargs,
)
try:
json_result = result.json()
json_result = backend_response.json()
if TYPE_CHECKING:
assert isinstance(json_result, dict)
return json_result
Expand All @@ -1153,7 +1201,8 @@ def http_delete(self, path: str, **kwargs: Any) -> requests.Response:
Raises:
GitlabHttpError: When the return code is not 2xx
"""
return self.http_request("delete", path, **kwargs)
backend_response = self.backend_request("delete", path, **kwargs)
return backend_response.response

@gitlab.exceptions.on_http_error(gitlab.exceptions.GitlabSearchError)
def search(
Expand Down Expand Up @@ -1207,7 +1256,11 @@ def _query(
self, url: str, query_data: Optional[Dict[str, Any]] = None, **kwargs: Any
) -> None:
query_data = query_data or {}
result = self._gl.http_request("get", url, query_data=query_data, **kwargs)
backend_response = self._gl.backend_request(
"get", url, query_data=query_data, **kwargs
)
result = backend_response.response

try:
next_url = result.links["next"]["url"]
except KeyError:
Expand Down

0 comments on commit 5be9523

Please sign in to comment.