diff options
Diffstat (limited to 'Lib/importlib/util.py')
-rw-r--r-- | Lib/importlib/util.py | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/Lib/importlib/util.py b/Lib/importlib/util.py index 74eef2a955..573b08c0cf 100644 --- a/Lib/importlib/util.py +++ b/Lib/importlib/util.py @@ -1,11 +1,13 @@ """Utility code for constructing importers, etc.""" from ._bootstrap import module_to_load -from ._bootstrap import module_for_loader from ._bootstrap import set_loader from ._bootstrap import set_package from ._bootstrap import _resolve_name +import functools +import warnings + def resolve_name(name, package): """Resolve a relative module name to an absolute one.""" @@ -20,3 +22,44 @@ def resolve_name(name, package): break level += 1 return _resolve_name(name[level:], package, level) + + +def module_for_loader(fxn): + """Decorator to handle selecting the proper module for loaders. + + The decorated function is passed the module to use instead of the module + name. The module passed in to the function is either from sys.modules if + it already exists or is a new module. If the module is new, then __name__ + is set the first argument to the method, __loader__ is set to self, and + __package__ is set accordingly (if self.is_package() is defined) will be set + before it is passed to the decorated function (if self.is_package() does + not work for the module it will be set post-load). + + If an exception is raised and the decorator created the module it is + subsequently removed from sys.modules. + + The decorator assumes that the decorated function takes the module name as + 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()', + PendingDeprecationWarning, stacklevel=2) + @functools.wraps(fxn) + def module_for_loader_wrapper(self, fullname, *args, **kwargs): + with module_to_load(fullname) as module: + module.__loader__ = self + try: + is_package = self.is_package(fullname) + except (ImportError, AttributeError): + pass + else: + if is_package: + module.__package__ = fullname + else: + module.__package__ = fullname.rpartition('.')[0] + # If __package__ was not set above, __import__() will do it later. + return fxn(self, module, *args, **kwargs) + + return module_for_loader_wrapper
\ No newline at end of file |