Skip to content

Commit eb72670

Browse files
Use asyncio for synchronization
1 parent e987df2 commit eb72670

11 files changed

+154
-163
lines changed

httpcore/_async/connection_pool.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from .._backends.base import SOCKET_OPTION, AsyncNetworkBackend
88
from .._exceptions import ConnectionNotAvailable, UnsupportedProtocol
99
from .._models import Origin, Request, Response
10-
from .._synchronization import AsyncEvent, AsyncShieldCancellation, AsyncThreadLock
10+
from .._synchronization import AsyncEvent, AsyncThreadLock, async_cancel_shield
1111
from .connection import AsyncHTTPConnection
1212
from .interfaces import AsyncConnectionInterface, AsyncRequestInterface
1313

@@ -299,11 +299,16 @@ def _assign_requests_to_connections(self) -> List[AsyncConnectionInterface]:
299299
return closing_connections
300300

301301
async def _close_connections(self, closing: List[AsyncConnectionInterface]) -> None:
302+
if not closing:
303+
return
304+
302305
# Close connections which have been removed from the pool.
303-
with AsyncShieldCancellation():
306+
async def close() -> None:
304307
for connection in closing:
305308
await connection.aclose()
306309

310+
await async_cancel_shield(close)
311+
307312
async def aclose(self) -> None:
308313
# Explicitly close the connection pool.
309314
# Clears all existing requests and connections.
@@ -369,9 +374,9 @@ async def __aiter__(self) -> AsyncIterator[bytes]:
369374
async def aclose(self) -> None:
370375
if not self._closed:
371376
self._closed = True
372-
with AsyncShieldCancellation():
373-
if hasattr(self._stream, "aclose"):
374-
await self._stream.aclose()
377+
378+
if hasattr(self._stream, "aclose"):
379+
await async_cancel_shield(self._stream.aclose)
375380

376381
with self._pool._optional_thread_lock:
377382
self._pool._requests.remove(self._pool_request)

httpcore/_async/http11.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
map_exceptions,
2626
)
2727
from .._models import Origin, Request, Response
28-
from .._synchronization import AsyncLock, AsyncShieldCancellation
28+
from .._synchronization import AsyncLock, async_cancel_shield
2929
from .._trace import Trace
3030
from .interfaces import AsyncConnectionInterface
3131

@@ -137,9 +137,8 @@ async def handle_async_request(self, request: Request) -> Response:
137137
},
138138
)
139139
except BaseException as exc:
140-
with AsyncShieldCancellation():
141-
async with Trace("response_closed", logger, request) as trace:
142-
await self._response_closed()
140+
async with Trace("response_closed", logger, request) as trace:
141+
await async_cancel_shield(self._response_closed)
143142
raise exc
144143

145144
# Sending the request...
@@ -344,8 +343,7 @@ async def __aiter__(self) -> AsyncIterator[bytes]:
344343
# If we get an exception while streaming the response,
345344
# we want to close the response (and possibly the connection)
346345
# before raising that exception.
347-
with AsyncShieldCancellation():
348-
await self.aclose()
346+
await async_cancel_shield(self.aclose)
349347
raise exc
350348

351349
async def aclose(self) -> None:

httpcore/_async/http2.py

+9-10
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
RemoteProtocolError,
1818
)
1919
from .._models import Origin, Request, Response
20-
from .._synchronization import AsyncLock, AsyncSemaphore, AsyncShieldCancellation
20+
from .._synchronization import AsyncLock, AsyncSemaphore, async_cancel_shield
2121
from .._trace import Trace
2222
from .interfaces import AsyncConnectionInterface
2323

@@ -108,8 +108,7 @@ async def handle_async_request(self, request: Request) -> Response:
108108
async with Trace("send_connection_init", logger, request, kwargs):
109109
await self._send_connection_init(**kwargs)
110110
except BaseException as exc:
111-
with AsyncShieldCancellation():
112-
await self.aclose()
111+
await async_cancel_shield(self.aclose)
113112
raise exc
114113

115114
self._sent_connection_init = True
@@ -160,11 +159,12 @@ async def handle_async_request(self, request: Request) -> Response:
160159
"stream_id": stream_id,
161160
},
162161
)
163-
except BaseException as exc: # noqa: PIE786
164-
with AsyncShieldCancellation():
165-
kwargs = {"stream_id": stream_id}
166-
async with Trace("response_closed", logger, request, kwargs):
167-
await self._response_closed(stream_id=stream_id)
162+
except BaseException as exc:
163+
kwargs = {"stream_id": stream_id}
164+
async with Trace("response_closed", logger, request, kwargs):
165+
await async_cancel_shield(
166+
lambda: self._response_closed(stream_id=stream_id)
167+
)
168168

169169
if isinstance(exc, h2.exceptions.ProtocolError):
170170
# One case where h2 can raise a protocol error is when a
@@ -577,8 +577,7 @@ async def __aiter__(self) -> typing.AsyncIterator[bytes]:
577577
# If we get an exception while streaming the response,
578578
# we want to close the response (and possibly the connection)
579579
# before raising that exception.
580-
with AsyncShieldCancellation():
581-
await self.aclose()
580+
await async_cancel_shield(self.aclose)
582581
raise exc
583582

584583
async def aclose(self) -> None:

