shimmodule.py
94 lines
| 2.8 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. | ||||
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 | |||
class ShimImporter(object): | ||||
"""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_module(self, fullname, path=None): | ||||
"""Return self if we should be used to import the module.""" | ||||
if fullname.startswith(self.src + '.'): | ||||
mirror_name = self._mirror_name(fullname) | ||||
try: | ||||
Min RK
|
r20992 | mod = import_item(mirror_name) | ||
Min RK
|
r20990 | except ImportError: | ||
return | ||||
else: | ||||
Min RK
|
r20992 | if not isinstance(mod, types.ModuleType): | ||
# not a module | ||||
return None | ||||
Min RK
|
r20990 | return self | ||
def load_module(self, fullname): | ||||
"""Import the mirrored module, and insert it into sys.modules""" | ||||
mirror_name = self._mirror_name(fullname) | ||||
Min RK
|
r20991 | mod = import_item(mirror_name) | ||
Min RK
|
r20990 | sys.modules[fullname] = mod | ||
return mod | ||||
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 | ||||