From e447e65d1f737cbf842024df0afdb86bf81b75d0 Mon Sep 17 00:00:00 2001 From: CzBiX Date: Wed, 29 May 2024 00:38:46 +0800 Subject: [PATCH 1/2] Raise original exception in connection pool --- httpcore/_async/connection_pool.py | 4 ++-- httpcore/_sync/connection_pool.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/httpcore/_async/connection_pool.py b/httpcore/_async/connection_pool.py index 214dfc4b..6e38107f 100644 --- a/httpcore/_async/connection_pool.py +++ b/httpcore/_async/connection_pool.py @@ -213,7 +213,7 @@ async def handle_async_request(self, request: Request) -> Response: closing = self._assign_requests_to_connections() await self._close_connections(closing) - raise exc from None + raise # Return the response. Note that in this case we still have to manage # the point at which the response is closed. @@ -364,7 +364,7 @@ async def __aiter__(self) -> AsyncIterator[bytes]: yield part except BaseException as exc: await self.aclose() - raise exc from None + raise async def aclose(self) -> None: if not self._closed: diff --git a/httpcore/_sync/connection_pool.py b/httpcore/_sync/connection_pool.py index 01bec59e..32f08465 100644 --- a/httpcore/_sync/connection_pool.py +++ b/httpcore/_sync/connection_pool.py @@ -213,7 +213,7 @@ def handle_request(self, request: Request) -> Response: closing = self._assign_requests_to_connections() self._close_connections(closing) - raise exc from None + raise # Return the response. Note that in this case we still have to manage # the point at which the response is closed. @@ -364,7 +364,7 @@ def __iter__(self) -> Iterator[bytes]: yield part except BaseException as exc: self.close() - raise exc from None + raise def close(self) -> None: if not self._closed: From a8ef8d7a9adb0de84a5be5e5d588f64316af975d Mon Sep 17 00:00:00 2001 From: CzBiX Date: Wed, 29 May 2024 01:16:36 +0800 Subject: [PATCH 2/2] Add test case --- httpcore/_async/connection_pool.py | 4 ++-- httpcore/_sync/connection_pool.py | 4 ++-- tests/_async/test_connection_pool.py | 8 ++++++-- tests/_sync/test_connection_pool.py | 8 ++++++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/httpcore/_async/connection_pool.py b/httpcore/_async/connection_pool.py index 6e38107f..79dc0898 100644 --- a/httpcore/_async/connection_pool.py +++ b/httpcore/_async/connection_pool.py @@ -205,7 +205,7 @@ async def handle_async_request(self, request: Request) -> Response: else: break # pragma: nocover - except BaseException as exc: + except BaseException: with self._optional_thread_lock: # For any exception or cancellation we remove the request from # the queue, and then re-assign requests to connections. @@ -362,7 +362,7 @@ async def __aiter__(self) -> AsyncIterator[bytes]: try: async for part in self._stream: yield part - except BaseException as exc: + except BaseException: await self.aclose() raise diff --git a/httpcore/_sync/connection_pool.py b/httpcore/_sync/connection_pool.py index 32f08465..8edc3aae 100644 --- a/httpcore/_sync/connection_pool.py +++ b/httpcore/_sync/connection_pool.py @@ -205,7 +205,7 @@ def handle_request(self, request: Request) -> Response: else: break # pragma: nocover - except BaseException as exc: + except BaseException: with self._optional_thread_lock: # For any exception or cancellation we remove the request from # the queue, and then re-assign requests to connections. @@ -362,7 +362,7 @@ def __iter__(self) -> Iterator[bytes]: try: for part in self._stream: yield part - except BaseException as exc: + except BaseException: self.close() raise diff --git a/tests/_async/test_connection_pool.py b/tests/_async/test_connection_pool.py index 2fc27204..c9559a39 100644 --- a/tests/_async/test_connection_pool.py +++ b/tests/_async/test_connection_pool.py @@ -410,6 +410,8 @@ async def test_connection_pool_with_connect_exception(): be returned to the connection pool. """ + cause_exception = Exception("cause") + class FailedConnectBackend(httpcore.AsyncMockBackend): async def connect_tcp( self, @@ -421,7 +423,7 @@ async def connect_tcp( typing.Iterable[httpcore.SOCKET_OPTION] ] = None, ) -> httpcore.AsyncNetworkStream: - raise httpcore.ConnectError("Could not connect") + raise httpcore.ConnectError("Could not connect") from cause_exception network_backend = FailedConnectBackend([]) @@ -432,11 +434,13 @@ async def trace(name, kwargs): async with httpcore.AsyncConnectionPool(network_backend=network_backend) as pool: # Sending an initial request, which once complete will not return to the pool. - with pytest.raises(Exception): + with pytest.raises(Exception) as exc_info: await pool.request( "GET", "https://example.com/", extensions={"trace": trace} ) + assert exc_info.value.__cause__ is cause_exception + info = [repr(c) for c in pool.connections] assert info == [] diff --git a/tests/_sync/test_connection_pool.py b/tests/_sync/test_connection_pool.py index ee303e5c..63aaecd3 100644 --- a/tests/_sync/test_connection_pool.py +++ b/tests/_sync/test_connection_pool.py @@ -410,6 +410,8 @@ def test_connection_pool_with_connect_exception(): be returned to the connection pool. """ + cause_exception = Exception("cause") + class FailedConnectBackend(httpcore.MockBackend): def connect_tcp( self, @@ -421,7 +423,7 @@ def connect_tcp( typing.Iterable[httpcore.SOCKET_OPTION] ] = None, ) -> httpcore.NetworkStream: - raise httpcore.ConnectError("Could not connect") + raise httpcore.ConnectError("Could not connect") from cause_exception network_backend = FailedConnectBackend([]) @@ -432,11 +434,13 @@ def trace(name, kwargs): with httpcore.ConnectionPool(network_backend=network_backend) as pool: # Sending an initial request, which once complete will not return to the pool. - with pytest.raises(Exception): + with pytest.raises(Exception) as exc_info: pool.request( "GET", "https://example.com/", extensions={"trace": trace} ) + assert exc_info.value.__cause__ is cause_exception + info = [repr(c) for c in pool.connections] assert info == []