Initial extracted documentation set

This commit is contained in:
Rodin
2026-06-01 21:42:05 +00:00
commit 60ffec18e4
17 changed files with 1590 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
# HTTPX source notes
Repo: `encode/httpx`
Local checkout: `/home/ubuntu/repos/rodin-sources/httpx`
## Why this repo is useful
- HTTPX is a strong source for modern boundary-design patterns in Python libraries: sync/async separation, transport seams, and caller-oriented exception design.
- It is especially useful because the same conceptual API is implemented twice (sync and async), making repeated design choices easy to spot.
## Sync and async APIs are parallel types, not a mode flag
### Repeated evidence
- `httpx/_client.py:594-660` defines `Client` as the synchronous entrypoint with `BaseTransport` and thread-sharing semantics.
- `httpx/_client.py:1307-1374` defines `AsyncClient` separately with the same broad constructor shape but `AsyncBaseTransport` and task-sharing semantics.
- `httpx/_client.py:688-696` and `httpx/_client.py:1402-1410` show the same transport-initialization flow in each class, reinforcing that the APIs are intentionally parallel rather than conditionally branching inside one type.
### Why it matters
Repeated signal: mature Python networking libraries keep sync and async usage obviously separate in the type system while preserving familiar parameter shapes. That lowers cognitive overhead without hiding execution-model differences.
### Caveat / counterexample
The pattern is not "duplicate everything." HTTPX keeps shared behavior in `BaseClient`; the duplication is at the public entrypoint where transport types and calling style genuinely differ.
## Exceptions are layered for catch-broadly / recover-narrowly behavior
### Repeated evidence
- `httpx/_exceptions.py:74-90` makes `HTTPError` the top-level catch point and explicitly documents `try/except httpx.HTTPError` as a supported usage pattern.
- `httpx/_exceptions.py:107-120` defines `RequestError` for failures that occur while issuing a request and explains why request context may be attached later.
- `httpx/_exceptions.py:123-160` narrows transport failures into `TransportError` and timeout-specific subclasses.
- `httpx/_exceptions.py:167-178` continues the layering into network-specific failures.
### Why it matters
Repeated signal: the exception tree is organized around what callers do next:
- catch one broad library exception for "request failed somehow"
- catch a narrower transport or timeout subtype for retry/backoff behavior
- still access `exc.request` when request context has been attached
## Testing and embedding happen at the transport boundary
### Repeated evidence
- `httpx/_transports/asgi.py:63-97` exposes `ASGITransport` as a first-class transport for routing requests directly into an ASGI app.
- `httpx/_transports/asgi.py:78-83` explicitly calls out `raise_app_exceptions=False` for testing 500 responses instead of surfacing app exceptions immediately.
- `httpx/_transports/mock.py:15-43` defines `MockTransport` as a shared sync/async seam that accepts a handler and adapts it through the transport interface.
### Why it matters
Repeated signal: HTTPX prefers substitutable transports over monkeypatching internal request code. That is a strong pattern for any client library that needs both real I/O and test-time embedding.
### Caveat / counterexample
Transport seams are great for boundary tests, but they are not a full replacement for end-to-end network tests. The strong pattern is to make the boundary swappable, not to pretend boundary tests cover every production behavior.
## Pattern candidates supported by this repo
- split sync and async public APIs into separate types
- keep constructor shapes parallel across sync/async variants
- design exception trees around recovery decisions
- expose transport seams for testing, embedding, and alternate runtimes