httpcore/_backends/auto.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import typing
22
from typing import Optional
33

4-
from .._synchronization import current_async_library
4+
from .._synchronization import current_async_backend
55
from .base import SOCKET_OPTION, AsyncNetworkBackend, AsyncNetworkStream
66

77

88
class AutoBackend(AsyncNetworkBackend):
99
async def _init_backend(self) -> None:
1010
if not (hasattr(self, "_backend")):
11-
backend = current_async_library()
11+
backend = current_async_backend()
1212
if backend == "trio":
1313
from .trio import TrioBackend
1414

httpcore/_sync/connection_pool.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from .._backends.base import SOCKET_OPTION, NetworkBackend
88
from .._exceptions import ConnectionNotAvailable, UnsupportedProtocol
99
from .._models import Origin, Request, Response
10-
from .._synchronization import Event, ShieldCancellation, ThreadLock
10+
from .._synchronization import Event, ThreadLock, sync_cancel_shield
1111
from .connection import HTTPConnection
1212
from .interfaces import ConnectionInterface, RequestInterface
1313

@@ -299,11 +299,16 @@ def _assign_requests_to_connections(self) -> List[ConnectionInterface]:
299299
return closing_connections
300300

301301
def _close_connections(self, closing: List[ConnectionInterface]) -> None:
302+
if not closing:
303+
return
304+
302305
# Close connections which have been removed from the pool.
303-
with ShieldCancellation():
306+
def close() -> None:
304307
for connection in closing:
305308
connection.close()
306309

310+
sync_cancel_shield(close)
311+
307312
def close(self) -> None:
308313
# Explicitly close the connection pool.
309314
# Clears all existing requests and connections.
@@ -369,9 +374,9 @@ def __iter__(self) -> Iterator[bytes]:
369374
def close(self) -> None:
370375
if not self._closed:
371376
self._closed = True
372-
with ShieldCancellation():
373-
if hasattr(self._stream, "close"):
374-
self._stream.close()
377+
378+
if hasattr(self._stream, "close"):
379+
sync_cancel_shield(self._stream.close)
375380

376381
with self._pool._optional_thread_lock:
377382
self._pool._requests.remove(self._pool_request)

httpcore/_sync/http11.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
map_exceptions,
2626
)
2727
from .._models import Origin, Request, Response
28-
from .._synchronization import Lock, ShieldCancellation
28+
from .._synchronization import Lock, sync_cancel_shield
2929
from .._trace import Trace
3030
from .interfaces import ConnectionInterface
3131

@@ -137,9 +137,8 @@ def handle_request(self, request: Request) -> Response:
137137
},
138138
)
139139
except BaseException as exc:
140-
with ShieldCancellation():
141-
with Trace("response_closed", logger, request) as trace:
142-
self._response_closed()
140+
with Trace("response_closed", logger, request) as trace:
141+
sync_cancel_shield(self._response_closed)
143142
raise exc
144143

145144
# Sending the request...
@@ -344,8 +343,7 @@ def __iter__(self) -> Iterator[bytes]:
344343
# If we get an exception while streaming the response,
345344
# we want to close the response (and possibly the connection)
346345
# before raising that exception.
347-
with ShieldCancellation():
348-
self.close()
346+
sync_cancel_shield(self.close)
349347
raise exc
350348

351349
def close(self) -> None:

httpcore/_sync/http2.py

+9-10
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
RemoteProtocolError,
1818
)
1919
from .._models import Origin, Request, Response
20-
from .._synchronization import Lock, Semaphore, ShieldCancellation
20+
from .._synchronization import Lock, Semaphore, sync_cancel_shield
2121
from .._trace import Trace
2222
from .interfaces import ConnectionInterface
2323

@@ -108,8 +108,7 @@ def handle_request(self, request: Request) -> Response:
108108
with Trace("send_connection_init", logger, request, kwargs):
109109
self._send_connection_init(**kwargs)
110110
except BaseException as exc:
111-
with ShieldCancellation():
112-
self.close()
111+
sync_cancel_shield(self.close)
113112
raise exc
114113

115114
self._sent_connection_init = True
@@ -160,11 +159,12 @@ def handle_request(self, request: Request) -> Response:
160159
"stream_id": stream_id,
161160
},
162161
)
163-
except BaseException as exc: # noqa: PIE786
164-
with ShieldCancellation():
165-
kwargs = {"stream_id": stream_id}
166-
with Trace("response_closed", logger, request, kwargs):
167-
self._response_closed(stream_id=stream_id)
162+
except BaseException as exc:
163+
kwargs = {"stream_id": stream_id}
164+
with Trace("response_closed", logger, request, kwargs):
165+
sync_cancel_shield(
166+
lambda: self._response_closed(stream_id=stream_id)
167+
)
168168

169169
if isinstance(exc, h2.exceptions.ProtocolError):
170170
# One case where h2 can raise a protocol error is when a
@@ -577,8 +577,7 @@ def __iter__(self) -> typing.Iterator[bytes]:
577577
# If we get an exception while streaming the response,
578578
# we want to close the response (and possibly the connection)
579579
# before raising that exception.
580-
with ShieldCancellation():
581-
self.close()
580+
sync_cancel_shield(self.close)
582581
raise exc
583582

584583
def close(self) -> None:

0 commit comments

Comments
 (0)