[PEP 451] Changes related to the find_spec() target module.

This commit is contained in:
Eric Snow 2013-11-02 15:08:19 -06:00
parent a1c321efbb
commit f729d23f82
1 changed files with 19 additions and 32 deletions

View File

@ -278,7 +278,7 @@ finders. See the `Factory Functions`_ section below for more detail.
Other API Additions Other API Additions
------------------- -------------------
* importlib.find_spec(name, path=None, existing=None) will work exactly * importlib.find_spec(name, path=None, target=None) will work exactly
the same as importlib.find_loader() (which it replaces), but return a the same as importlib.find_loader() (which it replaces), but return a
spec instead of a loader. spec instead of a loader.
@ -493,7 +493,7 @@ Here is the corresponding outline for reload()::
name = module.__spec__.name name = module.__spec__.name
except AttributeError: except AttributeError:
name = module.__name__ name = module.__name__
spec = find_spec(name, existing=module) spec = find_spec(name, target=module)
if sys.modules.get(name) is not module: if sys.modules.get(name) is not module:
raise ImportError raise ImportError
@ -521,7 +521,7 @@ see if the module was already in sys.modules. Now, by the time
exec_module() is called during load (not reload) the import machinery exec_module() is called during load (not reload) the import machinery
would already have placed the module in sys.modules. This is part of would already have placed the module in sys.modules. This is part of
the reason why find_spec() has the reason why find_spec() has
`the "existing" parameter <The "existing" parameter of find_spec()>`_. `the "target" parameter <The "target" parameter of find_spec()>`_.
The semantics of reload will remain essentially the same as they exist The semantics of reload will remain essentially the same as they exist
already [#reload-semantics-fix]_. The impact of this PEP on some kinds already [#reload-semantics-fix]_. The impact of this PEP on some kinds
@ -697,9 +697,9 @@ than returned directly. As is currently the case without the PEP, if a
loader would be costly to create, that loader can be designed to defer loader would be costly to create, that loader can be designed to defer
the cost until later. the cost until later.
**MetaPathFinder.find_spec(name, path=None, existing=None)** **MetaPathFinder.find_spec(name, path=None, target=None)**
**PathEntryFinder.find_spec(name, existing=None)** **PathEntryFinder.find_spec(name, target=None)**
Finders must return ModuleSpec objects when find_spec() is Finders must return ModuleSpec objects when find_spec() is
called. This new method replaces find_module() and called. This new method replaces find_module() and
@ -714,8 +714,8 @@ especially considering PathEntryFinder.find_loader() was just
added in Python 3.3. However, the extra complexity and a less-than- added in Python 3.3. However, the extra complexity and a less-than-
explicit method name aren't worth it. explicit method name aren't worth it.
The "existing" parameter of find_spec() The "target" parameter of find_spec()
--------------------------------------- -------------------------------------
A module object with the same name as the "name" argument (or None, the A module object with the same name as the "name" argument (or None, the
default) should be passed in to "exising". This argument allows the default) should be passed in to "exising". This argument allows the
@ -727,26 +727,26 @@ Through find_spec() the finder will always identify the loader it
will return in the spec. In the case of reload, at this point the will return in the spec. In the case of reload, at this point the
finder should also decide whether or not the loader supports loading finder should also decide whether or not the loader supports loading
into the module-to-be-reloaded (which was passed in to find_spec() as into the module-to-be-reloaded (which was passed in to find_spec() as
"existing"). This decision may entail consulting with the loader. If "target"). This decision may entail consulting with the loader. If
the finder determines that the loader does not support reloading that the finder determines that the loader does not support reloading that
module, it should either find another loader or return None (indicating module, it should either find another loader or raise ImportError
that it could not "find" the module). This reload decision is important (completely stopping import of the module). This reload decision is
since, as noted in `How Reloading Will Work`_, loaders will no longer be important since, as noted in `How Reloading Will Work`_, loaders will
able to trivially identify a reload situation on their own. no longer be able to trivially identify a reload situation on their own.
Two alternatives were presented to the "existing" parameter: Two alternatives were presented to the "target" parameter:
Loader.supports_reload() and adding "existing" to Loader.exec_module() Loader.supports_reload() and adding "target" to Loader.exec_module()
instead of find_spec(). supports_reload() was the initial approach to instead of find_spec(). supports_reload() was the initial approach to
the reload situation. [#supports_reload]_ However, there was some the reload situation. [#supports_reload]_ However, there was some
opposition to the loader-specific, reload-centric approach. opposition to the loader-specific, reload-centric approach.
[#supports_reload_considered_harmful]_ [#supports_reload_considered_harmful]_
As to "existing" on exec_module(), the loader may need other information As to "target" on exec_module(), the loader may need other information
from the existing module (or spec) during reload, more than just "does from the target module (or spec) during reload, more than just "does
this loader support reloading this module", that is no longer available this loader support reloading this module", that is no longer available
with the move away from load_module(). A proposal on the table was to with the move away from load_module(). A proposal on the table was to
add something like "existing" to exec_module(). [#exec_module_existing]_ add something like "target" to exec_module(). [#exec_module_target]_
However, putting "existing" on find_spec() instead is more in line with However, putting "target" on find_spec() instead is more in line with
the goals of this PEP. Furthermore, it obviates the need for the goals of this PEP. Furthermore, it obviates the need for
supports_reload(). supports_reload().
@ -835,19 +835,6 @@ Other Changes
* importlib.reload() will now make use of the per-module import lock. * importlib.reload() will now make use of the per-module import lock.
Open Issues
===========
\* In the `Finders`_ section, the PEP specifies returning None (or using
a different loader) when the found loader does not support loading into
an existing module (e.g during reload). An alternative to returning
None would be to raise ImportError with a message like "the loader does
not support reloading the module". This may actually be a better
approach since "could not find a loader" and "the found loader won't
work" are different situations that a single return value (None) may not
sufficiently represent.
Reference Implementation Reference Implementation
======================== ========================
@ -943,7 +930,7 @@ References
.. [#supports_reload_considered_harmful] .. [#supports_reload_considered_harmful]
https://mail.python.org/pipermail/python-dev/2013-October/129971.html https://mail.python.org/pipermail/python-dev/2013-October/129971.html
.. [#exec_module_existing] .. [#exec_module_target]
https://mail.python.org/pipermail/python-dev/2013-October/129933.html https://mail.python.org/pipermail/python-dev/2013-October/129933.html
Copyright Copyright