[PEP 451] Updates in response to the latest feedback.

This includes removing the remaining ModuleSpec methods and de-emphasizing
that find_spec() returns actual ModuleSpec instances.
This commit is contained in:
Eric Snow 2013-10-26 18:30:41 -06:00
parent e9eb066c0d
commit c9ba4a9756
1 changed files with 37 additions and 36 deletions

View File

@ -240,8 +240,8 @@ detail is available in later sections.
importlib.machinery.ModuleSpec (new)
------------------------------------
A specification for a module's import-system-related state. See the
`ModuleSpec`_ section below for a more detailed description.
An encapsulation of a module's import-system-related state during import.
See the `ModuleSpec`_ section below for a more detailed description.
* ModuleSpec(name, loader, \*, origin=None, loader_state=None, is_package=None)
@ -263,13 +263,6 @@ Attributes:
* has_location (RO-property) - a flag indicating whether or not the
module's "origin" attribute refers to a location.
Instance Methods:
* module_repr() - provide a repr string for the spec'ed module;
non-locatable modules will use their origin (e.g. "built-in").
* init_module_attrs(module) - set any of a module's import-related
attributes that aren't already set.
importlib.util Additions
------------------------
@ -289,6 +282,12 @@ Other API Additions
importlib.find_loader() (which it replaces), but return a spec instead
of a loader.
For finders:
* importlib.abc.MetaPathFinder.find_spec(name, path) and
importlib.abc.PathEntryFinder.find_spec(name) will return a module
spec to use during import.
For loaders:
* importlib.abc.Loader.exec_module(module) will execute a module in its
@ -443,34 +442,30 @@ factory functions nor any the instance methods.
How Loading Will Work
=====================
Here is an outline of what ModuleSpec does during loading::
def load(self):
if not hasattr(self.loader, 'exec_module'):
module = self.loader.load_module(self.name)
self.init_module_attrs(module)
return sys.modules[self.name]
Here is an outline of what the import machinery does during loading,
adjusted to take advantage of the module's spec and the new loader API::
module = None
if hasattr(self.loader, 'create_module'):
module = self.loader.create_module(self)
if hasattr(spec.loader, 'create_module'):
module = spec.loader.create_module(spec)
if module is None:
module = ModuleType(self.name)
self.init_module_attrs(module)
module = ModuleType(spec.name)
# The import-related module attributes get set here:
_init_module_attrs(module)
sys.modules[self.name] = module
if not hasattr(spec.loader, 'exec_module'):
module = spec.loader.load_module(spec.name)
else:
sys.modules[spec.name] = module
try:
self.loader.exec_module(module)
spec.loader.exec_module(module)
except BaseException:
try:
del sys.modules[self.name]
del sys.modules[spec.name]
except KeyError:
pass
raise
return sys.modules[self.name]
Note: no "load" method is actually implemented as part of the public
ModuleSpec API.
module_to_return = sys.modules[spec.name]
These steps are exactly what Loader.load_module() is already
expected to do. Loaders will thus be simplified since they will only
@ -494,8 +489,8 @@ Each of the following names is an attribute on ModuleSpec objects. A
value of None indicates "not set". This contrasts with module
objects where the attribute simply doesn't exist. Most of the
attributes correspond to the import-related attributes of modules. Here
is the mapping. The reverse of this mapping is used by
ModuleSpec.init_module_attrs().
is the mapping. The reverse of this mapping describes how the import
machinery sets the module attributes right before calling exec_module().
========================== ==============
On ModuleSpec On Modules
@ -523,7 +518,7 @@ involve changing the state of a module's spec.
"origin" is a string for the name of the place from which the module
originates. See `origin`_ above. Aside from the informational value,
it is also used in module_repr(). In the case of a spec where
it is also used in the module's repr. In the case of a spec where
"has_location" is true, ``__file__`` is set to the value of "origin".
For built-in modules "origin" would be set to "built-in".
@ -655,7 +650,7 @@ Simply setting loader_state or adding functionality to a custom
finder or loader will likely be a better fit and should be tried first.
However, as long as a subclass still fulfills the requirements of the
import system, objects of that type are completely fine as the return
value of Finder.find_spec().
value of Finder.find_spec(). The same points apply to duck-typing.
Existing Types
@ -695,7 +690,7 @@ the cost until later.
**PathEntryFinder.find_spec(name)**
Finders will return ModuleSpec objects when find_spec() is
Finders must return ModuleSpec objects when find_spec() is
called. This new method replaces find_module() and
find_loader() (in the PathEntryFinder case). If a loader does
not have find_spec(), find_module() and find_loader() are
@ -715,8 +710,9 @@ Currently a path entry finder may return (None, portions) from
find_loader() to indicate it found part of a possible namespace
package. To achieve the same effect, find_spec() must return a spec
with "loader" set to None (a.k.a. not set) and with
submodule_search_locations set to the same portions as were provided by
find_loader(). It's up to PathFinder how to handle such specs.
submodule_search_locations set to the same portions as would have been
provided by find_loader(). It's up to PathFinder how to handle such
specs.
Loaders
-------
@ -777,6 +773,11 @@ Other Changes
* The various finders and loaders provided by importlib will be
updated to comply with this proposal.
* Any other implmentations of or dependencies on the import-related APIs
(particularly finders and loaders) in the stdlib will be likewise
adjusted to this PEP. While they should continue to work, any such
changes that get missed should be considered bugs for the Python 3.4.x
series.
* The spec for the ``__main__`` module will reflect how the interpreter
was started. For instance, with ``-m`` the spec's name will be that
of the run module, while ``__main__.__name__`` will still be