-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
265 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,7 @@ jobs: | |
steps: | ||
- uses: actions/[email protected] | ||
with: | ||
repo-token: "${{ secrets.GITHUB_TOKEN }}" | ||
repo-token: ${{ secrets.GITHUB_TOKEN }} | ||
configuration-path: .github/labeler.yml | ||
sync-labels: true | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
from python_package_publish.client import HttpClient | ||
from python_package_publish.collections import chunk | ||
from python_package_publish.utils import get_utc_now, get_uuid | ||
from python_package_publish.version import __version__ # NOQA: F401 | ||
|
||
__all__ = ["chunk", "get_uuid", "get_utc_now"] | ||
__all__ = ["chunk", "get_uuid", "get_utc_now", "HttpClient"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
from typing import Any | ||
|
||
import requests | ||
from requests.exceptions import HTTPError | ||
|
||
from python_package_publish.errors import ServiceHTTPError | ||
|
||
|
||
class HttpClient: | ||
def __init__( | ||
self, | ||
url: str, | ||
timeout: Any = None, | ||
has_exception: bool = False, | ||
) -> None: | ||
self._base_url = url | ||
self._has_exception = has_exception | ||
self._timeout = timeout | ||
|
||
def get( | ||
self, | ||
route: str, | ||
headers: dict | None = None, | ||
params: dict | None = None, | ||
timeout: int = 30, | ||
) -> requests.Response: | ||
if headers is None: | ||
headers = {} | ||
|
||
if params is None: | ||
params = {} | ||
|
||
response = requests.get( | ||
url=f"{self._base_url}/{route}", | ||
headers=(self._headers() | headers), | ||
timeout=timeout, | ||
params=params, | ||
) | ||
if self._has_exception: | ||
try: | ||
response.raise_for_status() | ||
except HTTPError as exc: | ||
raise ServiceHTTPError(exception=exc) | ||
else: | ||
response.raise_for_status() | ||
return response | ||
|
||
def post( | ||
self, | ||
route: str, | ||
data: dict | list | None = None, | ||
headers: dict | None = None, | ||
timeout: int = 30, | ||
) -> requests.Response: | ||
if headers is None: | ||
headers = {} | ||
|
||
response = requests.post( | ||
f"{self._base_url}/{route}", | ||
json=data or {}, | ||
headers=(self._headers() | headers), | ||
timeout=timeout, | ||
) | ||
|
||
if self._has_exception: | ||
try: | ||
response.raise_for_status() | ||
except HTTPError as exc: | ||
raise ServiceHTTPError(exception=exc) | ||
else: | ||
response.raise_for_status() | ||
return response | ||
|
||
def put( | ||
self, route: str, data: dict, headers: dict | None = None, timeout: int = 30 | ||
) -> requests.Response: | ||
if headers is None: | ||
headers = {} | ||
|
||
response = requests.put( | ||
f"{self._base_url}/{route}", | ||
json=data, | ||
headers=(self._headers() | headers), | ||
timeout=timeout, | ||
) | ||
|
||
if self._has_exception: | ||
try: | ||
response.raise_for_status() | ||
except HTTPError as exc: | ||
raise ServiceHTTPError(exception=exc) | ||
else: | ||
response.raise_for_status() | ||
|
||
return response | ||
|
||
def patch( | ||
self, | ||
route: str, | ||
data: dict | None = None, | ||
headers: dict | None = None, | ||
timeout: int = 30, | ||
) -> requests.Response: | ||
if headers is None: | ||
headers = {} | ||
|
||
response = requests.patch( | ||
f"{self._base_url}/{route}", | ||
json=data or {}, | ||
headers=(self._headers() | headers), | ||
timeout=timeout, | ||
) | ||
|
||
if self._has_exception: | ||
try: | ||
response.raise_for_status() | ||
except HTTPError as exc: | ||
raise ServiceHTTPError(exception=exc) | ||
else: | ||
response.raise_for_status() | ||
|
||
return response | ||
|
||
def delete( | ||
self, route: str, headers: dict | None = None, timeout: int = 30 | ||
) -> requests.Response: | ||
if headers is None: | ||
headers = {} | ||
|
||
response = requests.delete( | ||
f"{self._base_url}/{route}", | ||
headers=(self._headers() | headers), | ||
timeout=timeout, | ||
) | ||
|
||
if self._has_exception: | ||
try: | ||
response.raise_for_status() | ||
except HTTPError as exc: | ||
raise ServiceHTTPError(exception=exc) | ||
else: | ||
response.raise_for_status() | ||
|
||
return response | ||
|
||
def _headers(self) -> dict: | ||
return {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from requests.exceptions import JSONDecodeError | ||
from requests.models import HTTPError | ||
|
||
|
||
class ServiceHTTPError(Exception): | ||
"""Adds response & error_id to base exception""" | ||
|
||
def __init__(self, exception: HTTPError): | ||
super().__init__(str(exception)) | ||
self.exception = exception | ||
self.response = exception.response | ||
self.error_id = None | ||
|
||
if self.response is None: | ||
return | ||
|
||
# set the error_id if the response has valid json and contains the `error_id` | ||
try: | ||
if (json := self.response.json()) and (error_id := json.get("error_id")): | ||
self.error_id = error_id | ||
except JSONDecodeError: | ||
pass | ||
|
||
def __reduce__(self) -> tuple[type, tuple[HTTPError]]: | ||
return self.__class__, (self.exception,) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import pytest | ||
import responses | ||
|
||
from python_package_publish.client import HttpClient | ||
from python_package_publish.errors import ServiceHTTPError | ||
|
||
|
||
@responses.activate | ||
def test_service_http_error_for_522_with_no_body() -> None: | ||
responses.add( | ||
responses.GET, | ||
"http://generic-url/request-path", | ||
json=None, | ||
status=522, | ||
) | ||
|
||
with pytest.raises(ServiceHTTPError) as error: | ||
HttpClient(url="http://generic-url", has_exception=True).get("request-path") | ||
|
||
service_http_error: ServiceHTTPError = error.value # type: ignore[annotation-unchecked] | ||
|
||
assert isinstance(service_http_error, ServiceHTTPError) | ||
assert service_http_error.response | ||
assert service_http_error.response.status_code == 522 | ||
assert service_http_error.error_id is None | ||
|
||
|
||
@responses.activate | ||
def test_service_http_error_for_522_with_empty() -> None: | ||
responses.add( | ||
responses.GET, | ||
"http://generic-url/request-path", | ||
json={}, | ||
status=522, | ||
) | ||
|
||
with pytest.raises(ServiceHTTPError) as error: | ||
HttpClient(url="http://generic-url", has_exception=True).get("request-path") | ||
|
||
service_http_error: ServiceHTTPError = error.value # type: ignore[annotation-unchecked] | ||
|
||
assert isinstance(service_http_error, ServiceHTTPError) | ||
assert service_http_error.response | ||
assert service_http_error.response.status_code == 522 | ||
assert service_http_error.error_id is None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters