This repository has been archived by the owner on Jul 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
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
1 parent
739d6c3
commit 991d06a
Showing
25 changed files
with
1,125 additions
and
941 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
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
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,16 @@ | ||
"""Package for dealing with HTTP.""" | ||
from .base import ( | ||
HTTPClient, | ||
HTTPConnectionError, | ||
HTTPRequestError, | ||
HTTPResponse, | ||
HTTPTimeoutError, | ||
) | ||
|
||
__all__ = [ | ||
"HTTPClient", | ||
"HTTPConnectionError", | ||
"HTTPRequestError", | ||
"HTTPResponse", | ||
"HTTPTimeoutError", | ||
] |
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,117 @@ | ||
"""Base client.""" | ||
|
||
import json as jsonlib | ||
from abc import ABC, abstractmethod | ||
from typing import Optional | ||
|
||
_DEFAULT_REQUEST_TIMEOUT = 5 | ||
|
||
|
||
class HTTPRequestError(Exception): | ||
"""Base HTTP request error.""" | ||
|
||
|
||
class HTTPConnectionError(HTTPRequestError): | ||
"""Any error related to connection.""" | ||
|
||
|
||
class HTTPTimeoutError(HTTPRequestError): | ||
"""HTTP request timed out.""" | ||
|
||
|
||
class HTTPInvalidResponseError(HTTPRequestError): | ||
"""HTTP response is invalid.""" | ||
|
||
|
||
class HTTPResponse: | ||
"""HTTP response wrapper.""" | ||
|
||
# pylint: disable=too-few-public-methods | ||
def __init__( | ||
self, status_code: int, body: Optional[bytes], headers: dict | ||
) -> None: | ||
self.status_code = status_code | ||
self.body = body or b"" | ||
self._headers = headers | ||
|
||
self._json = None | ||
|
||
@property | ||
def json(self) -> Optional[dict]: | ||
"""Return body as JSON.""" | ||
if self._json is not None: | ||
return self._json | ||
|
||
headers = {key.lower(): val for key, val in self._headers.items()} | ||
if "application/json" in headers.get("content-type", ""): | ||
try: | ||
self._json = jsonlib.loads(self.body) | ||
except Exception as exc: | ||
raise HTTPInvalidResponseError( | ||
f"Invalid JSON in response: {exc}" | ||
) from exc | ||
|
||
return self._json | ||
|
||
@property | ||
def success(self) -> bool: | ||
"""Return whether HTTP request was successful.""" | ||
return self.status_code < 400 | ||
|
||
def __str__(self) -> str: | ||
return f"{self.__class__.__name__}(status={self.status_code})" | ||
|
||
def __repr__(self) -> str: | ||
return ( | ||
f"{self.__class__.__name__}(" | ||
f"status={self.status_code}, " | ||
f"body={self.body}, " | ||
f"headers={self._headers}" | ||
")" | ||
) | ||
|
||
|
||
class HTTPClient(ABC): | ||
# pylint:disable=too-few-public-methods | ||
"""Base HTTP client.""" | ||
|
||
def __init__(self, timeout: int = _DEFAULT_REQUEST_TIMEOUT) -> None: | ||
self.timeout = timeout | ||
|
||
# pylint: disable=too-many-arguments | ||
@abstractmethod | ||
def _request( | ||
self, | ||
method: str, | ||
url: str, | ||
json: Optional[dict] = None, | ||
headers: Optional[dict] = None, | ||
) -> HTTPResponse: | ||
"""Perform request. | ||
This method must handle all possible HTTP exceptions and raise them | ||
as `HTTPRequestError`. | ||
Always use `headers`. You may extend it when needed. | ||
:param url: API method URL | ||
:param method: HTTP method | ||
:param json: JSON data to post | ||
:param headers: headers to be sent | ||
""" | ||
|
||
def request( | ||
self, | ||
method: str, | ||
url: str, | ||
json: Optional[dict] = None, | ||
headers: Optional[dict] = None, | ||
) -> HTTPResponse: | ||
"""Perform HTTP request with a given HTTP method. | ||
:param method: HTTP method to use | ||
:param url: API URL | ||
:param json: JSON data to post | ||
:param headers: headers | ||
""" | ||
return self._request(method, url, json, headers=headers) |
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,54 @@ | ||
"""HTTP client which uses `requests` under the hood.""" | ||
|
||
from typing import Optional | ||
|
||
import requests | ||
|
||
from .base import ( | ||
_DEFAULT_REQUEST_TIMEOUT, | ||
HTTPClient, | ||
HTTPConnectionError, | ||
HTTPRequestError, | ||
HTTPResponse, | ||
HTTPTimeoutError, | ||
) | ||
|
||
|
||
class RequestsHTTPClient(HTTPClient): | ||
# pylint: disable=too-few-public-methods | ||
"""`requests` HTTP client.""" | ||
|
||
def __init__(self, timeout: int = _DEFAULT_REQUEST_TIMEOUT) -> None: | ||
super().__init__(timeout) | ||
self._session = requests.Session() | ||
|
||
# pylint: disable=too-many-arguments | ||
def _request( | ||
self, | ||
method: str, | ||
url: str, | ||
json: Optional[dict] = None, | ||
headers: Optional[dict] = None, | ||
) -> HTTPResponse: | ||
try: | ||
response: requests.Response = getattr( | ||
self._session, method.lower() | ||
)( | ||
url, | ||
json=json, | ||
timeout=self.timeout, | ||
headers=headers, | ||
) | ||
except ConnectionError as exc: | ||
raise HTTPConnectionError(exc) from exc | ||
except requests.Timeout as exc: | ||
raise HTTPTimeoutError(exc) from exc | ||
except requests.RequestException as exc: | ||
raise HTTPRequestError(exc) from exc | ||
|
||
return HTTPResponse( | ||
response.status_code, response.content, dict(response.headers) | ||
) | ||
|
||
def __str__(self) -> str: | ||
return self.__class__.__name__ |
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,22 +1,15 @@ | ||
"""Client for API v.1.9.""" | ||
from .client import Client | ||
|
||
from .cart import Cart, CartItem | ||
from .client import Client | ||
from .currency import Currency | ||
from .key import CachedRSAKey, FileRSAKey, RSAKey | ||
from .payment import ( | ||
APIError, | ||
PaymentInfo, | ||
PaymentMethod, | ||
PaymentOperation, | ||
PaymentStatus, | ||
) | ||
from .webpage import WebPageAppearanceConfig, WebPageLanguage | ||
from .key import RSAKey, FileRSAKey, CachedRSAKey | ||
from .signature import InvalidSignatureError | ||
from .http import ( | ||
HTTPClient, | ||
HTTPConnectionError, | ||
HTTPRequestError, | ||
HTTPResponse, | ||
HTTPTimeoutError, | ||
RequestsHTTPClient, | ||
) | ||
from .webpage import WebPageAppearanceConfig, WebPageLanguage |
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 was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.