common_http.transports.base
Shared async HTTP exchange and engine lifecycle.
Classes
BaseTransport
Bases: ABC
One HTTP exchange, with shared ownership and lifecycle rules.
Construction is unconnected. The first open binds this transport to its asyncio event loop; concurrent tasks on that loop share one engine. An injected engine is borrowed and is never closed by this transport.
exchange() receives an absolute, resolved Request. The returned head and single-pass, content-decoded byte iterator live inside its async context. Response cleanup belongs to that context, including on early exit.
The base consumes network_timeout only. Engine creation settings are admitted by _open_engine; call/default/auth/redirect/cookie policy belongs to the client. No execution runner, retry loop, batch or decoding pipeline is constructed here.
__init__
def __init__(*, config: HttpClientConfig | Mapping[str, object] | None = None, engine: EngineT | None = None) -> NoneFields and properties declared here; inherited members belong to the bases above.
config
Read-only property.
config: HttpClientConfigowns_engine
Read-only property.
owns_engine: boolstate
Read-only property.
state: Literal['new', 'open', 'closed']Admission state; a failed close leaves admission closed too.
aclose
async def aclose() -> NoneClose owned resources or detach a borrowed engine.
Active exchanges reject closure without altering state. Finish/cancel their contexts first. Admission closes before engine cleanup starts. If cleanup fails, retain the handle so aclose can be retried; new work stays rejected. Repeated successful closure is harmless.
aopen
async def aopen() -> SelfOpen once, including under concurrent use; never reopen after close.
exchange
async def exchange(request: Request, *, timeout: HttpTimeout | None = None) -> AsyncIterator[Exchange]Manage one response, preserving original read/caller failures.
No network activity occurs until context entry. timeout=None selects the configured phase limits; individual None fields on HttpTimeout disable those phases. HTTP status codes are evidence, not exceptions.
get_info
def get_info() -> HttpTransportInfoInspect capabilities and inherited state without opening.
Use self.state and self.owns_engine for lifecycle truth. Report unknown borrowed-engine capabilities as unknown; do not claim configured protocols were negotiated. Never include requests or credentials.
prepare
def prepare(request: Request) -> RequestReturn the exact message an authenticator can sign without sending.
Backends encoding structured bodies or normalizing targets override this seam. The default supports already-finalized binary/no-body requests; it must never pretend an abstract body is encoded bytes.