From 2a6a168ce0dc1d659b0b22d81ad36f7bed42f2d6 Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Fri, 27 Mar 2026 09:06:34 +0000 Subject: [PATCH 1/2] Remove getattr calls in async transport closing Add aclose to the AsyncTransport protocol and call it directly instead of using getattr to check for its existence. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/vws/async_query.py | 4 +--- src/vws/async_vumark_service.py | 4 +--- src/vws/async_vws.py | 4 +--- src/vws/transports.py | 4 ++++ 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/vws/async_query.py b/src/vws/async_query.py index c229569e..bebd3089 100644 --- a/src/vws/async_query.py +++ b/src/vws/async_query.py @@ -64,9 +64,7 @@ def __init__( async def aclose(self) -> None: """Close the underlying transport if it supports closing.""" - close = getattr(self._transport, "aclose", None) - if close is not None: - await close() + await self._transport.aclose() async def __aenter__(self) -> Self: """Enter the async context manager.""" diff --git a/src/vws/async_vumark_service.py b/src/vws/async_vumark_service.py index a104f49c..51c2ef34 100644 --- a/src/vws/async_vumark_service.py +++ b/src/vws/async_vumark_service.py @@ -50,9 +50,7 @@ def __init__( async def aclose(self) -> None: """Close the underlying transport if it supports closing.""" - close = getattr(self._transport, "aclose", None) - if close is not None: - await close() + await self._transport.aclose() async def __aenter__(self) -> Self: """Enter the async context manager.""" diff --git a/src/vws/async_vws.py b/src/vws/async_vws.py index feba724d..92675ac1 100644 --- a/src/vws/async_vws.py +++ b/src/vws/async_vws.py @@ -61,9 +61,7 @@ def __init__( async def aclose(self) -> None: """Close the underlying transport if it supports closing.""" - close = getattr(self._transport, "aclose", None) - if close is not None: - await close() + await self._transport.aclose() async def __aenter__(self) -> Self: """Enter the async context manager.""" diff --git a/src/vws/transports.py b/src/vws/transports.py index 6bf9ceb9..5b261883 100644 --- a/src/vws/transports.py +++ b/src/vws/transports.py @@ -167,6 +167,10 @@ class AsyncTransport(Protocol): and returns a ``Response``. """ + async def aclose(self) -> None: + """Close the transport and release resources.""" + ... # pylint: disable=unnecessary-ellipsis + def __call__( self, *, From 147f2efc890ec3ca75a2480a0a79441bf0b895a8 Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Fri, 27 Mar 2026 09:08:05 +0000 Subject: [PATCH 2/2] Remove tests for transports without aclose The AsyncTransport protocol now requires aclose, so these tests for transports lacking aclose are no longer applicable. Co-Authored-By: Claude Opus 4.6 (1M context) --- tests/test_transports.py | 65 ---------------------------------------- 1 file changed, 65 deletions(-) diff --git a/tests/test_transports.py b/tests/test_transports.py index b8a34f70..96518f16 100644 --- a/tests/test_transports.py +++ b/tests/test_transports.py @@ -6,7 +6,6 @@ import pytest import respx -from vws import AsyncCloudRecoService, AsyncVuMarkService, AsyncVWS from vws.response import Response from vws.transports import AsyncHTTPXTransport, HTTPXTransport @@ -140,67 +139,3 @@ async def test_context_manager() -> None: assert route.called assert isinstance(response, Response) assert response.status_code == HTTPStatus.OK - - -class _NoCloseTransport: - """A minimal async transport without ``aclose``.""" - - async def __call__( # pragma: no cover - self, - *, - method: str, - url: str, - headers: dict[str, str], - data: bytes, - request_timeout: float | tuple[float, float], - ) -> Response: - """Not implemented.""" - raise NotImplementedError - - -_DUMMY_KEY = "x" - - -class TestAsyncClientAclose: - """Tests for ``aclose`` on async clients with transports that - lack ``aclose``. - """ - - @staticmethod - @pytest.mark.asyncio - async def test_vws_aclose_no_transport_aclose() -> None: - """``AsyncVWS.aclose`` works when the transport has no - ``aclose``. - """ - client = AsyncVWS( - server_access_key=_DUMMY_KEY, - server_secret_key=_DUMMY_KEY, - transport=_NoCloseTransport(), - ) - await client.aclose() - - @staticmethod - @pytest.mark.asyncio - async def test_cloud_reco_aclose_no_transport_aclose() -> None: - """``AsyncCloudRecoService.aclose`` works when the transport - has no ``aclose``. - """ - client = AsyncCloudRecoService( - client_access_key=_DUMMY_KEY, - client_secret_key=_DUMMY_KEY, - transport=_NoCloseTransport(), - ) - await client.aclose() - - @staticmethod - @pytest.mark.asyncio - async def test_vumark_aclose_no_transport_aclose() -> None: - """``AsyncVuMarkService.aclose`` works when the transport - has no ``aclose``. - """ - client = AsyncVuMarkService( - server_access_key=_DUMMY_KEY, - server_secret_key=_DUMMY_KEY, - transport=_NoCloseTransport(), - ) - await client.aclose()