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.
diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst
index 35336b1..d9e4273 100644
--- a/Doc/library/importlib.rst
+++ b/Doc/library/importlib.rst
@@ -246,7 +246,7 @@
The loader should set several attributes on the module.
(Note that some of these attributes can change when a module is
- reloaded.)
+ reloaded; see :meth:`init_module_attrs`):
- :attr:`__name__`
The name of the module.
@@ -289,6 +289,17 @@
.. versionchanged:: 3.4
Made optional instead of an abstractmethod.
+ .. method:: init_module_attrs(module)
+
+ Set the :attr:`__loader__` attribute on the module.
+
+ Subclasses overriding this method should set whatever appropriate
+ attributes it can, getting the module's name from :attr:`__name__` when
+ needed. All values should also be overridden so that reloading works as
+ expected.
+
+ .. versionadded:: 3.4
+
.. class:: ResourceLoader
@@ -363,6 +374,18 @@
.. versionadded:: 3.4
+ .. method:: init_module_attrs(module)
+
+ Set the :attr:`__package__` attribute and :attr:`__path__` attribute to
+ the empty list if appropriate along with what
+ :meth:`importlib.abc.Loader.init_module_attrs` sets.
+
+ .. versionadded:: 3.4
+
+ .. method:: load_module(fullname)
+
+ Implementation of :meth:`Loader.load_module`.
+
.. class:: ExecutionLoader
@@ -383,6 +406,15 @@
.. versionchanged:: 3.4
Raises :exc:`ImportError` instead of :exc:`NotImplementedError`.
+ .. method:: init_module_attrs(module)
+
+ Set :attr:`__file__` and if initializing a package then set
+ :attr:`__path__` to ``[os.path.dirname(__file__)]`` along with
+ all attributes set by
+ :meth:`importlib.abc.InspectLoader.init_module_attrs`.
+
+ .. versionadded:: 3.4
+
.. class:: FileLoader(fullname, path)
@@ -500,6 +532,14 @@
``__init__`` when the file extension is removed **and** the module name
itself does not end in ``__init__``.
+ .. method:: init_module_attr(module)
+
+ Set :attr:`__cached__` using :func:`imp.cache_from_source`. Other
+ attributes set by
+ :meth:`importlib.abc.ExecutionLoader.init_module_attrs`.
+
+ .. versionadded:: 3.4
+
:mod:`importlib.machinery` -- Importers and path hooks
------------------------------------------------------
@@ -826,17 +866,18 @@
module from being in left in :data:`sys.modules`. If the module was already
in :data:`sys.modules` then it is left alone.
- .. note::
- :func:`module_to_load` subsumes the module management aspect of this
- decorator.
-
.. versionchanged:: 3.3
:attr:`__loader__` and :attr:`__package__` are automatically set
(when possible).
.. versionchanged:: 3.4
- Set :attr:`__loader__` :attr:`__package__` unconditionally to support
- reloading.
+ Set :attr:`__name__`, :attr:`__loader__` :attr:`__package__`
+ unconditionally to support reloading.
+
+ .. deprecated:: 3.4
+ For the benefit of :term:`loader` subclasses, please use
+ :func:`module_to_load` and
+ :meth:`importlib.abc.Loader.init_module_attrs` instead.
.. decorator:: set_loader
@@ -849,7 +890,8 @@
.. note::
As this decorator sets :attr:`__loader__` after loading the module, it is
- recommended to use :func:`module_for_loader` instead when appropriate.
+ recommended to use :meth:`importlib.abc.Loader.init_module_attrs` instead
+ when appropriate.
.. versionchanged:: 3.4
Set ``__loader__`` if set to ``None``, as if the attribute does not
@@ -862,4 +904,5 @@
.. note::
As this decorator sets :attr:`__package__` after loading the module, it is
- recommended to use :func:`module_for_loader` instead when appropriate.
+ recommended to use :meth:`importlib.abc.Loader.init_module_attrs` instead
+ when appropriate.