apytizer 0.0.1a0__py3-none-any.whl → 0.0.1b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- apytizer/__init__.py +2 -12
- apytizer/adapters/__init__.py +2 -3
- apytizer/adapters/transport_adapter.py +91 -0
- apytizer/apis/__init__.py +6 -0
- apytizer/apis/abstract_api.py +36 -0
- apytizer/apis/web_api.py +461 -0
- apytizer/connections/__init__.py +6 -0
- apytizer/connections/abstract_connection.py +28 -0
- apytizer/connections/http_connection.py +431 -0
- apytizer/decorators/__init__.py +5 -5
- apytizer/decorators/caching.py +60 -9
- apytizer/decorators/chunking.py +105 -0
- apytizer/decorators/connection.py +55 -20
- apytizer/decorators/json_response.py +93 -0
- apytizer/decorators/pagination.py +50 -32
- apytizer/endpoints/__init__.py +6 -0
- apytizer/endpoints/abstract_endpoint.py +38 -0
- apytizer/endpoints/web_endpoint.py +519 -0
- apytizer/engines/__init__.py +6 -0
- apytizer/engines/abstract_engine.py +45 -0
- apytizer/engines/http_engine.py +129 -0
- apytizer/errors.py +34 -0
- apytizer/factories/__init__.py +5 -0
- apytizer/factories/abstract_factory.py +17 -0
- apytizer/http_methods.py +34 -0
- apytizer/managers/__init__.py +12 -0
- apytizer/managers/abstract_manager.py +80 -0
- apytizer/managers/base_manager.py +116 -0
- apytizer/mappers/__init__.py +6 -0
- apytizer/mappers/abstract_mapper.py +48 -0
- apytizer/mappers/base_mapper.py +78 -0
- apytizer/media_types.py +118 -0
- apytizer/models/__init__.py +6 -0
- apytizer/models/abstract_model.py +119 -0
- apytizer/models/base_model.py +85 -0
- apytizer/protocols.py +38 -0
- apytizer/repositories/__init__.py +6 -0
- apytizer/repositories/abstract_repository.py +81 -0
- apytizer/repositories/managed_repository.py +92 -0
- apytizer/routes/__init__.py +6 -0
- apytizer/routes/abstract_route.py +32 -0
- apytizer/routes/base_route.py +138 -0
- apytizer/sessions/__init__.py +33 -0
- apytizer/sessions/abstract_session.py +63 -0
- apytizer/sessions/requests_session.py +125 -0
- apytizer/states/__init__.py +6 -0
- apytizer/states/abstract_state.py +71 -0
- apytizer/states/local_state.py +99 -0
- apytizer/utils/__init__.py +9 -4
- apytizer/utils/caching.py +39 -0
- apytizer/utils/dictionaries.py +375 -0
- apytizer/utils/errors.py +104 -0
- apytizer/utils/iterables.py +91 -0
- apytizer/utils/objects.py +145 -0
- apytizer/utils/strings.py +69 -0
- apytizer/utils/typing.py +29 -0
- apytizer-0.0.1b1.dist-info/METADATA +41 -0
- apytizer-0.0.1b1.dist-info/RECORD +60 -0
- {apytizer-0.0.1a0.dist-info → apytizer-0.0.1b1.dist-info}/WHEEL +1 -2
- apytizer/abstracts/__init__.py +0 -8
- apytizer/abstracts/api.py +0 -147
- apytizer/abstracts/endpoint.py +0 -177
- apytizer/abstracts/model.py +0 -50
- apytizer/abstracts/session.py +0 -39
- apytizer/adapters/transport.py +0 -40
- apytizer/base/__init__.py +0 -8
- apytizer/base/api.py +0 -510
- apytizer/base/endpoint.py +0 -443
- apytizer/base/model.py +0 -119
- apytizer/decorators/json.py +0 -35
- apytizer/utils/generate_key.py +0 -18
- apytizer/utils/merge.py +0 -19
- apytizer-0.0.1a0.dist-info/METADATA +0 -27
- apytizer-0.0.1a0.dist-info/RECORD +0 -25
- apytizer-0.0.1a0.dist-info/top_level.txt +0 -1
- {apytizer-0.0.1a0.dist-info → apytizer-0.0.1b1.dist-info/licenses}/LICENSE +0 -0
apytizer/__init__.py
CHANGED
|
@@ -1,14 +1,4 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
+
# src/apytizer/__init__.py
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
from .base import BasicAPI as API
|
|
5
|
-
from .base import SessionAPI as Session
|
|
6
|
-
from .base import BasicEndpoint as Endpoint
|
|
7
|
-
from .base import BasicModel as Model
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
VERSION = (0, 0, 1, 'alpha', 0)
|
|
11
|
-
|
|
12
|
-
__version__ = '.'.join(str(v) for v in VERSION[:2])
|
|
13
|
-
|
|
14
|
-
__release__ = '.'.join(str(v) for v in VERSION)
|
|
4
|
+
__version__ = "0.0.1"
|
apytizer/adapters/__init__.py
CHANGED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# src/apytizer/adapters/transport_adapter.py
|
|
3
|
+
"""Transport Adapter.
|
|
4
|
+
|
|
5
|
+
This module defines a transport adapter class: an implementation of an
|
|
6
|
+
HTTPAdapter which handles exponential backoff for retrying requests and
|
|
7
|
+
provides default values for rate limiting and timeout.
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# Standard Library Imports
|
|
12
|
+
from http import HTTPStatus
|
|
13
|
+
from typing import Any
|
|
14
|
+
from urllib3.util import Retry
|
|
15
|
+
|
|
16
|
+
# Third-Party Imports
|
|
17
|
+
from requests import PreparedRequest
|
|
18
|
+
from requests import Response
|
|
19
|
+
from requests.adapters import HTTPAdapter
|
|
20
|
+
|
|
21
|
+
# Local Import
|
|
22
|
+
from ..http_methods import HTTPMethod
|
|
23
|
+
|
|
24
|
+
__all__ = ["TransportAdapter"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Constants
|
|
28
|
+
DEFAULT_RATE_LIMIT = 1
|
|
29
|
+
DEFAULT_TIMEOUT = 5
|
|
30
|
+
NUMBER_OF_RETRIES = 10
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TransportAdapter(HTTPAdapter):
|
|
34
|
+
"""Implementation of a transport adaptor.
|
|
35
|
+
|
|
36
|
+
Transport adapters define methods for interacting with HTTP services,
|
|
37
|
+
enabling the use of per-service configurations.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
*args: Positional arguments.
|
|
41
|
+
rate_limit (optional): Rate limit.
|
|
42
|
+
timeout (optional): Timeout.
|
|
43
|
+
**kwargs: Keyword arguments.
|
|
44
|
+
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
*args: Any,
|
|
50
|
+
rate_limit: int = DEFAULT_RATE_LIMIT,
|
|
51
|
+
timeout: int = DEFAULT_TIMEOUT,
|
|
52
|
+
**kwargs: Any,
|
|
53
|
+
) -> None:
|
|
54
|
+
kwargs.setdefault("max_retries", make_retry(rate_limit))
|
|
55
|
+
super().__init__(*args, **kwargs)
|
|
56
|
+
self.timeout = timeout
|
|
57
|
+
|
|
58
|
+
def send(
|
|
59
|
+
self,
|
|
60
|
+
request: PreparedRequest,
|
|
61
|
+
*args: Any,
|
|
62
|
+
**kwargs: Any,
|
|
63
|
+
) -> Response:
|
|
64
|
+
kwargs.setdefault("timeout", self.timeout)
|
|
65
|
+
return super().send(request, *args, **kwargs)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def make_retry(rate_limit: int) -> Retry:
|
|
69
|
+
"""Make retry configuration.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
rate_limit: Rate limit for backoff factor.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Retry configuration.
|
|
76
|
+
|
|
77
|
+
"""
|
|
78
|
+
result = Retry(
|
|
79
|
+
total=NUMBER_OF_RETRIES,
|
|
80
|
+
status_forcelist=[
|
|
81
|
+
HTTPStatus.REQUEST_ENTITY_TOO_LARGE,
|
|
82
|
+
HTTPStatus.TOO_MANY_REQUESTS,
|
|
83
|
+
HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
84
|
+
HTTPStatus.BAD_GATEWAY,
|
|
85
|
+
HTTPStatus.SERVICE_UNAVAILABLE,
|
|
86
|
+
HTTPStatus.GATEWAY_TIMEOUT,
|
|
87
|
+
],
|
|
88
|
+
allowed_methods=[method.name for method in HTTPMethod],
|
|
89
|
+
backoff_factor=rate_limit,
|
|
90
|
+
)
|
|
91
|
+
return result
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# src/apytizer/apis/abstract_api.py
|
|
3
|
+
"""Abstract API Class.
|
|
4
|
+
|
|
5
|
+
This module defines an abstract API class which provides an interface
|
|
6
|
+
for subclasses to implement.
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Standard Library Imports
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
import abc
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
# Local Imports
|
|
16
|
+
from ..connections import AbstractConnection
|
|
17
|
+
|
|
18
|
+
__all__ = ["AbstractAPI"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AbstractAPI(abc.ABC):
|
|
22
|
+
"""Represents an abstract API."""
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
@abc.abstractmethod
|
|
26
|
+
def connection(self) -> Optional[AbstractConnection]:
|
|
27
|
+
"""Connection with which to make requests."""
|
|
28
|
+
raise NotImplementedError
|
|
29
|
+
|
|
30
|
+
@abc.abstractmethod
|
|
31
|
+
def __eq__(self, other: object) -> bool:
|
|
32
|
+
raise NotImplementedError
|
|
33
|
+
|
|
34
|
+
@abc.abstractmethod
|
|
35
|
+
def __hash__(self) -> int:
|
|
36
|
+
raise NotImplementedError
|
apytizer/apis/web_api.py
ADDED
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# src/apytizer/apis/web_api.py
|
|
3
|
+
"""Web API class.
|
|
4
|
+
|
|
5
|
+
This module defines the web API class implementation.
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# Standard Library Imports
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
from typing import Any
|
|
12
|
+
from typing import Dict
|
|
13
|
+
from typing import final
|
|
14
|
+
from typing import Optional
|
|
15
|
+
from typing import Type
|
|
16
|
+
|
|
17
|
+
# Third-Party Imports
|
|
18
|
+
from requests import Response
|
|
19
|
+
|
|
20
|
+
# Local Imports
|
|
21
|
+
from .abstract_api import AbstractAPI
|
|
22
|
+
from ..connections import HttpConnection
|
|
23
|
+
from ..endpoints import AbstractEndpoint
|
|
24
|
+
from ..endpoints import WebEndpoint
|
|
25
|
+
from ..engines import AbstractEngine
|
|
26
|
+
from ..routes import AbstractRoute
|
|
27
|
+
from .. import errors
|
|
28
|
+
|
|
29
|
+
__all__ = ["WebAPI"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class WebAPI(AbstractAPI):
|
|
33
|
+
"""Implements a web API.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
engine: Engine.
|
|
37
|
+
endpoints (optional): Endpoints. Default ``None``.
|
|
38
|
+
locked (optional): Whether to lock endpoints. Default ``False``.
|
|
39
|
+
|
|
40
|
+
Raises:
|
|
41
|
+
TypeError: when `engine` argument is not type ``Engine``.
|
|
42
|
+
TypeError: when `endpoints` argument is not type ``dict``.
|
|
43
|
+
TypeError: when `locked` argument is not type ``bool``.
|
|
44
|
+
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
engine: AbstractEngine,
|
|
50
|
+
/,
|
|
51
|
+
endpoints: Optional[Dict[AbstractRoute, Type[WebEndpoint]]] = None,
|
|
52
|
+
*,
|
|
53
|
+
locked: bool = False,
|
|
54
|
+
) -> None:
|
|
55
|
+
if not isinstance(engine, AbstractEngine): # type: ignore
|
|
56
|
+
message = f"expected type 'Engine', got {type(engine)} instead"
|
|
57
|
+
raise TypeError(message)
|
|
58
|
+
|
|
59
|
+
if endpoints and not isinstance(endpoints, dict): # type: ignore
|
|
60
|
+
message = f"expected type 'dict', got {type(endpoints)} instead"
|
|
61
|
+
raise TypeError(message)
|
|
62
|
+
|
|
63
|
+
if not isinstance(locked, bool): # type: ignore
|
|
64
|
+
message = f"expected type 'bool', got {type(locked)} instead"
|
|
65
|
+
raise TypeError(message)
|
|
66
|
+
|
|
67
|
+
self._engine = engine
|
|
68
|
+
self._endpoints = endpoints.copy() if endpoints else {}
|
|
69
|
+
self._locked = locked
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def connection(self) -> Optional[HttpConnection]:
|
|
73
|
+
"""Connection with which to make requests."""
|
|
74
|
+
result = getattr(self, "_connection", None)
|
|
75
|
+
return result
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def url(self) -> str:
|
|
79
|
+
"""Base URL."""
|
|
80
|
+
return self._engine.url
|
|
81
|
+
|
|
82
|
+
@final
|
|
83
|
+
def __enter__(self) -> AbstractAPI:
|
|
84
|
+
"""Starts API as context manager."""
|
|
85
|
+
self.connect()
|
|
86
|
+
return self
|
|
87
|
+
|
|
88
|
+
@final
|
|
89
|
+
def __exit__(self, *_) -> None:
|
|
90
|
+
"""Ends API as context manager."""
|
|
91
|
+
self.close()
|
|
92
|
+
|
|
93
|
+
def __eq__(self, other: object) -> bool:
|
|
94
|
+
result = (
|
|
95
|
+
other.url.lower() == self.url.lower()
|
|
96
|
+
if isinstance(other, WebAPI)
|
|
97
|
+
else False
|
|
98
|
+
)
|
|
99
|
+
return result
|
|
100
|
+
|
|
101
|
+
def __hash__(self) -> int:
|
|
102
|
+
result = hash(self.url)
|
|
103
|
+
return result
|
|
104
|
+
|
|
105
|
+
def __repr__(self) -> str:
|
|
106
|
+
result = f"<{self.__class__.__name__!s} url={self.url!s}>"
|
|
107
|
+
return result
|
|
108
|
+
|
|
109
|
+
def __getitem__(self, path: str) -> AbstractEndpoint:
|
|
110
|
+
"""Get endpoint.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
path: Relative path of endpoint.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Endpoint.
|
|
117
|
+
|
|
118
|
+
"""
|
|
119
|
+
result = self.get_endpoint(path)
|
|
120
|
+
return result
|
|
121
|
+
|
|
122
|
+
def __truediv__(self, path: str) -> AbstractEndpoint:
|
|
123
|
+
"""Get endpoint.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
path: Relative path of endpoint.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
Endpoint.
|
|
130
|
+
|
|
131
|
+
"""
|
|
132
|
+
result = self.get_endpoint(path)
|
|
133
|
+
return result
|
|
134
|
+
|
|
135
|
+
def get_endpoint(self, path: str) -> AbstractEndpoint:
|
|
136
|
+
"""Get endpoint.
|
|
137
|
+
|
|
138
|
+
Arhs:
|
|
139
|
+
path: Relative path of endpoint.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
Endpoint.
|
|
143
|
+
|
|
144
|
+
"""
|
|
145
|
+
try:
|
|
146
|
+
matches = sorted(
|
|
147
|
+
(route, endpoint)
|
|
148
|
+
for route, endpoint in self._endpoints.items()
|
|
149
|
+
if route == path
|
|
150
|
+
)
|
|
151
|
+
_, endpoint = next(iter(matches))
|
|
152
|
+
|
|
153
|
+
except StopIteration:
|
|
154
|
+
if self._locked is True:
|
|
155
|
+
message = f"endpoint not found: {path}"
|
|
156
|
+
raise errors.EndpointNotFound(message)
|
|
157
|
+
|
|
158
|
+
endpoint = WebEndpoint
|
|
159
|
+
|
|
160
|
+
result = endpoint(self, path)
|
|
161
|
+
return result
|
|
162
|
+
|
|
163
|
+
def connect(self) -> None:
|
|
164
|
+
"""Start connection to web API."""
|
|
165
|
+
connection = self._engine.connect()
|
|
166
|
+
setattr(self, "_connection", connection)
|
|
167
|
+
connection.start()
|
|
168
|
+
|
|
169
|
+
def close(self) -> None:
|
|
170
|
+
"""Close connection to web API."""
|
|
171
|
+
if self.connection is not None:
|
|
172
|
+
self.connection.close()
|
|
173
|
+
delattr(self, "_connection")
|
|
174
|
+
|
|
175
|
+
@final
|
|
176
|
+
def head(
|
|
177
|
+
self,
|
|
178
|
+
*,
|
|
179
|
+
headers: Optional[Dict[str, str]] = None,
|
|
180
|
+
params: Optional[Dict[str, Any]] = None,
|
|
181
|
+
**kwargs: Any,
|
|
182
|
+
) -> Optional[Response]:
|
|
183
|
+
"""Sends an HTTP HEAD request to the API.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
headers (optional): Request headers (overrides global headers).
|
|
187
|
+
params (optional): Request parameters (overrides global parameters).
|
|
188
|
+
**kwargs: Keyword arguments to include in request.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
Response object.
|
|
192
|
+
|
|
193
|
+
Raises:
|
|
194
|
+
ConnectionNotStarted: when connection not started.
|
|
195
|
+
|
|
196
|
+
.. _MDN Web Docs:
|
|
197
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD
|
|
198
|
+
|
|
199
|
+
"""
|
|
200
|
+
if self.connection is None:
|
|
201
|
+
message = "connection not started before making HEAD request"
|
|
202
|
+
raise errors.ConnectionNotStarted(message)
|
|
203
|
+
|
|
204
|
+
response = self.connection.head(
|
|
205
|
+
headers=headers,
|
|
206
|
+
params=params,
|
|
207
|
+
**kwargs,
|
|
208
|
+
)
|
|
209
|
+
return response
|
|
210
|
+
|
|
211
|
+
@final
|
|
212
|
+
def get(
|
|
213
|
+
self,
|
|
214
|
+
*,
|
|
215
|
+
headers: Optional[Dict[str, str]] = None,
|
|
216
|
+
params: Optional[Dict[str, Any]] = None,
|
|
217
|
+
**kwargs: Any,
|
|
218
|
+
) -> Optional[Response]:
|
|
219
|
+
"""Sends an HTTP GET request to the API.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
headers (optional): Request headers (overrides global headers).
|
|
223
|
+
params (optional): Request parameters (overrides global parameters).
|
|
224
|
+
**kwargs: Keyword arguments to include in request.
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
Response object.
|
|
228
|
+
|
|
229
|
+
Raises:
|
|
230
|
+
ConnectionNotStarted: when connection not started.
|
|
231
|
+
|
|
232
|
+
.. _MDN Web Docs:
|
|
233
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET
|
|
234
|
+
|
|
235
|
+
"""
|
|
236
|
+
if self.connection is None:
|
|
237
|
+
message = "connection not started before making GET request"
|
|
238
|
+
raise errors.ConnectionNotStarted(message)
|
|
239
|
+
|
|
240
|
+
response = self.connection.get(
|
|
241
|
+
headers=headers,
|
|
242
|
+
params=params,
|
|
243
|
+
**kwargs,
|
|
244
|
+
)
|
|
245
|
+
return response
|
|
246
|
+
|
|
247
|
+
@final
|
|
248
|
+
def post(
|
|
249
|
+
self,
|
|
250
|
+
*,
|
|
251
|
+
headers: Optional[Dict[str, str]] = None,
|
|
252
|
+
params: Optional[Dict[str, Any]] = None,
|
|
253
|
+
**kwargs: Any,
|
|
254
|
+
) -> Optional[Response]:
|
|
255
|
+
"""Sends an HTTP POST request to the API.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
headers (optional): Request headers (overrides global headers).
|
|
259
|
+
params (optional): Request parameters (overrides global parameters).
|
|
260
|
+
**kwargs: Keyword arguments to include in request.
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
Response object.
|
|
264
|
+
|
|
265
|
+
Raises:
|
|
266
|
+
ConnectionNotStarted: when connection not started.
|
|
267
|
+
|
|
268
|
+
.. _MDN Web Docs:
|
|
269
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST
|
|
270
|
+
|
|
271
|
+
"""
|
|
272
|
+
if self.connection is None:
|
|
273
|
+
message = "connection not started before making POST request"
|
|
274
|
+
raise errors.ConnectionNotStarted(message)
|
|
275
|
+
|
|
276
|
+
response = self.connection.post(
|
|
277
|
+
headers=headers,
|
|
278
|
+
params=params,
|
|
279
|
+
**kwargs,
|
|
280
|
+
)
|
|
281
|
+
return response
|
|
282
|
+
|
|
283
|
+
@final
|
|
284
|
+
def put(
|
|
285
|
+
self,
|
|
286
|
+
*,
|
|
287
|
+
headers: Optional[Dict[str, str]] = None,
|
|
288
|
+
params: Optional[Dict[str, Any]] = None,
|
|
289
|
+
**kwargs: Any,
|
|
290
|
+
) -> Optional[Response]:
|
|
291
|
+
"""Sends an HTTP PUT request to the API.
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
headers (optional): Request headers (overrides global headers).
|
|
295
|
+
params (optional): Request parameters (overrides global parameters).
|
|
296
|
+
**kwargs: Keyword arguments to include in request.
|
|
297
|
+
|
|
298
|
+
Returns:
|
|
299
|
+
Response object.
|
|
300
|
+
|
|
301
|
+
Raises:
|
|
302
|
+
ConnectionNotStarted: when connection not started.
|
|
303
|
+
|
|
304
|
+
.. _MDN Web Docs:
|
|
305
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT
|
|
306
|
+
|
|
307
|
+
"""
|
|
308
|
+
if self.connection is None:
|
|
309
|
+
message = "connection not started before making PUT request"
|
|
310
|
+
raise errors.ConnectionNotStarted(message)
|
|
311
|
+
|
|
312
|
+
response = self.connection.put(
|
|
313
|
+
headers=headers,
|
|
314
|
+
params=params,
|
|
315
|
+
**kwargs,
|
|
316
|
+
)
|
|
317
|
+
return response
|
|
318
|
+
|
|
319
|
+
@final
|
|
320
|
+
def patch(
|
|
321
|
+
self,
|
|
322
|
+
*,
|
|
323
|
+
headers: Optional[Dict[str, str]] = None,
|
|
324
|
+
params: Optional[Dict[str, Any]] = None,
|
|
325
|
+
**kwargs: Any,
|
|
326
|
+
) -> Optional[Response]:
|
|
327
|
+
"""Sends an HTTP PATCH request to the API.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
headers (optional): Request headers (overrides global headers).
|
|
331
|
+
params (optional): Request parameters (overrides global parameters).
|
|
332
|
+
**kwargs: Keyword arguments to include in request.
|
|
333
|
+
|
|
334
|
+
Returns:
|
|
335
|
+
Response object.
|
|
336
|
+
|
|
337
|
+
Raises:
|
|
338
|
+
ConnectionNotStarted: when connection not started.
|
|
339
|
+
|
|
340
|
+
.. _MDN Web Docs:
|
|
341
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH
|
|
342
|
+
|
|
343
|
+
"""
|
|
344
|
+
if self.connection is None:
|
|
345
|
+
message = "connection not started before making PATCH request"
|
|
346
|
+
raise errors.ConnectionNotStarted(message)
|
|
347
|
+
|
|
348
|
+
response = self.connection.patch(
|
|
349
|
+
headers=headers,
|
|
350
|
+
params=params,
|
|
351
|
+
**kwargs,
|
|
352
|
+
)
|
|
353
|
+
return response
|
|
354
|
+
|
|
355
|
+
@final
|
|
356
|
+
def delete(
|
|
357
|
+
self,
|
|
358
|
+
*,
|
|
359
|
+
headers: Optional[Dict[str, str]] = None,
|
|
360
|
+
params: Optional[Dict[str, Any]] = None,
|
|
361
|
+
**kwargs: Any,
|
|
362
|
+
) -> Optional[Response]:
|
|
363
|
+
"""Sends an HTTP DELETE request to the API.
|
|
364
|
+
|
|
365
|
+
Args:
|
|
366
|
+
headers (optional): Request headers (overrides global headers).
|
|
367
|
+
params (optional): Request parameters (overrides global parameters).
|
|
368
|
+
**kwargs: Keyword arguments to include in request.
|
|
369
|
+
|
|
370
|
+
Returns:
|
|
371
|
+
Response object.
|
|
372
|
+
|
|
373
|
+
Raises:
|
|
374
|
+
ConnectionNotStarted: when connection not started.
|
|
375
|
+
|
|
376
|
+
.. _MDN Web Docs:
|
|
377
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE
|
|
378
|
+
|
|
379
|
+
"""
|
|
380
|
+
if self.connection is None:
|
|
381
|
+
message = "connection not started before making DELETE request"
|
|
382
|
+
raise errors.ConnectionNotStarted(message)
|
|
383
|
+
|
|
384
|
+
response = self.connection.delete(
|
|
385
|
+
headers=headers,
|
|
386
|
+
params=params,
|
|
387
|
+
**kwargs,
|
|
388
|
+
)
|
|
389
|
+
return response
|
|
390
|
+
|
|
391
|
+
@final
|
|
392
|
+
def options(
|
|
393
|
+
self,
|
|
394
|
+
*,
|
|
395
|
+
headers: Optional[Dict[str, str]] = None,
|
|
396
|
+
params: Optional[Dict[str, Any]] = None,
|
|
397
|
+
**kwargs: Any,
|
|
398
|
+
) -> Optional[Response]:
|
|
399
|
+
"""Sends an HTTP OPTIONS request to the API.
|
|
400
|
+
|
|
401
|
+
Args:
|
|
402
|
+
headers (optional): Request headers (overrides global headers).
|
|
403
|
+
params (optional): Request parameters (overrides global parameters).
|
|
404
|
+
**kwargs: Keyword arguments to include in request.
|
|
405
|
+
|
|
406
|
+
Returns:
|
|
407
|
+
Response object.
|
|
408
|
+
|
|
409
|
+
Raises:
|
|
410
|
+
ConnectionNotStarted: when connection not started.
|
|
411
|
+
|
|
412
|
+
.. _MDN Web Docs:
|
|
413
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
|
|
414
|
+
|
|
415
|
+
"""
|
|
416
|
+
if self.connection is None:
|
|
417
|
+
message = "connection not started before making OPTIONS request"
|
|
418
|
+
raise errors.ConnectionNotStarted(message)
|
|
419
|
+
|
|
420
|
+
response = self.connection.options(
|
|
421
|
+
headers=headers,
|
|
422
|
+
params=params,
|
|
423
|
+
**kwargs,
|
|
424
|
+
)
|
|
425
|
+
return response
|
|
426
|
+
|
|
427
|
+
@final
|
|
428
|
+
def trace(
|
|
429
|
+
self,
|
|
430
|
+
*,
|
|
431
|
+
headers: Optional[Dict[str, str]] = None,
|
|
432
|
+
params: Optional[Dict[str, Any]] = None,
|
|
433
|
+
**kwargs: Any,
|
|
434
|
+
) -> Optional[Response]:
|
|
435
|
+
"""Sends an HTTP TRACE request to the API.
|
|
436
|
+
|
|
437
|
+
Args:
|
|
438
|
+
headers (optional): Request headers (overrides global headers).
|
|
439
|
+
params (optional): Request parameters (overrides global parameters).
|
|
440
|
+
**kwargs: Keyword arguments to include in request.
|
|
441
|
+
|
|
442
|
+
Returns:
|
|
443
|
+
Response object.
|
|
444
|
+
|
|
445
|
+
Raises:
|
|
446
|
+
ConnectionNotStarted: when connection not started.
|
|
447
|
+
|
|
448
|
+
.. _MDN Web Docs:
|
|
449
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/TRACE
|
|
450
|
+
|
|
451
|
+
"""
|
|
452
|
+
if self.connection is None:
|
|
453
|
+
message = "connection not started before making TRACE request"
|
|
454
|
+
raise errors.ConnectionNotStarted(message)
|
|
455
|
+
|
|
456
|
+
response = self.connection.trace(
|
|
457
|
+
headers=headers,
|
|
458
|
+
params=params,
|
|
459
|
+
**kwargs,
|
|
460
|
+
)
|
|
461
|
+
return response
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# src/apytizer/connections/abstract_connection.py
|
|
3
|
+
"""Abstract Connection Class.
|
|
4
|
+
|
|
5
|
+
This module defines an abstract connection class which provides an
|
|
6
|
+
interface for subclasses to implement.
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Standard Library Imports
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
import abc
|
|
13
|
+
|
|
14
|
+
__all__ = ["AbstractConnection"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AbstractConnection(abc.ABC):
|
|
18
|
+
"""Represents an abstract connection."""
|
|
19
|
+
|
|
20
|
+
@abc.abstractmethod
|
|
21
|
+
def start(self) -> None:
|
|
22
|
+
"""Start connection."""
|
|
23
|
+
raise NotImplementedError
|
|
24
|
+
|
|
25
|
+
@abc.abstractmethod
|
|
26
|
+
def close(self) -> None:
|
|
27
|
+
"""Close connection."""
|
|
28
|
+
raise NotImplementedError
|