CodeVetter · Repo Unpack · Extension points
psf/requests
There is one primary extension seam and several secondary ones. The primary is the Transport Adapter: `Session.mount(prefix, adapter)` keeps `self.adapters` sorted by descending prefix length and `get_adapter` picks the longest matching prefix, so any URL prefix can be routed to a `BaseAdapter` subclass — this is how retry policies, custom TLS contexts, and test doubles are injected. Secondary seams are the response hook system, the `AuthBase` callable protocol, the `SessionRedirectMixin` methods documented as overridable, and the packager-facing `certs.where()`. Nearly every private-looking `HTTPAdapter` method carries a docstring saying it exists specifically for subclass overrides.
- `Session.mount(prefix, adapter)` is the registry: it inserts into the `self.adapters` OrderedDict then re-pops every shorter key so adapters stay in descending prefix-length order.
- `Session.get_adapter(url)` resolves by case-insensitive `startswith` over that ordered map, raising `InvalidSchema(f"No connection adapters were found for {url!r}")` when nothing matches — so registering a new scheme is purely a mount call.
- `BaseAdapter` defines the minimal contract — `send(request, stream, timeout, verify, cert, proxies)` and `close()` — that any replacement transport must implement.
- Eight `HTTPAdapter` methods are documented as subclass-override points rather than user API: `init_poolmanager`, `proxy_manager_for`, `cert_verify`, `build_response`, `get_connection_with_tls_context`, `request_url`, `add_headers`, and `proxy_headers`.
- `HTTPAdapter.add_headers()` is an intentional empty hook — 'As of v2.0 this does nothing by default, but is left for overriding by users that subclass' — and is called on every send with the full kwargs.
- `init_poolmanager(**pool_kwargs)` forwards arbitrary kwargs to `urllib3.PoolManager`, which is the documented way to inject a custom `ssl_context` or TLS version.
- The hook registry is the `HOOKS = ['response']` list in `hooks.py`, with `default_hooks()` building `{event: []}` and `dispatch_hook()` chaining callables so each non-None return replaces the data for the next hook.
- Hooks can be attached per-request (`hooks=` kwarg), per-session (`Session.hooks`), or programmatically via `RequestHooksMixin.register_hook` / `deregister_hook`, which both `Request` and `PreparedRequest` inherit.
- Custom auth plugs in via `AuthBase`, whose `__call__(self, r) -> PreparedRequest` raises `NotImplementedError` by default; `prepare_auth` treats any non-2-tuple auth value as such a callable.
- `SessionRedirectMixin` is a separately-inheritable class exposing `get_redirect_target`, `should_strip_auth`, `resolve_redirects`, `rebuild_auth`, `rebuild_proxies` and `rebuild_method` — the tests subclass it directly as `RedirectSession` to exercise redirect logic without a network.
- `get_redirect_target`'s docstring explicitly invites a custom mixin that caches the redirect location on the response as a private attribute, acknowledging the method is called redundantly per hop.
- `certs.where()` is the packager extension point: the module docstring instructs distributors to change its definition to return a separately packaged CA bundle.
- Character-detection backends are pluggable at import: `_resolve_char_detection()` tries `chardet` then `charset_normalizer`, and `Response.apparent_encoding` degrades to a plain `utf-8` assumption if neither is installed.
- The status-code table is data-driven: adding a code means adding an entry to the `_codes` dict, and `_init()` generates both lowercase and uppercase attributes plus the docstring table automatically.
- Custom HTTP verbs need no new code — `Session.request(method, ...)` uppercases whatever string it is given, which is the documented 'Custom Verbs' capability.
- Optional extras are declared as installable feature flags in `pyproject.toml`: `socks` (PySocks), `use_chardet_on_py3` (chardet), and a now-empty `security` extra kept for compatibility.