mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
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:
parent
f1d7b11db9
commit
0dbb4c7f13
10 changed files with 3934 additions and 3637 deletions
|
@ -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):
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue