Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions src/httpcore2/httpcore2/_backends/anyio.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
from .._exceptions import (
ConnectError,
ConnectTimeout,
ExceptionMapping,
ReadError,
ReadTimeout,
WriteError,
WriteTimeout,
map_exceptions,
map_timeout,
)
from .._utils import is_socket_readable
from .base import SOCKET_OPTION, AsyncNetworkBackend, AsyncNetworkStream
Expand All @@ -25,8 +27,8 @@ def __init__(self, stream: anyio.abc.ByteStream) -> None:
self._stream = stream

async def read(self, max_bytes: int, timeout: float | None = None) -> bytes:
exc_map: dict[type[Exception], type[Exception]] = {
TimeoutError: ReadTimeout,
exc_map: ExceptionMapping = {
TimeoutError: map_timeout(ReadTimeout),
anyio.BrokenResourceError: ReadError,
anyio.ClosedResourceError: ReadError,
anyio.EndOfStream: ReadError,
Expand All @@ -42,8 +44,8 @@ async def write(self, buffer: bytes, timeout: float | None = None) -> None:
if not buffer:
return

exc_map: dict[type[Exception], type[Exception]] = {
TimeoutError: WriteTimeout,
exc_map: ExceptionMapping = {
TimeoutError: map_timeout(WriteTimeout),
anyio.BrokenResourceError: WriteError,
anyio.ClosedResourceError: WriteError,
}
Expand All @@ -60,8 +62,8 @@ async def start_tls(
server_hostname: str | None = None,
timeout: float | None = None,
) -> AsyncNetworkStream:
exc_map: dict[type[Exception], type[Exception]] = {
TimeoutError: ConnectTimeout,
exc_map: ExceptionMapping = {
TimeoutError: map_timeout(ConnectTimeout),
anyio.BrokenResourceError: ConnectError,
anyio.EndOfStream: ConnectError,
ssl.SSLError: ConnectError,
Expand Down Expand Up @@ -107,8 +109,8 @@ async def connect_tcp(
) -> AsyncNetworkStream: # pragma: no cover
if socket_options is None:
socket_options = []
exc_map: dict[type[Exception], type[Exception]] = {
TimeoutError: ConnectTimeout,
exc_map: ExceptionMapping = {
TimeoutError: map_timeout(ConnectTimeout),
OSError: ConnectError,
anyio.BrokenResourceError: ConnectError,
}
Expand All @@ -132,8 +134,8 @@ async def connect_unix_socket(
) -> AsyncNetworkStream: # pragma: no cover
if socket_options is None:
socket_options = []
exc_map: dict[type[Exception], type[Exception]] = {
TimeoutError: ConnectTimeout,
exc_map: ExceptionMapping = {
TimeoutError: map_timeout(ConnectTimeout),
OSError: ConnectError,
anyio.BrokenResourceError: ConnectError,
}
Expand Down
11 changes: 6 additions & 5 deletions src/httpcore2/httpcore2/_backends/trio.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
WriteError,
WriteTimeout,
map_exceptions,
map_timeout,
)
from .base import SOCKET_OPTION, AsyncNetworkBackend, AsyncNetworkStream

Expand All @@ -25,7 +26,7 @@ def __init__(self, stream: trio.abc.Stream) -> None:
async def read(self, max_bytes: int, timeout: float | None = None) -> bytes:
timeout_or_inf = float("inf") if timeout is None else timeout
exc_map: ExceptionMapping = {
trio.TooSlowError: ReadTimeout,
trio.TooSlowError: map_timeout(ReadTimeout),
trio.BrokenResourceError: ReadError,
trio.ClosedResourceError: ReadError,
}
Expand All @@ -40,7 +41,7 @@ async def write(self, buffer: bytes, timeout: float | None = None) -> None:

timeout_or_inf = float("inf") if timeout is None else timeout
exc_map: ExceptionMapping = {
trio.TooSlowError: WriteTimeout,
trio.TooSlowError: map_timeout(WriteTimeout),
trio.BrokenResourceError: WriteError,
trio.ClosedResourceError: WriteError,
}
Expand All @@ -59,7 +60,7 @@ async def start_tls(
) -> AsyncNetworkStream:
timeout_or_inf = float("inf") if timeout is None else timeout
exc_map: ExceptionMapping = {
trio.TooSlowError: ConnectTimeout,
trio.TooSlowError: map_timeout(ConnectTimeout),
trio.BrokenResourceError: ConnectError,
}
ssl_stream = trio.SSLStream(
Expand Down Expand Up @@ -121,7 +122,7 @@ async def connect_tcp(
socket_options = [] # pragma: no cover
timeout_or_inf = float("inf") if timeout is None else timeout
exc_map: ExceptionMapping = {
trio.TooSlowError: ConnectTimeout,
trio.TooSlowError: map_timeout(ConnectTimeout),
trio.BrokenResourceError: ConnectError,
OSError: ConnectError,
}
Expand All @@ -142,7 +143,7 @@ async def connect_unix_socket(
socket_options = []
timeout_or_inf = float("inf") if timeout is None else timeout
exc_map: ExceptionMapping = {
trio.TooSlowError: ConnectTimeout,
trio.TooSlowError: map_timeout(ConnectTimeout),
trio.BrokenResourceError: ConnectError,
OSError: ConnectError,
}
Expand Down
9 changes: 8 additions & 1 deletion src/httpcore2/httpcore2/_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import typing
from collections.abc import Generator

ExceptionMapping = typing.Mapping[type[Exception], type[Exception]]
ExceptionMapping = typing.Mapping[type[Exception], typing.Callable[[Exception], Exception]]
Comment thread
Kludex marked this conversation as resolved.


@contextlib.contextmanager
Expand Down Expand Up @@ -82,3 +82,10 @@ class ReadError(NetworkError):

class WriteError(NetworkError):
pass


def map_timeout(exception_class: type[TimeoutException]) -> typing.Callable[[Exception], Exception]:
def factory(exc: Exception) -> Exception:
return exception_class(str(exc) or "timed out")

return factory
6 changes: 3 additions & 3 deletions tests/httpx2/test_timeouts.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ async def test_read_timeout(server: TestServer) -> None:
timeout = httpx2.Timeout(None, read=1e-6)

async with httpx2.AsyncClient(timeout=timeout) as client:
with pytest.raises(httpx2.ReadTimeout):
with pytest.raises(httpx2.ReadTimeout, match="timed out"):
await client.get(server.url.copy_with(path="/slow_response"))


Expand All @@ -24,7 +24,7 @@ async def test_write_timeout(server: TestServer) -> None:
timeout = httpx2.Timeout(None, write=1e-6)

async with httpx2.AsyncClient(timeout=timeout) as client:
with pytest.raises(httpx2.WriteTimeout):
with pytest.raises(httpx2.WriteTimeout, match="timed out"):
data = b"*" * 1024 * 1024 * 100
await client.put(server.url.copy_with(path="/slow_response"), content=data)

Expand All @@ -35,7 +35,7 @@ async def test_connect_timeout(server: TestServer) -> None:
timeout = httpx2.Timeout(None, connect=1e-6)

async with httpx2.AsyncClient(timeout=timeout) as client:
with pytest.raises(httpx2.ConnectTimeout):
with pytest.raises(httpx2.ConnectTimeout, match="timed out"):
# See https://stackoverflow.com/questions/100841/
await client.get("http://10.255.255.1/")

Expand Down
Loading