HTTPX Compatibility
HTTPXYZ is a fork of HTTPX. While most code
can be migrated simply by replacing import httpx with import httpxyz, there
are situations where you cannot easily change every dependency — for example,
when a third-party library such as RESPX
checks isinstance(response, httpx.Response) internally.
To handle this, importing httpxyz automatically registers it under the httpx
name in sys.modules:
import sys
import httpxyz
assert sys.modules["httpx"] is sys.modules["httpxyz"] # True
This means any subsequent import httpx in the same process will resolve to
httpxyz, and isinstance checks against httpx classes will pass for
httpxyz objects:
import httpx # resolves to httpxyz after the above
import httpxyz
response = httpxyz.Response(200)
assert isinstance(response, httpx.Response) # True
Prior art
This pattern — where the installable PyPI name differs from the importable module name, or where a fork registers itself under its predecessor's name — is well-established in the Python ecosystem:
- Pillow / PIL — The actively maintained fork of the Python Imaging Library.
It installs as
Pillowon PyPI but exposes thePILpackage, so all code written against the originalPILworks without modification. - opencv-python / cv2 — The PyPI package is
opencv-python; the module iscv2. - pyyaml / yaml — The PyPI package is
pyyaml; the module isyaml.
Important caveat
The aliasing uses sys.modules.setdefault, which means it only takes effect if
httpx has not already been imported before httpxyz. If both packages are
installed and httpx is imported first, the alias will not be established.
For this reason, ensure that nothing in your codebase (or its dependencies)
imports httpx before httpxyz is imported. In practice, the simplest way to
guarantee this is to import httpxyz early — for example, at the top of your
application's entry point — before any other imports that might pull in httpx.
Using respx in pytest
respx registers itself as a pytest plugin
via a pytest11 entry point. Pytest loads all such entry points before it reads
your conftest.py, so respx imports the real httpx first and the
setdefault becomes a no-op — breaking respx.mock with HTTPXYZ objects.
HTTPXYZ ships its own pytest11 entry point to solve this. Because -p flags
in addopts are processed by pytest before entry-point plugins are loaded,
adding -p httpxyz guarantees HTTPXYZ wins the race:
# pyproject.toml
[tool.pytest.ini_options]
addopts = "-p httpxyz"
With this in place:
import httpxanywhere in your test suite returns HTTPXYZ.respxsees HTTPXYZ ashttpx, so allisinstancechecks pass.- The
respx_mockfixture and@pytest.mark.respxmarker remain available. - No need for
-p no:respx.