<div dir="ltr">Here's an updated version of the PEP for ModuleSpec which addresses the feedback I've gotten.  Thanks for the help.  The big open question, to me, is whether or not to have a separate reload() method.  I'll be looking into that when I get a chance.  There's also the question of a path-based subclass, but I'm currently not convinced it's worth it.<div>
<br></div><div>-eric</div><div><br></div><div>-----------------------------------</div><div><br></div><div><div>PEP: 4XX</div><div>Title: A ModuleSpec Type for the Import System</div><div>Version: $Revision$</div><div>Last-Modified: $Date$</div>
<div>Author: Eric Snow <<a href="mailto:ericsnowcurrently@gmail.com">ericsnowcurrently@gmail.com</a>></div><div>BDFL-Delegate: ???</div><div>Discussions-To: <a href="mailto:import-sig@python.org">import-sig@python.org</a></div>
<div>Status: Draft</div><div>Type: Standards Track</div><div>Content-Type: text/x-rst</div><div>Created: 8-Aug-2013</div><div>Python-Version: 3.4</div><div>Post-History: 8-Aug-2013</div><div>Resolution:</div><div><br></div>
<div><br></div><div>Abstract</div><div>========</div><div><br></div><div>This PEP proposes to add a new class to ``importlib.machinery`` called</div><div>``ModuleSpec``.  It will contain all the import-related information</div>
<div>about a module without needing to load the module first.  Finders will</div><div>now return a module's spec rather than a loader.  The import system will</div><div>use the spec to load the module.</div><div><br></div>
<div><br></div><div>Motivation</div><div>==========</div><div><br></div><div>The import system has evolved over the lifetime of Python.  In late 2002</div><div>PEP 302 introduced standardized import hooks via ``finders`` and</div>
<div>``loaders`` and ``sys.meta_path``.  The ``importlib`` module, introduced</div><div>with Python 3.1, now exposes a pure Python implementation of the APIs</div><div>described by PEP 302, as well as of the full import system.  It is now</div>
<div>much easier to understand and extend the import system.  While a benefit</div><div>to the Python community, this greater accessibilty also presents a</div><div>challenge.</div><div><br></div><div>As more developers come to understand and customize the import system,</div>
<div>any weaknesses in the finder and loader APIs will be more impactful.  So</div><div>the sooner we can address any such weaknesses the import system, the</div><div>better...and there are a couple we can take care of with this proposal.</div>
<div><br></div><div>Firstly, any time the import system needs to save information about a</div><div>module we end up with more attributes on module objects that are</div><div>generally only meaningful to the import system and occoasionally to some</div>
<div>people.  It would be nice to have a per-module namespace to put future</div><div>import-related information.  Secondly, there's an API void between</div><div>finders and loaders that causes undue complexity when encountered.</div>
<div><br></div><div>Finders are strictly responsible for providing the loader which the</div><div>import system will use to load the module.  The loader is then</div><div>responsible for doing some checks, creating the module object, setting</div>
<div>import-related attributes, "installing" the module to ``sys.modules``,</div><div>and loading the module, along with some cleanup.  This all takes place</div><div>during the import system's call to ``Loader.load_module()``.  Loaders</div>
<div>also provide some APIs for accessing data associated with a module.</div><div><br></div><div>Loaders are not required to provide any of the functionality of</div><div>``load_module()`` through other methods.  Thus, though the import-</div>
<div>related information about a module is likely available without loading</div><div>the module, it is not otherwise exposed.</div><div><br></div><div>Furthermore, the requirements assocated with ``load_module()`` are</div>
<div>common to all loaders and mostly are implemented in exactly the same</div><div>way.  This means every loader has to duplicate the same boilerplate</div><div>code.  ``importlib.util`` provides some tools that help with this, but</div>
<div>it would be more helpful if the import system simply took charge of</div><div>these responsibilities.  The trouble is that this would limit the degree</div><div>of customization that ``load_module()`` facilitates.  This is a gap</div>
<div>between finders and loaders which this proposal aims to fill.</div><div><br></div><div>Finally, when the import system calls a finder's ``find_module()``, the</div><div>finder makes use of a variety of information about the module that is</div>
<div>useful outside the context of the method.  Currently the options are</div><div>limited for persisting that per-module information past the method call,</div><div>since it only returns the loader.  Popular options for this limitation</div>
<div>are to store the information in a module-to-info mapping somewhere on</div><div>the finder itself, or store it on the loader.</div><div><br></div><div>Unfortunately, loaders are not required to be module-specific.  On top</div>
<div>of that, some of the useful information finders could provide is</div><div>common to all finders, so ideally the import system could take care of</div><div>that.  This is the same gap as before between finders and loaders.</div>
<div><br></div><div>As an example of complexity attributable to this flaw, the</div><div>implementation of namespace packages in Python 3.3 (see PEP 420) added</div><div>``FileFinder.find_loader()`` because there was no good way for</div>
<div>``find_module()`` to provide the namespace path.</div><div><br></div><div>The answer to this gap is a ``ModuleSpec`` object that contains the</div><div>per-module information and takes care of the boilerplate functionality</div>
<div>of loading the module.</div><div><br></div><div>(The idea gained momentum during discussions related to another PEP.[1])</div><div><br></div><div><br></div><div>Specification</div><div>=============</div><div><br></div>
<div>The goal is to address the gap between finders and loaders while</div><div>changing as little of their semantics as possible.  Though some</div><div>functionality and information is moved the new ``ModuleSpec`` type,</div>
<div>their semantics should remain the same.  However, for the sake of</div><div>clarity, those semantics will be explicitly identified.</div><div><br></div><div>A High-Level View</div><div>-----------------</div><div><br>
</div><div>...</div><div><br></div><div>ModuleSpec</div><div>----------</div><div><br></div><div>A new class which defines the import-related values to use when loading</div><div>the module.  It closely corresponds to the import-related attributes of</div>
<div>module objects.  ``ModuleSpec`` objects may also be used by finders and</div><div>loaders and other import-related APIs to hold extra import-related</div><div>state about the module.  This greatly reduces the need to add any new</div>
<div>new import-related attributes to module objects, and loader ``__init__``</div><div>methods won't need to accommodate such per-module state.</div><div><br></div><div>Creating a ModuleSpec:</div><div><br></div><div>
``ModuleSpec(name, loader, *, origin=None, filename=None, cached=None,</div><div>path=None)``</div><div><br></div><div>The parameters have the same meaning as the attributes described below.</div><div>However, not all ``ModuleSpec`` attributes are also parameters.  The</div>
<div>passed values are set as-is.  For calculated values use the</div><div>``from_loader()`` method.</div><div><br></div><div>ModuleSpec Attributes</div><div>---------------------</div><div><br></div><div>Each of the following names is an attribute on ``ModuleSpec`` objects.</div>
<div>A value of ``None`` indicates "not set".  This contrasts with module</div><div>objects where the attribute simply doesn't exist.</div><div><br></div><div>While ``package`` and ``is_package`` are read-only properties, the</div>
<div>remaining attributes can be replaced after the module spec is created</div><div>and after import is complete.  This allows for unusual cases where</div><div>modifying the spec is the best option.  However, typical use should not</div>
<div>involve changing the state of a module's spec.</div><div><br></div><div>Most of the attributes correspond to the import-related attributes of</div><div>modules.  Here is the mapping, followed by a description of the</div>
<div>attributes.  The reverse of this mapping is used by</div><div>``init_module_attrs()``.</div><div><br></div><div>============= ===========</div><div>On ModuleSpec On Modules</div><div>============= ===========</div><div>
name          __name__</div><div>loader        __loader__</div><div>package       __package__</div><div>is_package    -</div><div>origin        -</div><div>filename      __file__</div><div>cached        __cached__</div><div>
path          __path__</div><div>============= ===========</div><div><br></div><div>``name``</div><div><br></div><div>The module's fully resolved and absolute name.  It must be set.</div><div><br></div><div>``loader``</div>
<div><br></div><div>The loader to use during loading and for module data.  These specific</div><div>functionalities do not change for loaders.  Finders are still</div><div>responsible for creating the loader and this attribute is where it is</div>
<div>stored.  The loader must be set.</div><div><br></div><div>``package``</div><div><br></div><div>The name of the module's parent.  This is a dynamic attribute with a</div><div>value derived from ``name`` and ``is_package``.  For packages it is the</div>
<div>value of ``name``.  Otherwise it is equivalent to</div><div>``name.rpartition('.')[0]``.  Consequently, a top-level module will have</div><div>give the empty string for ``package``.</div><div><br></div><div><br>
</div><div>``is_package``</div><div><br></div><div>Whether or not the module is a package.  This dynamic attribute is True</div><div>if ``path`` is set (even if empty), else it is false.</div><div><br></div><div>``origin``</div>
<div><br></div><div>A string for the location from which the module originates.  If</div><div>``filename`` is set, ``origin`` should be set to the same value unless</div><div>some other value is more appropriate.  ``origin`` is used in</div>
<div>``module_repr()`` if it does not match the value of ``filename``.</div><div><br></div><div>Using ``filename`` for this meaning would be inaccurate, since not all</div><div>modules have path-based locations.  For instance, built-in modules do</div>
<div>not have ``__file__`` set.  Yet it is useful to have a descriptive</div><div>string indicating that it originated from the interpreter as a built-in</div><div>module.  So built-in modules will have ``origin`` set to ``"built-in"``.</div>
<div><br></div><div>Path-based attributes:</div><div><br></div><div>If any of these is set, it indicates that the module is path-based.  For</div><div>reference, a path entry is a string for a location where the import</div>
<div>system will look for modules, e.g. the path entries in ``sys.path`` or a</div><div>package's ``__path__``).</div><div><br></div><div>``filename``</div><div><br></div><div>Like ``origin``, but limited to a path-based location.  If ``filename``</div>
<div>is set, ``origin`` should be set to the same string, unless origin is</div><div>explicitly set to something else.  ``filename`` is not necessarily an</div><div>actual file name, but could be any location string based on a path</div>
<div>entry.  Regarding the attribute name, while it is potentially</div><div>inaccurate, it is both consistent with the equivalent module attribute</div><div>and generally accurate.</div><div><br></div><div>.. XXX Would a different name be better?  ``path_location``?</div>
<div><br></div><div>``cached``</div><div><br></div><div>The path-based location where the compiled code for a module should be</div><div>stored.  If ``filename`` is set to a source file, this should be set to</div><div>corresponding path that PEP 3147 specifies.  The</div>
<div>``importlib.util.source_to_cache()`` function facilitates getting the</div><div>correct value.</div><div><br></div><div>``path``</div><div><br></div><div>The list of path entries in which to search for submodules if this</div>
<div>module is a package.  Otherwise it is ``None``.</div><div><br></div><div>.. XXX add a path-based subclass?</div><div><br></div><div>ModuleSpec Methods</div><div>------------------</div><div><br></div><div>``from_loader(name, loader, *, is_package=None, origin=None, filename=None, cached=None, path=None)``</div>
<div><br></div><div>.. XXX use a different name?</div><div><br></div><div>A factory classmethod that returns a new ``ModuleSpec`` derived from the</div><div>arguments.  ``is_package`` is used inside the method to indicate that</div>
<div>the module is a package.  If not explicitly passed in, it is set to</div><div>``True`` if ``path`` is passed in.  It falls back to using the result of</div><div>the loader's ``is_package()``, if available.  Finally it defaults to</div>
<div>False.  The remaining parameters have the same meaning as the</div><div>corresponding ``ModuleSpec`` attributes.</div><div><br></div><div>In contrast to ``ModuleSpec.__init__()``, which takes the arguments</div><div>
as-is, ``from_loader()`` calculates missing values from the ones passed</div><div>in, as much as possible.  This replaces the behavior that is currently</div><div>provided the several ``importlib.util`` functions as well as the</div>
<div>optional ``init_module_attrs()`` method of loaders.  Just to be clear,</div><div>here is a more detailed description of those calculations::</div><div><br></div><div>   If not passed in, ``filename`` is to the result of calling the</div>
<div>   loader's ``get_filename()``, if available.  Otherwise it stays</div><div>   unset (``None``).</div><div><br></div><div>   If not passed in, ``path`` is set to an empty list if</div><div>   ``is_package`` is true.  Then the directory from ``filename`` is</div>
<div>   appended to it, if possible.  If ``is_package`` is false, ``path``</div><div>   stays unset.</div><div><br></div><div>   If ``cached`` is not passed in and ``filename`` is passed in,</div><div>   ``cached`` is derived from it.  For filenames with a source suffix,</div>
<div>   it set to the result of calling</div><div>   ``importlib.util.cache_from_source()``.  For bytecode suffixes (e.g.</div><div>   ``.pyc``), ``cached`` is set to the value of ``filename``.  If</div><div>   ``filename`` is not passed in or ``cache_from_source()`` raises</div>
<div>   ``NotImplementedError``, ``cached`` stays unset.</div><div><br></div><div>   If not passed in, ``origin`` is set to ``filename``.  Thus if</div><div>   ``filename`` is unset, ``origin`` stays unset.</div><div><br>
</div><div>``module_repr()``</div><div><br></div><div>Returns a repr string for the module if ``origin`` is set and</div><div>``filename`` is not set.  The string refers to the value of ``origin``.</div><div>Otherwise ``module_repr()`` returns None.  This indicates to the module</div>
<div>type's ``__repr__()`` that it should fall back to the default repr.</div><div><br></div><div>We could also have ``module_repr()`` produce the repr for the case where</div><div>``filename`` is set or where ``origin`` is not set, mirroring the repr</div>
<div>that the module type produces directly.  However, the repr string is</div><div>derived from the import-related module attributes, which might be out of</div><div>sync with the spec.</div><div><br></div><div>.. XXX Is using the spec close enough?  Probably not.</div>
<div><br></div><div>The implementation of the module type's ``__repr__()`` will change to</div><div>accommodate this PEP.  However, the current functionality will remain to</div><div>handle the case where a module does not have a ``__spec__`` attribute.</div>
<div><br></div><div>``init_module_attrs(module)``</div><div><br></div><div>Sets the module's import-related attributes to the corresponding values</div><div>in the module spec.  If a path-based attribute is not set on the spec,</div>
<div>it is not set on the module.  For the rest, a ``None`` value on the spec</div><div>(aka "not set") means ``None`` will be set on the module.  If any of the</div><div>attributes are already set on the module, the existing values are</div>
<div>replaced.  The module's own ``__spec__`` is not consulted but does get</div><div>replaced with the spec on which ``init_module_attrs()`` was called.</div><div>The earlier mapping of ``ModuleSpec`` attributes to module attributes</div>
<div>indicates which attributes are involved on both sides.</div><div><br></div><div>``load(module=None, *, is_reload=False)``</div><div><br></div><div>This method captures the current functionality of and requirements on</div>
<div>``Loader.load_module()`` without any semantic changes, except one.</div><div>Reloading a module when ``exec_module()`` is available actually uses</div><div>``module`` rather than ignoring it in favor of the one in</div>
<div>``sys.modules``, as ``Loader.load_module()`` does.</div><div><br></div><div>``module`` is only allowed when ``is_reload`` is true.  This means that</div><div>``is_reload`` could be dropped as a parameter.  However, doing so would</div>
<div>mean we could not use ``None`` to indicate that the module should be</div><div>pulled from ``sys.modules``.  Furthermore, ``is_reload`` makes the</div><div>intent of the call clear.</div><div><br></div><div>There are two parts to what happens in ``load()``.  First, the module is</div>
<div>prepared, loaded, updated appropriately, and left available for the</div><div>second part.  This is described in more detail shortly.</div><div><br></div><div>Second, in the case of error during a normal load (not reload) the</div>
<div>module is removed from ``sys.modules``.  If no error happened, the</div><div>module is pulled from ``sys.modules``.  This the module returned by</div><div>``load()``.  Before it is returned, if it is a different object than the</div>
<div>one produced by the first part, attributes of the module from</div><div>``sys.modules`` are updated to reflect the spec.</div><div><br></div><div>Returning the module from ``sys.modules`` accommodates the ability of</div>
<div>the module to replace itself there while it is executing (during load).</div><div><br></div><div>As already noted, this is what already happens in the import system.</div><div>``load()`` is not meant to change any of this behavior.</div>
<div><br></div><div>Regarding the first part of ``load()``, the following describes what</div><div>happens.  It depends on if ``is_reload`` is true and if the loader has</div><div>``exec_module()``.</div><div><br></div><div>
For normal load with ``exec_module()`` available::</div><div><br></div><div>   A new module is created, ``init_module_attrs()`` is called to set</div><div>   its attributes, and it is set on sys.modules.  At that point</div>
<div>   the loader's ``exec_module()`` is called, after which the module</div><div>   is ready for the second part of loading.</div><div><br></div><div>.. XXX What if the module already exists in sys.modules?</div><div>
<br></div><div>For normal load without ``exec_module()`` available::</div><div><br></div><div>   The loader's ``load_module()`` is called and the attributes of the</div><div>   module it returns are updated to match the spec.</div>
<div><br></div><div>For reload with ``exec_module()`` available::</div><div><br></div><div>   If ``module`` is ``None``, it is pulled from ``sys.modules``.  If</div><div>   still ``None``, ImportError is raised.  Otherwise ``exec_module()``</div>
<div>   is called, passing in the module-to-be-reloaded.</div><div><br></div><div>For reload without ``exec_module()`` available::</div><div><br></div><div>   The loader's ``load_module()`` is called and the attributes of the</div>
<div>   module it returns are updated to match the spec.</div><div><br></div><div>There is some boilerplate involved when ``exec_module()`` is available,</div><div>but only the boilerplate that the import system uses currently.</div>
<div><br></div><div>If ``loader`` is not set (``None``), ``load()`` raises a ValueError.  If</div><div>``module`` is passed in but ``is_reload`` is false, a ValueError is also</div><div>raises to indicate that ``load()`` was called incorrectly.  There may be</div>
<div>use cases for calling ``load()`` in that way, but they are outside the</div><div>scope of this PEP</div><div><br></div><div>.. XXX add reload(module=None) and drop load()'s parameters entirely?</div><div>.. XXX add more of importlib.reload()'s boilerplate to load()/reload()?</div>
<div><br></div><div>Backward Compatibility</div><div>----------------------</div><div><br></div><div>Since ``Finder.find_module()`` methods would now return a module spec</div><div>instead of loader, specs must act like the loader that would have been</div>
<div>returned instead.  This is relatively simple to solve since the loader</div><div>is available as an attribute of the spec.  We will use ``__getattr__()``</div><div>to do it.</div><div><br></div><div>However, ``ModuleSpec.is_package`` (an attribute) conflicts with</div>
<div>``InspectLoader.is_package()`` (a method).  Working around this requires</div><div>a more complicated solution but is not a large obstacle.  Simply making</div><div>``ModuleSpec.is_package`` a method does not reflect that is a relatively</div>
<div>static piece of data.  ``module_repr()`` also conflicts with the same</div><div>method on loaders, but that workaround is not complicated since both are</div><div>methods.</div><div><br></div><div>Unfortunately, the ability to proxy does not extend to ``id()``</div>
<div>comparisons and ``isinstance()`` tests.  In the case of the return value</div><div>of ``find_module()``, we accept that break in backward compatibility.</div><div>However, we will mitigate the problem with ``isinstance()`` somewhat by</div>
<div>registering ``ModuleSpec`` on the loaders in ``importlib.abc``.</div><div><br></div><div>Subclassing</div><div>-----------</div><div><br></div><div>Subclasses of ModuleSpec are allowed, but should not be necessary.</div>
<div>Adding functionality to a custom finder or loader will likely be a</div><div>better fit and should be tried first.  However, as long as a subclass</div><div>still fulfills the requirements of the import system, objects of that</div>
<div>type are completely fine as the return value of ``find_module()``.</div><div><br></div><div>Module Objects</div><div>--------------</div><div><br></div><div>Module objects will now have a ``__spec__`` attribute to which the</div>
<div>module's spec will be bound.  None of the other import-related module</div><div>attributes will be changed or deprecated, though some of them could be;</div><div>any such deprecation can wait until Python 4.</div>
<div><br></div><div>``ModuleSpec`` objects will not be kept in sync with the corresponding</div><div>module object's import-related attributes.  Though they may differ, in</div><div>practice they will typically be the same.</div>
<div><br></div><div>Finders</div><div>-------</div><div><br></div><div>Finders will now return ModuleSpec objects when ``find_module()`` is</div><div>called rather than loaders.  For backward compatility, ``Modulespec``</div>
<div>objects proxy the attributes of their ``loader`` attribute.</div><div><br></div><div>Adding another similar method to avoid backward-compatibility issues</div><div>is undersireable if avoidable.  The import APIs have suffered enough,</div>
<div>especially considering ``PathEntryFinder.find_loader()`` was just</div><div>added in Python 3.3.  The approach taken by this PEP should be</div><div>sufficient to address backward-compatibility issues for</div><div>``find_module()``.</div>
<div><br></div><div>The change to ``find_module()`` applies to both ``MetaPathFinder`` and</div><div>``PathEntryFinder``.  ``PathEntryFinder.find_loader()`` will be</div><div>deprecated and, for backward compatibility, implicitly special-cased if</div>
<div>the method exists on a finder.</div><div><br></div><div>Finders are still responsible for creating the loader.  That loader will</div><div>now be stored in the module spec returned by ``find_module()`` rather</div><div>
than returned directly.  As is currently the case without the PEP, if a</div><div>loader would be costly to create, that loader can be designed to defer</div><div>the cost until later.</div><div><br></div><div>Loaders</div>
<div>-------</div><div><br></div><div>Loaders will have a new method, ``exec_module(module)``.  Its only job</div><div>is to "exec" the module and consequently populate the module's</div><div>namespace.  It is not responsible for creating or preparing the module</div>
<div>object, nor for any cleanup afterward.  It has no return value.</div><div><br></div><div>The ``load_module()`` of loaders will still work and be an active part</div><div>of the loader API.  It is still useful for cases where the default</div>
<div>module creation/prepartion/cleanup is not appropriate for the loader.</div><div><br></div><div>For example, the C API for extension modules only supports the full</div><div>control of ``load_module()``.  As such, ``ExtensionFileLoader`` will not</div>
<div>implement ``exec_module()``.  In the future it may be appropriate to</div><div>produce a second C API that would support an ``exec_module()``</div><div>implementation for ``ExtensionFileLoader``.  Such a change is outside</div>
<div>the scope of this PEP.</div><div><br></div><div>A loader must have at least one of ``exec_module()`` and</div><div>``load_module()`` defined.  If both exist on the loader,</div><div>``ModuleSpec.load()`` uses ``exec_module()`` and ignores</div>
<div>``load_module()``.</div><div><br></div><div>PEP 420 introduced the optional ``module_repr()`` loader method to limit</div><div>the amount of special-casing in the module type's ``__repr__()``.  Since</div><div>this method is part of ``ModuleSpec``, it will be deprecated on loaders.</div>
<div>However, if it exists on a loader it will be used exclusively.</div><div><br></div><div>``Loader.init_module_attr()`` method, added prior to Python 3.4's</div><div>release , will be removed in favor of the same method on ``ModuleSpec``.</div>
<div><br></div><div>However, ``InspectLoader.is_package()`` will not be deprecated even</div><div>though the same information is found on ``ModuleSpec``.  ``ModuleSpec``</div><div>can use it to populate its own ``is_package`` if that information is</div>
<div>not otherwise available.  Still, it will be made optional.</div><div><br></div><div>The path-based loaders in ``importlib`` take arguments in their</div><div>``__init__()`` and have corresponding attributes.  However, the need for</div>
<div>those values is eliminated.  The only exception is</div><div>``FileLoader.get_filename()``, which uses ``self.path``.  The signatures</div><div>for these loaders and the accompanying attributes will be deprecated.</div>
<div><br></div><div>In addition to executing a module during loading, loaders will still be</div><div>directly responsible for providing APIs concerning module-related data.</div><div><br></div><div>Other Changes</div><div>
-------------</div><div><br></div><div>* The various finders and loaders provided by ``importlib`` will be</div><div>updated to comply with this proposal.</div><div><br></div><div>* The spec for the ``__main__`` module will reflect how the interpreter</div>
<div>was started.  For instance, with ``-m`` the spec's name will be that of</div><div>the run module, while ``__main__.__name__`` will still be "__main__".</div><div><br></div><div>* We add ``importlib.find_module()`` to mirror</div>
<div>``importlib.find_loader()`` (which becomes deprecated).</div><div><br></div><div>* Deprecations in ``importlib.util``: ``set_package()``,</div><div>``set_loader()``, and ``module_for_loader()``.  ``module_to_load()``</div>
<div>(introduced prior to Python 3.4's release) can be removed.</div><div><br></div><div>* ``importlib.reload()`` is changed to use ``ModuleSpec.load()``.</div><div><br></div><div>* ``ModuleSpec.load()`` and ``importlib.reload()`` will now make use of</div>
<div>the per-module import lock, whereas ``Loader.load_module()`` did not.</div><div><br></div><div>Reference Implementation</div><div>------------------------</div><div><br></div><div>A reference implementation is available at <TBD>.</div>
<div><br></div><div><br></div><div>References</div><div>==========</div><div><br></div><div>[1] <a href="http://mail.python.org/pipermail/import-sig/2013-August/000658.html">http://mail.python.org/pipermail/import-sig/2013-August/000658.html</a></div>
<div><br></div><div><br></div><div>Copyright</div><div>=========</div><div><br></div><div>This document has been placed in the public domain.</div><div><br></div><div> </div><div>..</div><div>   Local Variables:</div><div>
   mode: indented-text</div><div>   indent-tabs-mode: nil</div><div>   sentence-end-double-space: t</div><div>   fill-column: 70</div><div>   coding: utf-8</div><div>   End:</div></div><div><br></div></div>