httpware 0.1.0__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.
- httpware/__init__.py +67 -0
- httpware/_internal/__init__.py +1 -0
- httpware/_internal/chain.py +39 -0
- httpware/_internal/import_checker.py +6 -0
- httpware/client.py +620 -0
- httpware/config.py +40 -0
- httpware/decoders/__init__.py +18 -0
- httpware/decoders/msgspec.py +32 -0
- httpware/decoders/pydantic.py +29 -0
- httpware/errors.py +194 -0
- httpware/middleware/__init__.py +89 -0
- httpware/py.typed +0 -0
- httpware/request.py +55 -0
- httpware/response.py +69 -0
- httpware/transports/__init__.py +27 -0
- httpware/transports/httpx2.py +180 -0
- httpware/transports/recorded.py +84 -0
- httpware-0.1.0.dist-info/METADATA +94 -0
- httpware-0.1.0.dist-info/RECORD +20 -0
- httpware-0.1.0.dist-info/WHEEL +4 -0
httpware/__init__.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""httpware — resilience-first async HTTP client framework for Python."""
|
|
2
|
+
|
|
3
|
+
from httpware.client import AsyncClient
|
|
4
|
+
from httpware.config import ClientConfig, Limits, Timeout
|
|
5
|
+
from httpware.decoders import ResponseDecoder
|
|
6
|
+
from httpware.decoders.pydantic import PydanticDecoder
|
|
7
|
+
from httpware.errors import (
|
|
8
|
+
STATUS_TO_EXCEPTION,
|
|
9
|
+
BadRequestError,
|
|
10
|
+
ClientError,
|
|
11
|
+
ClientStatusError,
|
|
12
|
+
ConflictError,
|
|
13
|
+
ForbiddenError,
|
|
14
|
+
InternalServerError,
|
|
15
|
+
NotFoundError,
|
|
16
|
+
RateLimitedError,
|
|
17
|
+
ServerStatusError,
|
|
18
|
+
ServiceUnavailableError,
|
|
19
|
+
StatusError,
|
|
20
|
+
TimeoutError, # noqa: A004
|
|
21
|
+
TransportError,
|
|
22
|
+
UnauthorizedError,
|
|
23
|
+
UnprocessableEntityError,
|
|
24
|
+
)
|
|
25
|
+
from httpware.middleware import Middleware, Next, after_response, before_request, on_error
|
|
26
|
+
from httpware.request import Request
|
|
27
|
+
from httpware.response import Response, StreamResponse
|
|
28
|
+
from httpware.transports import Transport
|
|
29
|
+
from httpware.transports.httpx2 import Httpx2Transport
|
|
30
|
+
from httpware.transports.recorded import RecordedTransport
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"STATUS_TO_EXCEPTION",
|
|
35
|
+
"AsyncClient",
|
|
36
|
+
"BadRequestError",
|
|
37
|
+
"ClientConfig",
|
|
38
|
+
"ClientError",
|
|
39
|
+
"ClientStatusError",
|
|
40
|
+
"ConflictError",
|
|
41
|
+
"ForbiddenError",
|
|
42
|
+
"Httpx2Transport",
|
|
43
|
+
"InternalServerError",
|
|
44
|
+
"Limits",
|
|
45
|
+
"Middleware",
|
|
46
|
+
"Next",
|
|
47
|
+
"NotFoundError",
|
|
48
|
+
"PydanticDecoder",
|
|
49
|
+
"RateLimitedError",
|
|
50
|
+
"RecordedTransport",
|
|
51
|
+
"Request",
|
|
52
|
+
"Response",
|
|
53
|
+
"ResponseDecoder",
|
|
54
|
+
"ServerStatusError",
|
|
55
|
+
"ServiceUnavailableError",
|
|
56
|
+
"StatusError",
|
|
57
|
+
"StreamResponse",
|
|
58
|
+
"Timeout",
|
|
59
|
+
"TimeoutError",
|
|
60
|
+
"Transport",
|
|
61
|
+
"TransportError",
|
|
62
|
+
"UnauthorizedError",
|
|
63
|
+
"UnprocessableEntityError",
|
|
64
|
+
"after_response",
|
|
65
|
+
"before_request",
|
|
66
|
+
"on_error",
|
|
67
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Private cross-module helpers (not part of the public API)."""
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Middleware chain composition — wires a middleware list against a Transport.
|
|
2
|
+
|
|
3
|
+
Private helper. AsyncClient calls `compose` at construction time and stores the
|
|
4
|
+
returned `Next` callable; per-request dispatch awaits that callable.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from collections.abc import Sequence
|
|
8
|
+
|
|
9
|
+
from httpware.middleware import Middleware, Next
|
|
10
|
+
from httpware.request import Request
|
|
11
|
+
from httpware.response import Response
|
|
12
|
+
from httpware.transports import Transport
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def compose(middlewares: Sequence[Middleware], transport: Transport) -> Next:
|
|
16
|
+
"""Fold `middlewares` into a single `Next` callable terminating at `transport`.
|
|
17
|
+
|
|
18
|
+
The outermost middleware in the input sequence is the first to receive the
|
|
19
|
+
request; its `next` argument forwards to the next middleware, and so on,
|
|
20
|
+
until the innermost middleware's `next` calls `transport.__call__`. An
|
|
21
|
+
empty sequence returns `transport.__call__` directly.
|
|
22
|
+
|
|
23
|
+
The returned callable is reusable across many requests; it captures
|
|
24
|
+
references to `middlewares` and `transport` by closure.
|
|
25
|
+
"""
|
|
26
|
+
chain: Next = transport.__call__
|
|
27
|
+
for middleware in reversed(middlewares):
|
|
28
|
+
chain = _wrap(middleware, chain)
|
|
29
|
+
return chain
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _wrap(middleware: Middleware, next_call: Next) -> Next:
|
|
33
|
+
async def _call(request: Request) -> Response:
|
|
34
|
+
return await middleware(request, next_call)
|
|
35
|
+
|
|
36
|
+
return _call
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
__all__ = ["compose"]
|