Merge 09fc81a33c into b5addb64f0
This commit is contained in:
commit
0fd701e8c2
@ -26,8 +26,8 @@ client = httpx.Client(transport=transport)
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import typing
|
||||
from functools import cache
|
||||
from types import TracebackType
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
@ -68,9 +68,8 @@ SOCKET_OPTION = typing.Union[
|
||||
|
||||
__all__ = ["AsyncHTTPTransport", "HTTPTransport"]
|
||||
|
||||
HTTPCORE_EXC_MAP: dict[type[Exception], type[httpx.HTTPError]] = {}
|
||||
|
||||
|
||||
@cache
|
||||
def _load_httpcore_exceptions() -> dict[type[Exception], type[httpx.HTTPError]]:
|
||||
import httpcore
|
||||
|
||||
@ -92,30 +91,26 @@ def _load_httpcore_exceptions() -> dict[type[Exception], type[httpx.HTTPError]]:
|
||||
}
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def map_httpcore_exceptions() -> typing.Iterator[None]:
|
||||
global HTTPCORE_EXC_MAP
|
||||
if len(HTTPCORE_EXC_MAP) == 0:
|
||||
HTTPCORE_EXC_MAP = _load_httpcore_exceptions()
|
||||
try:
|
||||
yield
|
||||
except Exception as exc:
|
||||
mapped_exc = None
|
||||
@cache
|
||||
def _get_httpcore_exception_types() -> tuple[type[Exception], ...]:
|
||||
return tuple(_load_httpcore_exceptions())
|
||||
|
||||
for from_exc, to_exc in HTTPCORE_EXC_MAP.items():
|
||||
if not isinstance(exc, from_exc):
|
||||
continue
|
||||
# We want to map to the most specific exception we can find.
|
||||
# Eg if `exc` is an `httpcore.ReadTimeout`, we want to map to
|
||||
# `httpx.ReadTimeout`, not just `httpx.TimeoutException`.
|
||||
if mapped_exc is None or issubclass(to_exc, mapped_exc):
|
||||
mapped_exc = to_exc
|
||||
|
||||
if mapped_exc is None: # pragma: no cover
|
||||
raise
|
||||
def _map_httpcore_exception(exc: Exception) -> httpx.HTTPError:
|
||||
mapped_exc = None
|
||||
for from_exc, to_exc in _load_httpcore_exceptions().items():
|
||||
if not isinstance(exc, from_exc):
|
||||
continue
|
||||
# We want to map to the most specific exception we can find.
|
||||
# Eg if `exc` is an `httpcore.ReadTimeout`, we want to map to
|
||||
# `httpx.ReadTimeout`, not just `httpx.TimeoutException`.
|
||||
if mapped_exc is None or issubclass(to_exc, mapped_exc):
|
||||
mapped_exc = to_exc
|
||||
|
||||
message = str(exc)
|
||||
raise mapped_exc(message) from exc
|
||||
if mapped_exc is None: # pragma: no cover
|
||||
raise
|
||||
|
||||
return mapped_exc(str(exc))
|
||||
|
||||
|
||||
class ResponseStream(SyncByteStream):
|
||||
@ -123,9 +118,11 @@ class ResponseStream(SyncByteStream):
|
||||
self._httpcore_stream = httpcore_stream
|
||||
|
||||
def __iter__(self) -> typing.Iterator[bytes]:
|
||||
with map_httpcore_exceptions():
|
||||
try:
|
||||
for part in self._httpcore_stream:
|
||||
yield part
|
||||
except _get_httpcore_exception_types() as exc:
|
||||
raise _map_httpcore_exception(exc) from exc
|
||||
|
||||
def close(self) -> None:
|
||||
if hasattr(self._httpcore_stream, "close"):
|
||||
@ -224,8 +221,10 @@ class HTTPTransport(BaseTransport):
|
||||
exc_value: BaseException | None = None,
|
||||
traceback: TracebackType | None = None,
|
||||
) -> None:
|
||||
with map_httpcore_exceptions():
|
||||
try:
|
||||
self._pool.__exit__(exc_type, exc_value, traceback)
|
||||
except _get_httpcore_exception_types() as exc: # pragma: no cover
|
||||
raise _map_httpcore_exception(exc) from exc
|
||||
|
||||
def handle_request(
|
||||
self,
|
||||
@ -246,8 +245,10 @@ class HTTPTransport(BaseTransport):
|
||||
content=request.stream,
|
||||
extensions=request.extensions,
|
||||
)
|
||||
with map_httpcore_exceptions():
|
||||
try:
|
||||
resp = self._pool.handle_request(req)
|
||||
except _get_httpcore_exception_types() as exc:
|
||||
raise _map_httpcore_exception(exc) from exc
|
||||
|
||||
assert isinstance(resp.stream, typing.Iterable)
|
||||
|
||||
@ -267,9 +268,11 @@ class AsyncResponseStream(AsyncByteStream):
|
||||
self._httpcore_stream = httpcore_stream
|
||||
|
||||
async def __aiter__(self) -> typing.AsyncIterator[bytes]:
|
||||
with map_httpcore_exceptions():
|
||||
try:
|
||||
async for part in self._httpcore_stream:
|
||||
yield part
|
||||
except _get_httpcore_exception_types() as exc: # pragma: no cover
|
||||
raise _map_httpcore_exception(exc) from exc
|
||||
|
||||
async def aclose(self) -> None:
|
||||
if hasattr(self._httpcore_stream, "aclose"):
|
||||
@ -368,8 +371,10 @@ class AsyncHTTPTransport(AsyncBaseTransport):
|
||||
exc_value: BaseException | None = None,
|
||||
traceback: TracebackType | None = None,
|
||||
) -> None:
|
||||
with map_httpcore_exceptions():
|
||||
try:
|
||||
await self._pool.__aexit__(exc_type, exc_value, traceback)
|
||||
except _get_httpcore_exception_types() as exc: # pragma: no cover
|
||||
raise _map_httpcore_exception(exc) from exc
|
||||
|
||||
async def handle_async_request(
|
||||
self,
|
||||
@ -390,8 +395,10 @@ class AsyncHTTPTransport(AsyncBaseTransport):
|
||||
content=request.stream,
|
||||
extensions=request.extensions,
|
||||
)
|
||||
with map_httpcore_exceptions():
|
||||
try:
|
||||
resp = await self._pool.handle_async_request(req)
|
||||
except _get_httpcore_exception_types() as exc:
|
||||
raise _map_httpcore_exception(exc) from exc
|
||||
|
||||
assert isinstance(resp.stream, typing.AsyncIterable)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user