Home | History | Annotate | Download | only in importlib
      1 """A pure Python implementation of import."""
      2 __all__ = ['__import__', 'import_module', 'invalidate_caches', 'reload']
      3 
      4 # Bootstrap help #####################################################
      5 
      6 # Until bootstrapping is complete, DO NOT import any modules that attempt
      7 # to import importlib._bootstrap (directly or indirectly). Since this
      8 # partially initialised package would be present in sys.modules, those
      9 # modules would get an uninitialised copy of the source version, instead
     10 # of a fully initialised version (either the frozen one or the one
     11 # initialised below if the frozen one is not available).
     12 import _imp  # Just the builtin component, NOT the full Python module
     13 import sys
     14 
     15 try:
     16     import _frozen_importlib as _bootstrap
     17 except ImportError:
     18     from . import _bootstrap
     19     _bootstrap._setup(sys, _imp)
     20 else:
     21     # importlib._bootstrap is the built-in import, ensure we don't create
     22     # a second copy of the module.
     23     _bootstrap.__name__ = 'importlib._bootstrap'
     24     _bootstrap.__package__ = 'importlib'
     25     try:
     26         _bootstrap.__file__ = __file__.replace('__init__.py', '_bootstrap.py')
     27     except NameError:
     28         # __file__ is not guaranteed to be defined, e.g. if this code gets
     29         # frozen by a tool like cx_Freeze.
     30         pass
     31     sys.modules['importlib._bootstrap'] = _bootstrap
     32 
     33 try:
     34     import _frozen_importlib_external as _bootstrap_external
     35 except ImportError:
     36     from . import _bootstrap_external
     37     _bootstrap_external._setup(_bootstrap)
     38     _bootstrap._bootstrap_external = _bootstrap_external
     39 else:
     40     _bootstrap_external.__name__ = 'importlib._bootstrap_external'
     41     _bootstrap_external.__package__ = 'importlib'
     42     try:
     43         _bootstrap_external.__file__ = __file__.replace('__init__.py', '_bootstrap_external.py')
     44     except NameError:
     45         # __file__ is not guaranteed to be defined, e.g. if this code gets
     46         # frozen by a tool like cx_Freeze.
     47         pass
     48     sys.modules['importlib._bootstrap_external'] = _bootstrap_external
     49 
     50 # To simplify imports in test code
     51 _w_long = _bootstrap_external._w_long
     52 _r_long = _bootstrap_external._r_long
     53 
     54 # Fully bootstrapped at this point, import whatever you like, circular
     55 # dependencies and startup overhead minimisation permitting :)
     56 
     57 import types
     58 import warnings
     59 
     60 
     61 # Public API #########################################################
     62 
     63 from ._bootstrap import __import__
     64 
     65 
     66 def invalidate_caches():
     67     """Call the invalidate_caches() method on all meta path finders stored in
     68     sys.meta_path (where implemented)."""
     69     for finder in sys.meta_path:
     70         if hasattr(finder, 'invalidate_caches'):
     71             finder.invalidate_caches()
     72 
     73 
     74 def find_loader(name, path=None):
     75     """Return the loader for the specified module.
     76 
     77     This is a backward-compatible wrapper around find_spec().
     78 
     79     This function is deprecated in favor of importlib.util.find_spec().
     80 
     81     """
     82     warnings.warn('Use importlib.util.find_spec() instead.',
     83                   DeprecationWarning, stacklevel=2)
     84     try:
     85         loader = sys.modules[name].__loader__
     86         if loader is None:
     87             raise ValueError('{}.__loader__ is None'.format(name))
     88         else:
     89             return loader
     90     except KeyError:
     91         pass
     92     except AttributeError:
     93         raise ValueError('{}.__loader__ is not set'.format(name)) from None
     94 
     95     spec = _bootstrap._find_spec(name, path)
     96     # We won't worry about malformed specs (missing attributes).
     97     if spec is None:
     98         return None
     99     if spec.loader is None:
    100         if spec.submodule_search_locations is None:
    101             raise ImportError('spec for {} missing loader'.format(name),
    102                               name=name)
    103         raise ImportError('namespace packages do not have loaders',
    104                           name=name)
    105     return spec.loader
    106 
    107 
    108 def import_module(name, package=None):
    109     """Import a module.
    110 
    111     The 'package' argument is required when performing a relative import. It
    112     specifies the package to use as the anchor point from which to resolve the
    113     relative import to an absolute import.
    114 
    115     """
    116     level = 0
    117     if name.startswith('.'):
    118         if not package:
    119             msg = ("the 'package' argument is required to perform a relative "
    120                    "import for {!r}")
    121             raise TypeError(msg.format(name))
    122         for character in name:
    123             if character != '.':
    124                 break
    125             level += 1
    126     return _bootstrap._gcd_import(name[level:], package, level)
    127 
    128 
    129 _RELOADING = {}
    130 
    131 
    132 def reload(module):
    133     """Reload the module and return it.
    134 
    135     The module must have been successfully imported before.
    136 
    137     """
    138     if not module or not isinstance(module, types.ModuleType):
    139         raise TypeError("reload() argument must be module")
    140     try:
    141         name = module.__spec__.name
    142     except AttributeError:
    143         name = module.__name__
    144 
    145     if sys.modules.get(name) is not module:
    146         msg = "module {} not in sys.modules"
    147         raise ImportError(msg.format(name), name=name)
    148     if name in _RELOADING:
    149         return _RELOADING[name]
    150     _RELOADING[name] = module
    151     try:
    152         parent_name = name.rpartition('.')[0]
    153         if parent_name:
    154             try:
    155                 parent = sys.modules[parent_name]
    156             except KeyError:
    157                 msg = "parent {!r} not in sys.modules"
    158                 raise ImportError(msg.format(parent_name),
    159                                   name=parent_name) from None
    160             else:
    161                 pkgpath = parent.__path__
    162         else:
    163             pkgpath = None
    164         target = module
    165         spec = module.__spec__ = _bootstrap._find_spec(name, pkgpath, target)
    166         _bootstrap._exec(spec, module)
    167         # The module may have replaced itself in sys.modules!
    168         return sys.modules[name]
    169     finally:
    170         try:
    171             del _RELOADING[name]
    172         except KeyError:
    173             pass
    174