shimmodule.py
81 lines
| 2.3 KiB
| text/x-python
|
PythonLexer
Thomas Kluyver
|
r20851 | """A shim module for deprecated imports | ||
""" | ||||
# Copyright (c) IPython Development Team. | ||||
# Distributed under the terms of the Modified BSD License. | ||||
Nikita Kniazev
|
r27078 | import importlib.abc | ||
import importlib.util | ||||
Min RK
|
r20990 | import sys | ||
Thomas Kluyver
|
r20851 | import types | ||
Diego Garcia
|
r22954 | from importlib import import_module | ||
Thomas Kluyver
|
r20851 | |||
Min RK
|
r20991 | from .importstring import import_item | ||
Diego Garcia
|
r22954 | |||
Min RK
|
r21515 | class ShimWarning(Warning): | ||
"""A warning to show when a module has moved, and a shim is in its place.""" | ||||
Min RK
|
r20990 | |||
Nikita Kniazev
|
r27078 | |||
class ShimImporter(importlib.abc.MetaPathFinder): | ||||
Min RK
|
r20990 | """Import hook for a shim. | ||
Nikita Kniazev
|
r27078 | |||
Min RK
|
r20990 | 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 | ||||
Nikita Kniazev
|
r27078 | |||
Min RK
|
r20990 | def _mirror_name(self, fullname): | ||
"""get the name of the mirrored module""" | ||||
Nikita Kniazev
|
r27078 | return self.mirror + fullname[len(self.src) :] | ||
def find_spec(self, fullname, path, target=None): | ||||
if fullname.startswith(self.src + "."): | ||||
Min RK
|
r20990 | mirror_name = self._mirror_name(fullname) | ||
Nikita Kniazev
|
r27078 | return importlib.util.find_spec(mirror_name) | ||
Min RK
|
r20990 | |||
Thomas Kluyver
|
r20851 | class ShimModule(types.ModuleType): | ||
def __init__(self, *args, **kwargs): | ||||
self._mirror = kwargs.pop("mirror") | ||||
Min RK
|
r20990 | src = kwargs.pop("src", None) | ||
if src: | ||||
kwargs['name'] = src.rsplit('.', 1)[-1] | ||||
Thomas Kluyver
|
r20851 | super(ShimModule, self).__init__(*args, **kwargs) | ||
Min RK
|
r20990 | # add import hook for descendent modules | ||
if src: | ||||
sys.meta_path.append( | ||||
ShimImporter(src=src, mirror=self._mirror) | ||||
) | ||||
@property | ||||
def __path__(self): | ||||
return [] | ||||
Min RK
|
r20953 | @property | ||
def __spec__(self): | ||||
"""Don't produce __spec__ until requested""" | ||||
Diego Garcia
|
r22954 | return import_module(self._mirror).__spec__ | ||
Min RK
|
r21311 | |||
def __dir__(self): | ||||
Diego Garcia
|
r22954 | return dir(import_module(self._mirror)) | ||
Min RK
|
r21311 | |||
@property | ||||
def __all__(self): | ||||
"""Ensure __all__ is always defined""" | ||||
Diego Garcia
|
r22954 | mod = import_module(self._mirror) | ||
Min RK
|
r21311 | try: | ||
return mod.__all__ | ||||
except AttributeError: | ||||
return [name for name in dir(mod) if not name.startswith('_')] | ||||
Thomas Kluyver
|
r20851 | |||
def __getattr__(self, key): | ||||
# Use the equivalent of import_item(name), see below | ||||
name = "%s.%s" % (self._mirror, key) | ||||
Min RK
|
r20991 | try: | ||
return import_item(name) | ||||
Ram Rachum
|
r25833 | except ImportError as e: | ||
raise AttributeError(key) from e | ||||