Initial Commit
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import importlib.abc
|
||||
import importlib.machinery
|
||||
import importlib.util
|
||||
import sys
|
||||
from collections.abc import Sequence
|
||||
from types import ModuleType
|
||||
|
||||
__all__ = ["alias_httpx"]
|
||||
|
||||
|
||||
class _AliasLoader(importlib.abc.Loader):
|
||||
_original_spec: importlib.machinery.ModuleSpec | None
|
||||
|
||||
def __init__(self, real_name: str) -> None:
|
||||
self._real_name = real_name
|
||||
|
||||
def create_module(self, spec: importlib.machinery.ModuleSpec) -> ModuleType:
|
||||
module = importlib.import_module(self._real_name)
|
||||
self._original_spec = module.__spec__
|
||||
return module
|
||||
|
||||
def exec_module(self, module: ModuleType) -> None:
|
||||
module.__spec__ = self._original_spec
|
||||
|
||||
|
||||
class _AliasFinder(importlib.abc.MetaPathFinder):
|
||||
def __init__(self, alias: str, real: str) -> None:
|
||||
self._alias = alias
|
||||
self._real = real
|
||||
|
||||
def find_spec(
|
||||
self,
|
||||
fullname: str,
|
||||
path: Sequence[str] | None = None,
|
||||
target: ModuleType | None = None,
|
||||
) -> importlib.machinery.ModuleSpec | None:
|
||||
if fullname != self._alias and not fullname.startswith(self._alias + "."):
|
||||
return None
|
||||
real_name = self._real + fullname.removeprefix(self._alias)
|
||||
if real_name not in sys.modules and importlib.util.find_spec(real_name) is None:
|
||||
return None
|
||||
return importlib.machinery.ModuleSpec(fullname, _AliasLoader(real_name))
|
||||
|
||||
|
||||
def _alias(alias: str, module: ModuleType) -> None:
|
||||
existing = sys.modules.get(alias)
|
||||
if existing is not None and existing is not module:
|
||||
raise RuntimeError(f"{alias} was already imported; call `alias_httpx()` before any `import {alias}`.")
|
||||
|
||||
if not any(isinstance(finder, _AliasFinder) and finder._alias == alias for finder in sys.meta_path):
|
||||
sys.meta_path.insert(0, _AliasFinder(alias, module.__name__))
|
||||
sys.modules[alias] = module
|
||||
|
||||
|
||||
def alias_httpx() -> None:
|
||||
"""
|
||||
Make `import httpx` resolve to `httpx2`, and `import httpcore` to `httpcore2`, process-wide.
|
||||
|
||||
Intended for applications migrating from `httpx`, so that dependencies still
|
||||
importing `httpx` or `httpcore` share the `httpx2` classes. Libraries should never call this.
|
||||
|
||||
Must be called before anything imports `httpx` or `httpcore`. Calling it again is a no-op.
|
||||
"""
|
||||
import httpcore2
|
||||
import httpx2
|
||||
|
||||
_alias("httpx", httpx2)
|
||||
_alias("httpcore", httpcore2)
|
||||
Reference in New Issue
Block a user