apytizer 0.0.1a0__py3-none-any.whl → 0.0.1b2__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 +460 -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.py +70 -12
- 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 +171 -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 +376 -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.1b2.dist-info/METADATA +41 -0
- apytizer-0.0.1b2.dist-info/RECORD +60 -0
- {apytizer-0.0.1a0.dist-info → apytizer-0.0.1b2.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/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.1b2.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# src/apytizer/endpoints/web_endpoint.py
|
|
3
|
+
"""Web Endpoint Class.
|
|
4
|
+
|
|
5
|
+
This module defines the web endpoint class implementation.
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# Standard Library Imports
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
from collections import ChainMap
|
|
12
|
+
import logging
|
|
13
|
+
from typing import Any
|
|
14
|
+
from typing import Collection
|
|
15
|
+
from typing import Dict
|
|
16
|
+
from typing import MutableMapping
|
|
17
|
+
from typing import Optional
|
|
18
|
+
from typing import Set
|
|
19
|
+
from typing import Union
|
|
20
|
+
from typing import TYPE_CHECKING
|
|
21
|
+
from urllib.parse import urljoin
|
|
22
|
+
|
|
23
|
+
# Third-Party Imports
|
|
24
|
+
from requests import Response
|
|
25
|
+
|
|
26
|
+
# Local Imports
|
|
27
|
+
from .abstract_endpoint import AbstractEndpoint
|
|
28
|
+
from ..connections import HttpConnection
|
|
29
|
+
from ..decorators import cache_response
|
|
30
|
+
from ..http_methods import HTTPMethod
|
|
31
|
+
from ..routes import Route
|
|
32
|
+
from .. import errors
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
from ..apis import WebAPI
|
|
36
|
+
|
|
37
|
+
__all__ = ["WebEndpoint"]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
log = logging.getLogger("apytizer")
|
|
41
|
+
|
|
42
|
+
# Define constants.
|
|
43
|
+
DEFAULT_METHODS = (
|
|
44
|
+
HTTPMethod.HEAD,
|
|
45
|
+
HTTPMethod.GET,
|
|
46
|
+
HTTPMethod.POST,
|
|
47
|
+
HTTPMethod.PUT,
|
|
48
|
+
HTTPMethod.PATCH,
|
|
49
|
+
HTTPMethod.DELETE,
|
|
50
|
+
HTTPMethod.OPTIONS,
|
|
51
|
+
HTTPMethod.TRACE,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class WebEndpoint(AbstractEndpoint):
|
|
56
|
+
"""Implements an endpoint for web APIs.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
__api: API instance.
|
|
60
|
+
path: Relative path to endpoint.
|
|
61
|
+
methods (optional): List of HTTP methods accepted by endpoint.
|
|
62
|
+
headers (optional): Headers to set globally for endpoint.
|
|
63
|
+
params (optional): Parameters to set globally for endpoint.
|
|
64
|
+
cache (optional): Mutable mapping for caching responses.
|
|
65
|
+
|
|
66
|
+
Attributes:
|
|
67
|
+
connection: Connection with which to make requests.
|
|
68
|
+
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
__slots__ = (
|
|
72
|
+
"_api",
|
|
73
|
+
"_path",
|
|
74
|
+
"_methods",
|
|
75
|
+
"_headers",
|
|
76
|
+
"_params",
|
|
77
|
+
"_cache",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def __init__(
|
|
81
|
+
self,
|
|
82
|
+
__api: "WebAPI",
|
|
83
|
+
/,
|
|
84
|
+
path: Union[int, Route, str],
|
|
85
|
+
*,
|
|
86
|
+
methods: Optional[Collection[HTTPMethod]] = DEFAULT_METHODS,
|
|
87
|
+
headers: Optional[Dict[str, str]] = None,
|
|
88
|
+
params: Optional[Dict[str, Any]] = None,
|
|
89
|
+
cache: Optional[MutableMapping[str, Any]] = None,
|
|
90
|
+
) -> None:
|
|
91
|
+
self._api = __api
|
|
92
|
+
self._path = str(path).strip("/")
|
|
93
|
+
self._methods: Set[HTTPMethod] = set(methods or [])
|
|
94
|
+
self._headers = ChainMap(headers or {})
|
|
95
|
+
self._params = ChainMap(params or {})
|
|
96
|
+
self._cache = cache
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def api(self) -> "WebAPI":
|
|
100
|
+
"""API."""
|
|
101
|
+
return self._api
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def connection(self) -> Optional[HttpConnection]:
|
|
105
|
+
"""Connection with which to make requests."""
|
|
106
|
+
return self._api.connection
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def path(self) -> str:
|
|
110
|
+
"""Endpoint path."""
|
|
111
|
+
return self._path
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def url(self) -> str:
|
|
115
|
+
"""Endpoint URL."""
|
|
116
|
+
result = urljoin(self.api.url, self.path)
|
|
117
|
+
return result
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def methods(self) -> Set[HTTPMethod]:
|
|
121
|
+
"""Endpoint methods."""
|
|
122
|
+
return self._methods
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def headers(self) -> ChainMap[str, str]:
|
|
126
|
+
"""Headers."""
|
|
127
|
+
return self._headers
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def params(self) -> ChainMap[str, Any]:
|
|
131
|
+
"""Parameters."""
|
|
132
|
+
return self._params
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def cache(self) -> Optional[MutableMapping[str, Any]]:
|
|
136
|
+
"""Cache."""
|
|
137
|
+
return self._cache
|
|
138
|
+
|
|
139
|
+
def __eq__(self, other: object) -> bool:
|
|
140
|
+
result = (
|
|
141
|
+
other.path.lower() == self.path.lower()
|
|
142
|
+
if isinstance(other, WebEndpoint)
|
|
143
|
+
else False
|
|
144
|
+
)
|
|
145
|
+
return result
|
|
146
|
+
|
|
147
|
+
def __hash__(self) -> int:
|
|
148
|
+
return hash(self.path)
|
|
149
|
+
|
|
150
|
+
def __repr__(self) -> str:
|
|
151
|
+
result = f"<{self.__class__.__name__!s} (path={self.path!s})>"
|
|
152
|
+
return result
|
|
153
|
+
|
|
154
|
+
def __str__(self) -> str:
|
|
155
|
+
return self.path
|
|
156
|
+
|
|
157
|
+
def __getitem__(self, path: str) -> WebEndpoint:
|
|
158
|
+
"""Get endpoint.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
path: Relative path of endpoint.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Endpoint.
|
|
165
|
+
|
|
166
|
+
"""
|
|
167
|
+
route = "/".join([self._path, path])
|
|
168
|
+
result = self._api[route]
|
|
169
|
+
return result
|
|
170
|
+
|
|
171
|
+
def __truediv__(self, path: str) -> WebEndpoint:
|
|
172
|
+
"""Get endpoint.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
path: Relative path of endpoint.
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
Endpoint.
|
|
179
|
+
|
|
180
|
+
"""
|
|
181
|
+
route = "/".join([self._path, path])
|
|
182
|
+
result = self._api[route]
|
|
183
|
+
return result
|
|
184
|
+
|
|
185
|
+
@cache_response
|
|
186
|
+
def head(
|
|
187
|
+
self,
|
|
188
|
+
*,
|
|
189
|
+
headers: Optional[Dict[str, str]] = None,
|
|
190
|
+
params: Optional[Dict[str, Any]] = None,
|
|
191
|
+
**kwargs: Any,
|
|
192
|
+
) -> Optional[Response]:
|
|
193
|
+
"""Sends an HTTP HEAD request to the endpoint.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
headers (optional): Request headers (overrides global headers).
|
|
197
|
+
params (optional): Request parameters (overrides global parameters).
|
|
198
|
+
**kwargs: Keyword arguments to include in request.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
Response object.
|
|
202
|
+
|
|
203
|
+
Raises:
|
|
204
|
+
ConnectionNotStarted: when connection not started.
|
|
205
|
+
MethodNotAllowed: when HTTP method not allowed on endpoint.
|
|
206
|
+
|
|
207
|
+
.. _MDN Web Docs:
|
|
208
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD
|
|
209
|
+
|
|
210
|
+
"""
|
|
211
|
+
if self.connection is None:
|
|
212
|
+
message = "connection not started before making HEAD request"
|
|
213
|
+
raise errors.ConnectionNotStarted(message)
|
|
214
|
+
|
|
215
|
+
if HTTPMethod.HEAD not in self.methods:
|
|
216
|
+
message = f"HEAD method not allowed at {self.path!s} endpoint"
|
|
217
|
+
raise errors.MethodNotAllowed(message)
|
|
218
|
+
|
|
219
|
+
response = self.connection.head(
|
|
220
|
+
self.path,
|
|
221
|
+
headers=self.headers.new_child(headers),
|
|
222
|
+
params=self.params.new_child(params),
|
|
223
|
+
**kwargs,
|
|
224
|
+
)
|
|
225
|
+
return response
|
|
226
|
+
|
|
227
|
+
@cache_response
|
|
228
|
+
def get(
|
|
229
|
+
self,
|
|
230
|
+
*,
|
|
231
|
+
headers: Optional[Dict[str, str]] = None,
|
|
232
|
+
params: Optional[Dict[str, Any]] = None,
|
|
233
|
+
**kwargs: Any,
|
|
234
|
+
) -> Optional[Response]:
|
|
235
|
+
"""Sends an HTTP GET request to the endpoint.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
headers (optional): Request headers (overrides global headers).
|
|
239
|
+
params (optional): Request parameters (overrides global parameters).
|
|
240
|
+
**kwargs: Keyword arguments to include in request.
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
Response object.
|
|
244
|
+
|
|
245
|
+
Raises:
|
|
246
|
+
ConnectionNotStarted: when connection not started.
|
|
247
|
+
MethodNotAllowed: when HTTP method not allowed on endpoint.
|
|
248
|
+
|
|
249
|
+
.. _MDN Web Docs:
|
|
250
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET
|
|
251
|
+
|
|
252
|
+
"""
|
|
253
|
+
if self.connection is None:
|
|
254
|
+
message = "connection not started before making GET request"
|
|
255
|
+
raise errors.ConnectionNotStarted(message)
|
|
256
|
+
|
|
257
|
+
if HTTPMethod.GET not in self.methods:
|
|
258
|
+
message = f"GET method not allowed at {self.path!s} endpoint"
|
|
259
|
+
raise errors.MethodNotAllowed(message)
|
|
260
|
+
|
|
261
|
+
response = self.connection.get(
|
|
262
|
+
self.path,
|
|
263
|
+
headers=self.headers.new_child(headers),
|
|
264
|
+
params=self.params.new_child(params),
|
|
265
|
+
**kwargs,
|
|
266
|
+
)
|
|
267
|
+
return response
|
|
268
|
+
|
|
269
|
+
@cache_response
|
|
270
|
+
def post(
|
|
271
|
+
self,
|
|
272
|
+
*,
|
|
273
|
+
headers: Optional[Dict[str, str]] = None,
|
|
274
|
+
params: Optional[Dict[str, Any]] = None,
|
|
275
|
+
**kwargs: Any,
|
|
276
|
+
) -> Optional[Response]:
|
|
277
|
+
"""Sends an HTTP POST request to the endpoint.
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
headers (optional): Request headers (overrides global headers).
|
|
281
|
+
params (optional): Request parameters (overrides global parameters).
|
|
282
|
+
**kwargs: Keyword arguments to include in request.
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
Response object.
|
|
286
|
+
|
|
287
|
+
Raises:
|
|
288
|
+
ConnectionNotStarted: when connection not started.
|
|
289
|
+
MethodNotAllowed: when HTTP method not allowed on endpoint.
|
|
290
|
+
|
|
291
|
+
.. _MDN Web Docs:
|
|
292
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST
|
|
293
|
+
|
|
294
|
+
"""
|
|
295
|
+
if self.connection is None:
|
|
296
|
+
message = "connection not started before making POST request"
|
|
297
|
+
raise errors.ConnectionNotStarted(message)
|
|
298
|
+
|
|
299
|
+
if HTTPMethod.POST not in self.methods:
|
|
300
|
+
message = f"POST method not allowed at {self.path!s} endpoint"
|
|
301
|
+
raise errors.MethodNotAllowed(message)
|
|
302
|
+
|
|
303
|
+
response = self.connection.post(
|
|
304
|
+
self.path,
|
|
305
|
+
headers=self.headers.new_child(headers),
|
|
306
|
+
params=self.params.new_child(params),
|
|
307
|
+
**kwargs,
|
|
308
|
+
)
|
|
309
|
+
return response
|
|
310
|
+
|
|
311
|
+
@cache_response
|
|
312
|
+
def put(
|
|
313
|
+
self,
|
|
314
|
+
*,
|
|
315
|
+
headers: Optional[Dict[str, str]] = None,
|
|
316
|
+
params: Optional[Dict[str, Any]] = None,
|
|
317
|
+
**kwargs: Any,
|
|
318
|
+
) -> Optional[Response]:
|
|
319
|
+
"""Sends an HTTP PUT request to the endpoint.
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
headers (optional): Request headers (overrides global headers).
|
|
323
|
+
params (optional): Request parameters (overrides global parameters).
|
|
324
|
+
**kwargs: Keyword arguments to include in request.
|
|
325
|
+
|
|
326
|
+
Returns:
|
|
327
|
+
Response object.
|
|
328
|
+
|
|
329
|
+
Raises:
|
|
330
|
+
ConnectionNotStarted: when connection not started.
|
|
331
|
+
MethodNotAllowed: when HTTP method not allowed on endpoint.
|
|
332
|
+
|
|
333
|
+
.. _MDN Web Docs:
|
|
334
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT
|
|
335
|
+
|
|
336
|
+
"""
|
|
337
|
+
if self.connection is None:
|
|
338
|
+
message = "connection not started before making PUT request"
|
|
339
|
+
raise errors.ConnectionNotStarted(message)
|
|
340
|
+
|
|
341
|
+
if HTTPMethod.PUT not in self.methods:
|
|
342
|
+
message = f"PUT method not allowed at {self.path!s} endpoint"
|
|
343
|
+
raise errors.MethodNotAllowed(message)
|
|
344
|
+
|
|
345
|
+
response = self.connection.put(
|
|
346
|
+
self.path,
|
|
347
|
+
headers=self.headers.new_child(headers),
|
|
348
|
+
params=self.params.new_child(params),
|
|
349
|
+
**kwargs,
|
|
350
|
+
)
|
|
351
|
+
return response
|
|
352
|
+
|
|
353
|
+
@cache_response
|
|
354
|
+
def patch(
|
|
355
|
+
self,
|
|
356
|
+
*,
|
|
357
|
+
headers: Optional[Dict[str, str]] = None,
|
|
358
|
+
params: Optional[Dict[str, Any]] = None,
|
|
359
|
+
**kwargs: Any,
|
|
360
|
+
) -> Optional[Response]:
|
|
361
|
+
"""Sends an HTTP PATCH request to the endpoint.
|
|
362
|
+
|
|
363
|
+
Args:
|
|
364
|
+
headers (optional): Request headers (overrides global headers).
|
|
365
|
+
params (optional): Request parameters (overrides global parameters).
|
|
366
|
+
**kwargs: Keyword arguments to include in request.
|
|
367
|
+
|
|
368
|
+
Returns:
|
|
369
|
+
Response object.
|
|
370
|
+
|
|
371
|
+
Raises:
|
|
372
|
+
ConnectionNotStarted: when connection not started.
|
|
373
|
+
MethodNotAllowed: when HTTP method not allowed on endpoint.
|
|
374
|
+
|
|
375
|
+
.. _MDN Web Docs:
|
|
376
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH
|
|
377
|
+
|
|
378
|
+
"""
|
|
379
|
+
if self.connection is None:
|
|
380
|
+
message = "connection not started before making PATCH request"
|
|
381
|
+
raise errors.ConnectionNotStarted(message)
|
|
382
|
+
|
|
383
|
+
if HTTPMethod.PATCH not in self.methods:
|
|
384
|
+
message = f"PATCH method not allowed at {self.path!s} endpoint"
|
|
385
|
+
raise errors.MethodNotAllowed(message)
|
|
386
|
+
|
|
387
|
+
response = self.connection.patch(
|
|
388
|
+
self.path,
|
|
389
|
+
headers=self.headers.new_child(headers),
|
|
390
|
+
params=self.params.new_child(params),
|
|
391
|
+
**kwargs,
|
|
392
|
+
)
|
|
393
|
+
return response
|
|
394
|
+
|
|
395
|
+
@cache_response
|
|
396
|
+
def delete(
|
|
397
|
+
self,
|
|
398
|
+
*,
|
|
399
|
+
headers: Optional[Dict[str, str]] = None,
|
|
400
|
+
params: Optional[Dict[str, Any]] = None,
|
|
401
|
+
**kwargs: Any,
|
|
402
|
+
) -> Optional[Response]:
|
|
403
|
+
"""Sends an HTTP DELETE request to the endpoint.
|
|
404
|
+
|
|
405
|
+
Args:
|
|
406
|
+
headers (optional): Request headers (overrides global headers).
|
|
407
|
+
params (optional): Request parameters (overrides global parameters).
|
|
408
|
+
**kwargs: Keyword arguments to include in request.
|
|
409
|
+
|
|
410
|
+
Returns:
|
|
411
|
+
Response object.
|
|
412
|
+
|
|
413
|
+
Raises:
|
|
414
|
+
ConnectionNotStarted: when connection not started.
|
|
415
|
+
MethodNotAllowed: when HTTP method not allowed on endpoint.
|
|
416
|
+
|
|
417
|
+
.. _MDN Web Docs:
|
|
418
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE
|
|
419
|
+
|
|
420
|
+
"""
|
|
421
|
+
if self.connection is None:
|
|
422
|
+
message = "connection not started before making DELETE request"
|
|
423
|
+
raise errors.ConnectionNotStarted(message)
|
|
424
|
+
|
|
425
|
+
if HTTPMethod.DELETE not in self.methods:
|
|
426
|
+
message = f"DELETE method not allowed at {self.path!s} endpoint"
|
|
427
|
+
raise errors.MethodNotAllowed(message)
|
|
428
|
+
|
|
429
|
+
response = self.connection.delete(
|
|
430
|
+
self.path,
|
|
431
|
+
headers=self.headers.new_child(headers),
|
|
432
|
+
params=self.params.new_child(params),
|
|
433
|
+
**kwargs,
|
|
434
|
+
)
|
|
435
|
+
return response
|
|
436
|
+
|
|
437
|
+
@cache_response
|
|
438
|
+
def options(
|
|
439
|
+
self,
|
|
440
|
+
*,
|
|
441
|
+
headers: Optional[Dict[str, str]] = None,
|
|
442
|
+
params: Optional[Dict[str, Any]] = None,
|
|
443
|
+
**kwargs: Any,
|
|
444
|
+
) -> Optional[Response]:
|
|
445
|
+
"""Sends an HTTP OPTIONS request to the endpoint.
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
headers (optional): Request headers (overrides global headers).
|
|
449
|
+
params (optional): Request parameters (overrides global parameters).
|
|
450
|
+
**kwargs: Keyword arguments to include in request.
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
Response object.
|
|
454
|
+
|
|
455
|
+
Raises:
|
|
456
|
+
ConnectionNotStarted: when connection not started.
|
|
457
|
+
MethodNotAllowed: when HTTP method not allowed on endpoint.
|
|
458
|
+
|
|
459
|
+
.. _MDN Web Docs:
|
|
460
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
|
|
461
|
+
|
|
462
|
+
"""
|
|
463
|
+
if self.connection is None:
|
|
464
|
+
message = "connection not started before making OPTIONS request"
|
|
465
|
+
raise errors.ConnectionNotStarted(message)
|
|
466
|
+
|
|
467
|
+
if HTTPMethod.OPTIONS not in self.methods:
|
|
468
|
+
message = f"OPTIONS method not allowed at {self.path!s} endpoint"
|
|
469
|
+
raise errors.MethodNotAllowed(message)
|
|
470
|
+
|
|
471
|
+
response = self.connection.options(
|
|
472
|
+
self.path,
|
|
473
|
+
headers=self.headers.new_child(headers),
|
|
474
|
+
params=self.params.new_child(params),
|
|
475
|
+
**kwargs,
|
|
476
|
+
)
|
|
477
|
+
return response
|
|
478
|
+
|
|
479
|
+
@cache_response
|
|
480
|
+
def trace(
|
|
481
|
+
self,
|
|
482
|
+
*,
|
|
483
|
+
headers: Optional[Dict[str, str]] = None,
|
|
484
|
+
params: Optional[Dict[str, Any]] = None,
|
|
485
|
+
**kwargs: Any,
|
|
486
|
+
) -> Optional[Response]:
|
|
487
|
+
"""Sends an HTTP TRACE request to the endpoint.
|
|
488
|
+
|
|
489
|
+
Args:
|
|
490
|
+
headers (optional): Request headers (overrides global headers).
|
|
491
|
+
params (optional): Request parameters (overrides global parameters).
|
|
492
|
+
**kwargs: Keyword arguments to include in request.
|
|
493
|
+
|
|
494
|
+
Returns:
|
|
495
|
+
Response object.
|
|
496
|
+
|
|
497
|
+
Raises:
|
|
498
|
+
ConnectionNotStarted: when connection not started.
|
|
499
|
+
MethodNotAllowed: when HTTP method not allowed on endpoint.
|
|
500
|
+
|
|
501
|
+
.. _MDN Web Docs:
|
|
502
|
+
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/TRACE
|
|
503
|
+
|
|
504
|
+
"""
|
|
505
|
+
if self.connection is None:
|
|
506
|
+
message = "connection not started before making TRACE request"
|
|
507
|
+
raise errors.ConnectionNotStarted(message)
|
|
508
|
+
|
|
509
|
+
if HTTPMethod.TRACE not in self.methods:
|
|
510
|
+
message = f"TRACE method not allowed at {self.path!s} endpoint"
|
|
511
|
+
raise errors.MethodNotAllowed(message)
|
|
512
|
+
|
|
513
|
+
response = self.connection.trace(
|
|
514
|
+
self.path,
|
|
515
|
+
headers=self.headers.new_child(headers),
|
|
516
|
+
params=self.params.new_child(params),
|
|
517
|
+
**kwargs,
|
|
518
|
+
)
|
|
519
|
+
return response
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# src/apytizer/engines/abstract_engine.py
|
|
3
|
+
"""Abstract Engine Class.
|
|
4
|
+
|
|
5
|
+
This module defines an abstract engine 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
|
+
from ..protocols import Protocol
|
|
18
|
+
|
|
19
|
+
__all__ = ["AbstractEngine"]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AbstractEngine(abc.ABC):
|
|
23
|
+
"""Represents an abstract engine."""
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
@abc.abstractmethod
|
|
27
|
+
def protocol(self) -> Optional[Protocol]:
|
|
28
|
+
"""Protocol."""
|
|
29
|
+
raise NotImplementedError
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
@abc.abstractmethod
|
|
33
|
+
def url(self) -> str:
|
|
34
|
+
"""Base URL."""
|
|
35
|
+
raise NotImplementedError
|
|
36
|
+
|
|
37
|
+
@abc.abstractmethod
|
|
38
|
+
def connect(self) -> AbstractConnection:
|
|
39
|
+
"""Establish connection.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Connection.
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
raise NotImplementedError
|