Issues #18088, 18089: Introduce

importlib.abc.Loader.init_module_attrs() and implement
importlib.abc.InspectLoader.load_module().

The importlib.abc.Loader.init_module_attrs() method sets the various
attributes on the module being loaded. It is done unconditionally to
support reloading. Typically people used
importlib.util.module_for_loader, but since that's a decorator there
was no way to override it's actions, so init_module_attrs() came into
existence to allow for overriding. This is also why module_for_loader
is now pending deprecation (having its other use replaced by
importlib.util.module_to_load).

All of this allowed for importlib.abc.InspectLoader.load_module() to
be implemented. At this point you can now implement a loader with
nothing more than get_code() (which only requires get_source();
package support requires is_package()). Thanks to init_module_attrs()
the implementation of load_module() is basically a context manager
containing 2 methods calls, a call to exec(), and a return statement.
This commit is contained in:
Brett Cannon 2013-05-31 18:56:47 -04:00
parent f1d7b11db9
commit 0dbb4c7f13
10 changed files with 3934 additions and 3637 deletions

View file

@ -8,11 +8,6 @@ except ImportError as exc:
raise
_frozen_importlib = None
import abc
import imp
import marshal
import sys
import tokenize
import warnings
def _register(abstract_cls, *classes):
@ -113,6 +108,10 @@ class Loader(metaclass=abc.ABCMeta):
"""
raise NotImplementedError
def init_module_attrs(self, module):
"""Set the module's __loader__ attribute."""
module.__loader__ = self
class ResourceLoader(Loader):
@ -177,6 +176,17 @@ class InspectLoader(Loader):
argument should be where the data was retrieved (when applicable)."""
return compile(data, path, 'exec', dont_inherit=True)
def init_module_attrs(self, module):
"""Initialize the __loader__ and __package__ attributes of the module.
The name of the module is gleaned from module.__name__. The __package__
attribute is set based on self.is_package().
"""
super().init_module_attrs(module)
_bootstrap._init_package_attrs(self, module)
load_module = _bootstrap._LoaderBasics.load_module
_register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter,
machinery.ExtensionFileLoader)
@ -215,6 +225,18 @@ class ExecutionLoader(InspectLoader):
else:
return self.source_to_code(source, path)
def init_module_attrs(self, module):
"""Initialize the module's attributes.
It is assumed that the module's name has been set on module.__name__.
It is also assumed that any path returned by self.get_filename() uses
(one of) the operating system's path separator(s) to separate filenames
from directories in order to set __path__ intelligently.
InspectLoader.init_module_attrs() sets __loader__ and __package__.
"""
super().init_module_attrs(module)
_bootstrap._init_file_attrs(self, module)
class FileLoader(_bootstrap.FileLoader, ResourceLoader, ExecutionLoader):