From 107729ec8b8a128eef92667756d2e945944a722b Mon Sep 17 00:00:00 2001 From: Miwory Date: Sun, 26 Oct 2025 14:24:58 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0=D1=89=D0=B0?= =?UTF-8?q?=D0=B5=D0=BC=D1=8B=D0=B5=20=D1=82=D0=B8=D0=BF=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- src/aiohttpx/__init__.py | 2 +- src/aiohttpx/client.py | 2 +- src/aiohttpx/responses/__init__.py | 2 +- src/aiohttpx/transports/aio.py | 31 ++++++++++++++------ src/aiohttpx/transports/cache.py | 16 ++++++----- src/aiohttpx/transports/rate_limiter.py | 4 +-- stubs/aiohttpx/__init__.pyi | 1 - stubs/aiohttpx/client.pyi | 33 ---------------------- stubs/aiohttpx/responses/__init__.pyi | 6 ---- stubs/aiohttpx/transports/__init__.pyi | 0 stubs/aiohttpx/transports/aio.pyi | 31 -------------------- stubs/aiohttpx/transports/cache.pyi | 26 ----------------- stubs/aiohttpx/transports/rate_limiter.pyi | 12 -------- 14 files changed, 38 insertions(+), 130 deletions(-) delete mode 100644 stubs/aiohttpx/__init__.pyi delete mode 100644 stubs/aiohttpx/client.pyi delete mode 100644 stubs/aiohttpx/responses/__init__.pyi delete mode 100644 stubs/aiohttpx/transports/__init__.pyi delete mode 100644 stubs/aiohttpx/transports/aio.pyi delete mode 100644 stubs/aiohttpx/transports/cache.pyi delete mode 100644 stubs/aiohttpx/transports/rate_limiter.pyi diff --git a/pyproject.toml b/pyproject.toml index 507f488..e5360a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "aiohttpx" -version = "0.1.0" +version = "0.2.0" description = "Custom HTTPX client with aiohttp transport, rate limiter and caching" readme = "README.md" authors = [ diff --git a/src/aiohttpx/__init__.py b/src/aiohttpx/__init__.py index fcdb636..c8a9404 100644 --- a/src/aiohttpx/__init__.py +++ b/src/aiohttpx/__init__.py @@ -1 +1 @@ -__version__: str = '0.1.0' +__version__: str = '0.2.0' diff --git a/src/aiohttpx/client.py b/src/aiohttpx/client.py index ab41313..ea7ab9b 100644 --- a/src/aiohttpx/client.py +++ b/src/aiohttpx/client.py @@ -33,7 +33,7 @@ class AioHTTPXClient(AsyncHTTPXClient): redis_url: str | None = None, key: str | None = None, limit: int | None = None, - ): + ) -> None: super().__init__( auth=auth, params=params, diff --git a/src/aiohttpx/responses/__init__.py b/src/aiohttpx/responses/__init__.py index 09807a5..eafa6ef 100644 --- a/src/aiohttpx/responses/__init__.py +++ b/src/aiohttpx/responses/__init__.py @@ -5,5 +5,5 @@ from orjson import loads class Response(HTTPXResponse): - def json(self, **kwargs: Any): + def json(self, **kwargs: Any) -> Any: return loads(self.content, **kwargs) diff --git a/src/aiohttpx/transports/aio.py b/src/aiohttpx/transports/aio.py index a597aa0..c72b7cd 100644 --- a/src/aiohttpx/transports/aio.py +++ b/src/aiohttpx/transports/aio.py @@ -1,7 +1,7 @@ import asyncio from logging import getLogger from types import TracebackType -from typing import Any +from typing import Any, Self import aiohttp import httpx @@ -32,12 +32,27 @@ class AiohttpTransport(httpx.AsyncBaseTransport): def __init__( self, session: aiohttp.ClientSession | None = None, - ): + ) -> None: self.logger = getLogger(__name__) self._session = session or aiohttp.ClientSession() self._closed = False - def map_aiohttp_exception(self, exc: Exception): + def map_aiohttp_exception( + self, exc: Exception + ) -> ( + httpx.ConnectError + | httpx.DecodingError + | httpx.HTTPStatusError + | httpx.InvalidURL + | httpx.NetworkError + | httpx.ProtocolError + | httpx.ProxyError + | httpx.ReadError + | httpx.RequestError + | httpx.TooManyRedirects + | httpx.TimeoutException + | httpx.HTTPError + ): for aiohttp_exc, httpx_exc in EXCEPTIONS.items(): if isinstance(exc, aiohttp_exc): return httpx_exc(message=str(exc)) # type: ignore @@ -47,7 +62,7 @@ class AiohttpTransport(httpx.AsyncBaseTransport): return httpx.HTTPError(f'Unknown error: {exc!s}') - async def __aenter__(self): + async def __aenter__(self) -> Self: await self._session.__aenter__() return self @@ -56,16 +71,16 @@ class AiohttpTransport(httpx.AsyncBaseTransport): exc_type: type[BaseException] | None = None, exc_value: BaseException | None = None, traceback: TracebackType | None = None, - ): + ) -> None: await self._session.__aexit__(exc_type, exc_value, traceback) self._closed = True - async def aclose(self): + async def aclose(self) -> None: if not self._closed: self._closed = True await self._session.close() - async def handle_async_request(self, request: httpx.Request): + async def handle_async_request(self, request: httpx.Request) -> Response: headers = dict(request.headers) method = request.method url = str(request.url) @@ -102,7 +117,7 @@ class AiohttpTransport(httpx.AsyncBaseTransport): async def make_request( self, method: str, url: str, headers: dict[str, Any], data: bytes - ): + ) -> Response: if self._closed: msg = 'Cannot make request: Transport session is closed' raise RuntimeError(msg) diff --git a/src/aiohttpx/transports/cache.py b/src/aiohttpx/transports/cache.py index 723ec01..e4d0172 100644 --- a/src/aiohttpx/transports/cache.py +++ b/src/aiohttpx/transports/cache.py @@ -7,7 +7,7 @@ from aiohttpx.responses import Response from aiohttpx.transports.rate_limiter import AsyncRateLimit, Redis -def generate_cache_key(request: Request): +def generate_cache_key(request: Request) -> str: request_data = { 'method': request.method, 'url': str(request.url), @@ -28,7 +28,7 @@ def cache_response( client.set(cache_key, serialized_response, ex=ttl) -def get_ttl_from_headers(headers: m.Headers): +def get_ttl_from_headers(headers: m.Headers) -> int | None: if 'X-Cache-TTL' in headers: try: return int(headers['X-Cache-TTL']) @@ -36,7 +36,9 @@ def get_ttl_from_headers(headers: m.Headers): return None -def get_cached_response(client: Redis[bytes], cache_key: str): +def get_cached_response( + client: Redis[bytes], cache_key: str +) -> Response | None: cached_data = client.get(cache_key) if cached_data: @@ -45,7 +47,7 @@ def get_cached_response(client: Redis[bytes], cache_key: str): return None -def serialize_response(response: Response | HTTPXResponse): +def serialize_response(response: Response | HTTPXResponse) -> bytes: response_data = { 'status_code': response.status_code, 'headers': dict(response.headers), @@ -55,7 +57,7 @@ def serialize_response(response: Response | HTTPXResponse): return dumps(response_data) -def deserialize_response(serialized_response: bytes): +def deserialize_response(serialized_response: bytes) -> Response: response_data = loads(serialized_response) return Response( @@ -68,7 +70,7 @@ def deserialize_response(serialized_response: bytes): class AsyncCacheTransport(AsyncRateLimit): def __init__( self, redis_url: str | None, key: str | None, limit: int | None - ): + ) -> None: if redis_url: self.client = Redis.from_url(redis_url) else: @@ -76,7 +78,7 @@ class AsyncCacheTransport(AsyncRateLimit): self.transport = AsyncRateLimit(self.client, key, limit) - async def handle_async_request(self, request: Request): + async def handle_async_request(self, request: Request) -> Response: if not self.client: return await self.transport.handle_async_request(request) diff --git a/src/aiohttpx/transports/rate_limiter.py b/src/aiohttpx/transports/rate_limiter.py index a93cf6a..20c2ebd 100644 --- a/src/aiohttpx/transports/rate_limiter.py +++ b/src/aiohttpx/transports/rate_limiter.py @@ -10,7 +10,7 @@ from aiohttpx.transports.aio import AiohttpTransport class AsyncRateLimit(AiohttpTransport): def __init__( self, redis: Redis[bytes] | None, key: str | None, limit: int | None - ): + ) -> None: self.transport = AiohttpTransport() self.client = redis self.key = key @@ -25,7 +25,7 @@ class AsyncRateLimit(AiohttpTransport): msg = 'Incorrectly configured for rate limiting' raise Exception(msg) - async def request_is_limited(self): + async def request_is_limited(self) -> bool: if self.client and self.key and self.limit: t: int = int(self.client.time()[0]) # type: ignore separation = round(60 / self.limit) diff --git a/stubs/aiohttpx/__init__.pyi b/stubs/aiohttpx/__init__.pyi deleted file mode 100644 index 8e393b4..0000000 --- a/stubs/aiohttpx/__init__.pyi +++ /dev/null @@ -1 +0,0 @@ -__version__: str = ... diff --git a/stubs/aiohttpx/client.pyi b/stubs/aiohttpx/client.pyi deleted file mode 100644 index e27767f..0000000 --- a/stubs/aiohttpx/client.pyi +++ /dev/null @@ -1,33 +0,0 @@ -from collections.abc import Callable, Mapping -from ssl import SSLContext -from typing import Any - -from httpx import URL, Limits -from httpx import AsyncClient as AsyncHTTPXClient -from httpx import _types as t # type: ignore - -class AioHTTPXClient(AsyncHTTPXClient): - def __init__( - self, - *, - auth: t.AuthTypes | None = ..., - params: t.QueryParamTypes | None = ..., - headers: t.HeaderTypes | None = ..., - cookies: t.CookieTypes | None = ..., - verify: SSLContext | str | bool = ..., - cert: t.CertTypes | None = ..., - proxy: t.ProxyTypes | None = ..., - timeout: t.TimeoutTypes = ..., - follow_redirects: bool = ..., - limits: Limits = ..., - max_redirects: int = ..., - event_hooks: Mapping[str, list[Callable[..., Any]]] | None = ..., - base_url: URL | str = ..., - trust_env: bool = ..., - default_encoding: str | Callable[[bytes], str] = ..., - redis_url: str | None = ..., - key: str | None = ..., - limit: int | None = ..., - ) -> None: ... - -__all__ = ['AioHTTPXClient'] diff --git a/stubs/aiohttpx/responses/__init__.pyi b/stubs/aiohttpx/responses/__init__.pyi deleted file mode 100644 index 3b4e625..0000000 --- a/stubs/aiohttpx/responses/__init__.pyi +++ /dev/null @@ -1,6 +0,0 @@ -from typing import Any - -from httpx import Response as HTTPXResponse - -class Response(HTTPXResponse): - def json(self, **kwargs: Any) -> Any: ... diff --git a/stubs/aiohttpx/transports/__init__.pyi b/stubs/aiohttpx/transports/__init__.pyi deleted file mode 100644 index e69de29..0000000 diff --git a/stubs/aiohttpx/transports/aio.pyi b/stubs/aiohttpx/transports/aio.pyi deleted file mode 100644 index bce6c12..0000000 --- a/stubs/aiohttpx/transports/aio.pyi +++ /dev/null @@ -1,31 +0,0 @@ -from types import TracebackType -from typing import Any, Self - -import aiohttp -import httpx - -from aiohttpx.responses import Response - -EXCEPTIONS = ... - -class AiohttpTransport(httpx.AsyncBaseTransport): - def __init__( - self, session: aiohttp.ClientSession | None = ... - ) -> None: ... - def map_aiohttp_exception( - self, exc: Exception - ) -> httpx.TimeoutException | httpx.HTTPError: ... - async def __aenter__(self) -> Self: ... - async def __aexit__( - self, - exc_type: type[BaseException] | None = ..., - exc_value: BaseException | None = ..., - traceback: TracebackType | None = ..., - ) -> None: ... - async def aclose(self) -> None: ... - async def handle_async_request( - self, request: httpx.Request - ) -> Response: ... - async def make_request( - self, method: str, url: str, headers: dict[str, Any], data: bytes - ) -> Response: ... diff --git a/stubs/aiohttpx/transports/cache.pyi b/stubs/aiohttpx/transports/cache.pyi deleted file mode 100644 index dfeaf36..0000000 --- a/stubs/aiohttpx/transports/cache.pyi +++ /dev/null @@ -1,26 +0,0 @@ -from httpx import Request -from httpx import Response as HTTPXResponse -from httpx import _models as m # type: ignore - -from aiohttpx.responses import Response -from aiohttpx.transports.rate_limiter import AsyncRateLimit, Redis - -def generate_cache_key(request: Request) -> str: ... -def cache_response( - client: Redis[bytes], - cache_key: str, - request: Request, - response: Response | HTTPXResponse, -) -> None: ... -def get_ttl_from_headers(headers: m.Headers) -> int | None: ... -def get_cached_response( - client: Redis[bytes], cache_key: str -) -> Response | None: ... -def serialize_response(response: Response | HTTPXResponse) -> bytes: ... -def deserialize_response(serialized_response: bytes) -> Response: ... - -class AsyncCacheTransport(AsyncRateLimit): - def __init__( - self, redis_url: str | None, key: str | None, limit: int | None - ) -> None: ... - async def handle_async_request(self, request: Request) -> Response: ... diff --git a/stubs/aiohttpx/transports/rate_limiter.pyi b/stubs/aiohttpx/transports/rate_limiter.pyi deleted file mode 100644 index 0b77a9f..0000000 --- a/stubs/aiohttpx/transports/rate_limiter.pyi +++ /dev/null @@ -1,12 +0,0 @@ -from httpx import Request -from redis import Redis - -from aiohttpx.responses import Response -from aiohttpx.transports.aio import AiohttpTransport - -class AsyncRateLimit(AiohttpTransport): - def __init__( - self, redis: Redis[bytes] | None, key: str | None, limit: int | None - ) -> None: ... - async def request_is_limited(self) -> bool: ... - async def handle_async_request(self, request: Request) -> Response: ...