diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2013-11-22 16:05:39 (GMT) |
---|---|---|
committer | Eric Snow <ericsnowcurrently@gmail.com> | 2013-11-22 16:05:39 (GMT) |
commit | b523f8433a8982e10eb41a3e2b37ee0e6d6a6e00 (patch) | |
tree | b38661db4903b7edc4042e7562b32720dd3687bf /Lib/importlib/util.py | |
parent | 9e6097ebe7bb99a4a22b949ef4b1563b21ad7166 (diff) | |
download | cpython-b523f8433a8982e10eb41a3e2b37ee0e6d6a6e00.zip cpython-b523f8433a8982e10eb41a3e2b37ee0e6d6a6e00.tar.gz cpython-b523f8433a8982e10eb41a3e2b37ee0e6d6a6e00.tar.bz2 |
Implement PEP 451 (ModuleSpec).
Diffstat (limited to 'Lib/importlib/util.py')
-rw-r--r-- | Lib/importlib/util.py | 65 |
1 files changed, 58 insertions, 7 deletions
diff --git a/Lib/importlib/util.py b/Lib/importlib/util.py index 7727f9d..04b1951 100644 --- a/Lib/importlib/util.py +++ b/Lib/importlib/util.py @@ -3,13 +3,14 @@ from ._bootstrap import MAGIC_NUMBER from ._bootstrap import cache_from_source from ._bootstrap import decode_source -from ._bootstrap import module_to_load -from ._bootstrap import set_loader -from ._bootstrap import set_package from ._bootstrap import source_from_cache +from ._bootstrap import spec_from_loader +from ._bootstrap import spec_from_file_location from ._bootstrap import _resolve_name +from contextlib import contextmanager import functools +import sys import warnings @@ -28,6 +29,58 @@ def resolve_name(name, package): return _resolve_name(name[level:], package, level) +@contextmanager +def _module_to_load(name): + is_reload = name in sys.modules + + module = sys.modules.get(name) + if not is_reload: + # This must be done before open() is called as the 'io' module + # implicitly imports 'locale' and would otherwise trigger an + # infinite loop. + module = type(sys)(name) + # This must be done before putting the module in sys.modules + # (otherwise an optimization shortcut in import.c becomes wrong) + module.__initializing__ = True + sys.modules[name] = module + try: + yield module + except Exception: + if not is_reload: + try: + del sys.modules[name] + except KeyError: + pass + finally: + module.__initializing__ = False + + +# XXX deprecate +def set_package(fxn): + """Set __package__ on the returned module.""" + @functools.wraps(fxn) + def set_package_wrapper(*args, **kwargs): + module = fxn(*args, **kwargs) + if getattr(module, '__package__', None) is None: + module.__package__ = module.__name__ + if not hasattr(module, '__path__'): + module.__package__ = module.__package__.rpartition('.')[0] + return module + return set_package_wrapper + + +# XXX deprecate +def set_loader(fxn): + """Set __loader__ on the returned module.""" + @functools.wraps(fxn) + def set_loader_wrapper(self, *args, **kwargs): + module = fxn(self, *args, **kwargs) + if getattr(module, '__loader__', None) is None: + module.__loader__ = self + return module + return set_loader_wrapper + + def module_for_loader(fxn): """Decorator to handle selecting the proper module for loaders. @@ -46,13 +99,11 @@ def module_for_loader(fxn): the second argument. """ - warnings.warn('To make it easier for subclasses, please use ' - 'importlib.util.module_to_load() and ' - 'importlib.abc.Loader.init_module_attrs()', + warnings.warn('The import system now takes care of this automatically.', PendingDeprecationWarning, stacklevel=2) @functools.wraps(fxn) def module_for_loader_wrapper(self, fullname, *args, **kwargs): - with module_to_load(fullname) as module: + with _module_to_load(fullname) as module: module.__loader__ = self try: is_package = self.is_package(fullname) |