* Relax the constraint that m.__file__ must exist (except for built-ins)

* Describe the loader.module_repr() protocol.
 * Fix some misspellings.
This commit is contained in:
Barry Warsaw 2012-05-04 15:40:10 -04:00
parent 6f8d74ea28
commit 4742457cda
1 changed files with 51 additions and 10 deletions

View File

@ -13,13 +13,13 @@ Post-History:
Abstract Abstract
======== ========
Namespace packages are a mechanism for splitting a single Python Namespace packages are a mechanism for splitting a single Python package
package across multiple directories on disk. In current Python across multiple directories on disk. In current Python versions, an algorithm
versions, an algorithm to compute the packages ``__path__`` must be to compute the packages ``__path__`` must be formulated. With the enhancement
formulated. With the enhancement proposed here, the import machinery proposed here, the import machinery itself will construct the list of
itself will construct the list of directories that make up the directories that make up the package. This PEP builds upon previous work,
package. This PEP builds upon the work started in rejected PEPs 382 documented in PEP 382 and PEP 402. Those PEPs have since been rejected in
and 402. An implementation of this PEP is at [1]_. favor of this one. An implementation of this PEP is at [1]_.
Terminology Terminology
=========== ===========
@ -111,7 +111,7 @@ Namespace packages cannot contain an ``__init__.py``. As a
consequence, ``pkgutil.extend_path`` and consequence, ``pkgutil.extend_path`` and
``pkg_resources.declare_namespace`` become obsolete for purposes of ``pkg_resources.declare_namespace`` become obsolete for purposes of
namespace package creation. There will be no marker file or directory namespace package creation. There will be no marker file or directory
for specifing a namespace package. for specifying a namespace package.
During import processing, the import machinery will continue to During import processing, the import machinery will continue to
iterate over each directory in the parent path as it does in Python iterate over each directory in the parent path as it does in Python
@ -171,7 +171,9 @@ the string that will be recorded and later used as a component of the
namespace module's ``__path__``, as described above. This string must namespace module's ``__path__``, as described above. This string must
not contain a trailing path separator. not contain a trailing path separator.
There is no impact on PEP 302 "loaders". The specification expands PEP 302 loaders to include an optional method called
``module_repr()`` which if present, is used to generate module object reprs.
See the section below for further details.
If an existing finder is not updated to support returning a string If an existing finder is not updated to support returning a string
from ``find_module``, the only impact is that such a finder will be from ``find_module``, the only impact is that such a finder will be
@ -200,7 +202,7 @@ If the portions are installed in different locations, two different
"foo" directories would be in directories that are on ``sys.path``. "foo" directories would be in directories that are on ``sys.path``.
"foo/bar" would be in one of these sys.path entries, and "foo/baz" "foo/bar" would be in one of these sys.path entries, and "foo/baz"
would be in the other. Upon removal of "foo.bar", the "foo/bar" and would be in the other. Upon removal of "foo.bar", the "foo/bar" and
corresonding "foo" directories can be completely removed. But corresponding "foo" directories can be completely removed. But
"foo/baz" and its corresponding "foo" directory cannot be removed. "foo/baz" and its corresponding "foo" directory cannot be removed.
It is also possible to have the "foo.bar" portion installed in a It is also possible to have the "foo.bar" portion installed in a
@ -258,6 +260,45 @@ simplest possible solution working. It will be possible at a later
date to add such features. Several possible ways to do so were date to add such features. Several possible ways to do so were
discussed in the referenced email thread. discussed in the referenced email thread.
Module reprs
============
Previously, module reprs were hard coded based on assumptions about a module's
``__file__`` attribute. If this attribute existed and was a string, it was
assumed to be a file system path, and the module object's repr would include
this in its value. The only exception was that PEP 302 reserved missing
``__file__`` attributes to built-in modules, and in CPython, this assumption
was baked into the module object's implementation. Because of this
restriction, some module contained contrived ``__file__`` values that did not
reflect file system paths, and which could cause unexpected problems later
(e.g. ``os.path.join()`` on a non-path ``__file__`` would return gibberish).
This PEP relaxes this constraint, and leaves the setting of ``__file__`` to
the purview of the loader producing the module. Loaders may opt to leave
``__file__`` unset if no file system path is appropriate. This means that the
definitive way to determine the origin of a module is to check its
``__loader__`` attribute.
For example, namespace packages as described in this PEP will have no
``__file__`` attribute because no corresponding file exists. In order to
provide flexibility and descriptiveness in the reprs of such modules, a new
optional protocol is added to PEP 302 loaders. Loaders can implement a
``module_repr()`` method which takes a single argument, the module object.
This method should return the string to be used verbatim as the repr of the
module. The rules for producing a module repr are now standardized as:
* If the module has an ``__loader__`` and that loader has a ``module_repr()``
method, call it with a single argument, which is the module object. The
value returned is used as the module's repr.
* Exceptions from ``module_repr()`` are ignored, and the following steps
are used instead.
* If the module has an ``__file__`` attribute, this is used as part of the
module's repr.
* If the module has no ``__file__`` but does have an ``__loader__``, then the
loader's repr is used as part of the module's repr.
* Otherwise, just use the module's ``__name__`` in the repr.
References References
========== ==========