Skip to content
Closed
17 changes: 13 additions & 4 deletions httpcore/_async/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ def __init__(
async def handle_async_request(self, request: Request) -> Response:
if not self.can_handle_request(request.url.origin):
raise RuntimeError(
f"Attempted to send request to {request.url.origin} on connection to {self._origin}"
f"Attempted to send request to {request.url.origin}"
f" on connection to {self._origin}"
)

try:
Expand Down Expand Up @@ -118,7 +119,12 @@ async def _connect(self, request: Request) -> AsyncNetworkStream:
"timeout": timeout,
"socket_options": self._socket_options,
}
async with Trace("connect_tcp", logger, request, kwargs) as trace:
async with Trace(
"connect_tcp",
logger,
request,
kwargs,
) as trace:
stream = await self._network_backend.connect_tcp(**kwargs)
trace.return_value = stream
else:
Expand All @@ -128,10 +134,13 @@ async def _connect(self, request: Request) -> AsyncNetworkStream:
"socket_options": self._socket_options,
}
async with Trace(
"connect_unix_socket", logger, request, kwargs
"connect_unix_socket",
logger,
request,
kwargs,
) as trace:
stream = await self._network_backend.connect_unix_socket(
**kwargs
**kwargs,
)
trace.return_value = stream

Expand Down
32 changes: 22 additions & 10 deletions httpcore/_async/connection_pool.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import ssl
import sys
from types import TracebackType
from typing import AsyncIterable, AsyncIterator, Iterable, List, Optional, Type
from typing import ( # noqa: F811
AsyncIterable,
AsyncIterator,
Iterable,
List,
Optional,
Type,
)

from .._backends.auto import AutoBackend
from .._backends.base import SOCKET_OPTION, AsyncNetworkBackend
Expand All @@ -19,7 +26,8 @@ def __init__(self, request: Request) -> None:
self._connection_acquired = AsyncEvent()

def assign_to_connection(
self, connection: Optional[AsyncConnectionInterface]
self,
connection: Optional[AsyncConnectionInterface],
) -> None:
self.connection = connection
self._connection_acquired.set()
Expand Down Expand Up @@ -119,9 +127,10 @@ def __init__(
self._connections: List[AsyncConnectionInterface] = []
self._requests: List[AsyncPoolRequest] = []

# We only mutate the state of the connection pool within an 'optional_thread_lock'
# context. This holds a threading lock unless we're running in async mode,
# in which case it is a no-op.
# We only mutate the state of the connection pool
# within an 'optional_thread_lock' context.
# This holds a threading lock unless we're running in
# async mode, in which case it is a no-op.
self._optional_thread_lock = AsyncThreadLock()

def create_connection(self, origin: Origin) -> AsyncConnectionInterface:
Expand All @@ -148,9 +157,12 @@ def connections(self) -> List[AsyncConnectionInterface]:
```python
>>> pool.connections
[
<AsyncHTTPConnection ['https://example.com:443', HTTP/1.1, ACTIVE, Request Count: 6]>,
<AsyncHTTPConnection ['https://example.com:443', HTTP/1.1, IDLE, Request Count: 9]> ,
<AsyncHTTPConnection ['http://example.com:80', HTTP/1.1, IDLE, Request Count: 1]>,
<AsyncHTTPConnection ['https://example.com:443', HTTP/1.1, ACTIVE,
Request Count: 6]>,
<AsyncHTTPConnection ['https://example.com:443', HTTP/1.1, IDLE,
Request Count: 9]>,
<AsyncHTTPConnection ['http://example.com:80', HTTP/1.1, IDLE,
Request Count: 1]>,
]
```
"""
Expand All @@ -160,7 +172,7 @@ async def handle_async_request(self, request: Request) -> Response:
"""
Send an HTTP request, and return an HTTP response.

This is the core implementation that is called into by `.request()` or `.stream()`.
The core implementation that is called into by `.request()` or `.stream()`.
"""
scheme = request.url.scheme.decode()
if scheme == "":
Expand Down Expand Up @@ -194,7 +206,7 @@ async def handle_async_request(self, request: Request) -> Response:
try:
# Send the request on the assigned connection.
response = await connection.handle_async_request(
pool_request.request
pool_request.request,
)
except ConnectionNotAvailable:
# In some cases a connection may initially be available to
Expand Down
17 changes: 13 additions & 4 deletions httpcore/_async/http11.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ async def handle_async_request(self, request: Request) -> Response:
kwargs = {"request": request}
try:
async with Trace(
"send_request_headers", logger, request, kwargs
"send_request_headers",
logger,
request,
kwargs,
) as trace:
await self._send_request_headers(**kwargs)
async with Trace("send_request_body", logger, request, kwargs) as trace:
Expand All @@ -102,7 +105,10 @@ async def handle_async_request(self, request: Request) -> Response:
pass

async with Trace(
"receive_response_headers", logger, request, kwargs
"receive_response_headers",
logger,
request,
kwargs,
) as trace:
(
http_version,
Expand Down Expand Up @@ -168,7 +174,9 @@ async def _send_request_body(self, request: Request) -> None:
await self._send_event(h11.EndOfMessage(), timeout=timeout)

async def _send_event(
self, event: h11.Event, timeout: Optional[float] = None
self,
event: h11.Event,
timeout: Optional[float] = None,
) -> None:
bytes_to_send = self._h11_state.send(event)
if bytes_to_send is not None:
Expand Down Expand Up @@ -222,7 +230,8 @@ async def _receive_event(

if event is h11.NEED_DATA:
data = await self._network_stream.read(
self.READ_NUM_BYTES, timeout=timeout
self.READ_NUM_BYTES,
timeout=timeout,
)

# If we feed this case through h11 we'll raise an exception like:
Expand Down
25 changes: 17 additions & 8 deletions httpcore/_async/http2.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,10 @@ async def handle_async_request(self, request: Request) -> Response:
async with Trace("send_request_body", logger, request, kwargs):
await self._send_request_body(request=request, stream_id=stream_id)
async with Trace(
"receive_response_headers", logger, request, kwargs
"receive_response_headers",
logger,
request,
kwargs,
) as trace:
status, headers = await self._receive_response(
request=request, stream_id=stream_id
Expand Down Expand Up @@ -261,7 +264,10 @@ async def _send_request_body(self, request: Request, stream_id: int) -> None:
await self._send_end_stream(request, stream_id)

async def _send_stream_data(
self, request: Request, stream_id: int, data: bytes
self,
request: Request,
stream_id: int,
data: bytes,
) -> None:
"""
Send a single chunk of data in one or more data frames.
Expand Down Expand Up @@ -362,7 +368,9 @@ async def _receive_events(
for event in events:
if isinstance(event, h2.events.RemoteSettingsChanged):
async with Trace(
"receive_remote_settings", logger, request
"receive_remote_settings",
logger,
request,
) as trace:
await self._receive_remote_settings_change(event)
trace.return_value = event
Expand Down Expand Up @@ -426,7 +434,8 @@ async def aclose(self) -> None:
# Wrappers around network read/write operations...

async def _read_incoming_data(
self, request: Request
self,
request: Request,
) -> typing.List[h2.events.Event]:
timeouts = request.extensions.get("timeout", {})
timeout = timeouts.get("read", None)
Expand Down Expand Up @@ -470,10 +479,10 @@ async def _write_outgoing_data(self, request: Request) -> None:
except Exception as exc: # pragma: nocover
# If we get a network error we should:
#
# 1. Save the exception and just raise it immediately on any future write.
# (For example, this means that a single write timeout or disconnect will
# immediately close all pending streams. Without requiring multiple
# sequential timeouts.)
# 1. Save the exception and just raise it immediately on any
# future write. (For example, this means that a single write timeout
# or disconnect will immediately close all pending streams,
# without requiring multiple sequential timeouts.)
# 2. Mark the connection as errored, so that we don't accept any other
# incoming requests.
self._write_exception = exc
Expand Down
5 changes: 3 additions & 2 deletions httpcore/_async/http_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ def __init__(
ssl_context: An SSL context to use for verifying connections.
If not specified, the default `httpcore.default_ssl_context()`
will be used.
proxy_ssl_context: The same as `ssl_context`, but for a proxy server rather than a remote origin.
proxy_ssl_context: The same as `ssl_context`, but for a proxy server
rather than a remote origin.
max_connections: The maximum number of concurrent HTTP connections that
the pool should allow. Any attempt to send a request on a pool that
would exceed this amount will block until a connection is available.
Expand Down Expand Up @@ -287,7 +288,7 @@ async def handle_async_request(self, request: Request) -> Response:
extensions=request.extensions,
)
connect_response = await self._connection.handle_async_request(
connect_request
connect_request,
)

if connect_response.status < 200 or connect_response.status > 299:
Expand Down
3 changes: 2 additions & 1 deletion httpcore/_backends/trio.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ async def start_tls(

def get_extra_info(self, info: str) -> typing.Any:
if info == "ssl_object" and isinstance(self._stream, trio.SSLStream):
# Type checkers cannot see `_ssl_object` attribute because trio._ssl.SSLStream uses __getattr__/__setattr__.
# Type checkers cannot see `_ssl_object` attribute
# because `trio._ssl.SSLStream` uses `__getattr__`/`__setattr__`.
# Tracked at https://github.com/python-trio/trio/issues/542
return self._stream._ssl_object # type: ignore[attr-defined]
if info == "client_addr":
Expand Down
17 changes: 13 additions & 4 deletions httpcore/_sync/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ def __init__(
def handle_request(self, request: Request) -> Response:
if not self.can_handle_request(request.url.origin):
raise RuntimeError(
f"Attempted to send request to {request.url.origin} on connection to {self._origin}"
f"Attempted to send request to {request.url.origin}"
f" on connection to {self._origin}"
)

try:
Expand Down Expand Up @@ -118,7 +119,12 @@ def _connect(self, request: Request) -> NetworkStream:
"timeout": timeout,
"socket_options": self._socket_options,
}
with Trace("connect_tcp", logger, request, kwargs) as trace:
with Trace(
"connect_tcp",
logger,
request,
kwargs,
) as trace:
stream = self._network_backend.connect_tcp(**kwargs)
trace.return_value = stream
else:
Expand All @@ -128,10 +134,13 @@ def _connect(self, request: Request) -> NetworkStream:
"socket_options": self._socket_options,
}
with Trace(
"connect_unix_socket", logger, request, kwargs
"connect_unix_socket",
logger,
request,
kwargs,
) as trace:
stream = self._network_backend.connect_unix_socket(
**kwargs
**kwargs,
)
trace.return_value = stream

Expand Down
32 changes: 22 additions & 10 deletions httpcore/_sync/connection_pool.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import ssl
import sys
from types import TracebackType
from typing import Iterable, Iterator, Iterable, List, Optional, Type
from typing import ( # noqa: F811
Iterable,
Iterator,
Iterable,
List,
Optional,
Type,
)

from .._backends.sync import SyncBackend
from .._backends.base import SOCKET_OPTION, NetworkBackend
Expand All @@ -19,7 +26,8 @@ def __init__(self, request: Request) -> None:
self._connection_acquired = Event()

def assign_to_connection(
self, connection: Optional[ConnectionInterface]
self,
connection: Optional[ConnectionInterface],
) -> None:
self.connection = connection
self._connection_acquired.set()
Expand Down Expand Up @@ -119,9 +127,10 @@ def __init__(
self._connections: List[ConnectionInterface] = []
self._requests: List[PoolRequest] = []

# We only mutate the state of the connection pool within an 'optional_thread_lock'
# context. This holds a threading lock unless we're running in async mode,
# in which case it is a no-op.
# We only mutate the state of the connection pool
# within an 'optional_thread_lock' context.
# This holds a threading lock unless we're running in
# async mode, in which case it is a no-op.
self._optional_thread_lock = ThreadLock()

def create_connection(self, origin: Origin) -> ConnectionInterface:
Expand All @@ -148,9 +157,12 @@ def connections(self) -> List[ConnectionInterface]:
```python
>>> pool.connections
[
<HTTPConnection ['https://example.com:443', HTTP/1.1, ACTIVE, Request Count: 6]>,
<HTTPConnection ['https://example.com:443', HTTP/1.1, IDLE, Request Count: 9]> ,
<HTTPConnection ['http://example.com:80', HTTP/1.1, IDLE, Request Count: 1]>,
<HTTPConnection ['https://example.com:443', HTTP/1.1, ACTIVE,
Request Count: 6]>,
<HTTPConnection ['https://example.com:443', HTTP/1.1, IDLE,
Request Count: 9]>,
<HTTPConnection ['http://example.com:80', HTTP/1.1, IDLE,
Request Count: 1]>,
]
```
"""
Expand All @@ -160,7 +172,7 @@ def handle_request(self, request: Request) -> Response:
"""
Send an HTTP request, and return an HTTP response.

This is the core implementation that is called into by `.request()` or `.stream()`.
The core implementation that is called into by `.request()` or `.stream()`.
"""
scheme = request.url.scheme.decode()
if scheme == "":
Expand Down Expand Up @@ -194,7 +206,7 @@ def handle_request(self, request: Request) -> Response:
try:
# Send the request on the assigned connection.
response = connection.handle_request(
pool_request.request
pool_request.request,
)
except ConnectionNotAvailable:
# In some cases a connection may initially be available to
Expand Down
Loading