Add `alias_httpx()` to alias `httpx` imports to `httpx2`

Merged
KL
3mo ago
+165-0

Summary

Adds httpx2.alias_httpx(): an explicit, application-level function that makes import httpx resolve to httpx2 process-wide, so dependencies still importing httpx share the httpx2 classes - isinstance() checks and except clauses interoperate.

Closes #963.

Why not just sys.modules['httpx'] = httpx2?

The one-liner only covers top-level imports. Any from httpx._x import y makes the import system load httpx2/_x.py a second time under the httpx._x name, recreating the split class hierarchy - and libraries do import httpx internals. So alias_httpx() also installs a MetaPathFinder whose loader returns the already-loaded httpx2.* module for any httpx.* import (no re-execution, __name__ stays truthful).

Behavior

  • Raises RuntimeError if real httpx was already imported (the alias can't rewrite existing references, so it fails loudly instead of half-working).
  • Idempotent; repairs a prior bare sys.modules assignment by installing the finder.
  • For applications only, never libraries - per the docstring and the discussion in #963.

Known limits (unfixable by any aliasing): importlib.metadata.version("httpx") mismatches, logging.getLogger("httpx") silence, and spawn-based subprocess workers re-importing without the alias. These will be covered in the migration guide.

AI Disclaimer

This PR was developed with the assistance of either Claude or Codex. I've reviewed and verified the changes.