| """A shim module for deprecated imports |
| """ |
| |
| |
|
|
| import importlib.abc |
| import importlib.util |
| import sys |
| import types |
| from importlib import import_module |
|
|
| from .importstring import import_item |
|
|
|
|
| class ShimWarning(Warning): |
| """A warning to show when a module has moved, and a shim is in its place.""" |
|
|
|
|
| class ShimImporter(importlib.abc.MetaPathFinder): |
| """Import hook for a shim. |
| |
| This ensures that submodule imports return the real target module, |
| not a clone that will confuse `is` and `isinstance` checks. |
| """ |
| def __init__(self, src, mirror): |
| self.src = src |
| self.mirror = mirror |
|
|
| def _mirror_name(self, fullname): |
| """get the name of the mirrored module""" |
|
|
| return self.mirror + fullname[len(self.src) :] |
|
|
| def find_spec(self, fullname, path, target=None): |
| if fullname.startswith(self.src + "."): |
| mirror_name = self._mirror_name(fullname) |
| return importlib.util.find_spec(mirror_name) |
|
|
|
|
| class ShimModule(types.ModuleType): |
|
|
| def __init__(self, *args, **kwargs): |
| self._mirror = kwargs.pop("mirror") |
| src = kwargs.pop("src", None) |
| if src: |
| kwargs['name'] = src.rsplit('.', 1)[-1] |
| super(ShimModule, self).__init__(*args, **kwargs) |
| |
| if src: |
| sys.meta_path.append( |
| ShimImporter(src=src, mirror=self._mirror) |
| ) |
| |
| @property |
| def __path__(self): |
| return [] |
| |
| @property |
| def __spec__(self): |
| """Don't produce __spec__ until requested""" |
| return import_module(self._mirror).__spec__ |
| |
| def __dir__(self): |
| return dir(import_module(self._mirror)) |
| |
| @property |
| def __all__(self): |
| """Ensure __all__ is always defined""" |
| mod = import_module(self._mirror) |
| try: |
| return mod.__all__ |
| except AttributeError: |
| return [name for name in dir(mod) if not name.startswith('_')] |
|
|
| def __getattr__(self, key): |
| |
| name = "%s.%s" % (self._mirror, key) |
| try: |
| return import_item(name) |
| except ImportError as e: |
| raise AttributeError(key) from e |
|
|
| def __repr__(self): |
| |
| |
| try: |
| return self.__getattr__("__repr__")() |
| except AttributeError: |
| return f"<ShimModule for {self._mirror!r}>" |
|
|