Issue #26914: Fix formatting of lists in PEP 420

Patch by Ned Batchelder.
This commit is contained in:
Berker Peksag 2016-05-03 10:36:46 +03:00
parent 30ad98f0b1
commit 936292e0c4
1 changed files with 78 additions and 69 deletions

View File

@ -28,20 +28,25 @@ Terminology
Within this PEP:
* "package" refers to Python packages as defined by Python's import
statement.
* "distribution" refers to separately installable sets of Python
modules as stored in the Python package index, and installed by
distutils or setuptools.
* "vendor package" refers to groups of files installed by an
operating system's packaging mechanism (e.g. Debian or Redhat
packages install on Linux systems).
* "regular package" refers to packages as they are implemented in
Python 3.2 and earlier.
* "portion" refers to a set of files in a single directory (possibly
stored in a zip file) that contribute to a namespace package.
* "legacy portion" refers to a portion that uses ``__path__``
manipulation in order to implement namespace packages.
* "package" refers to Python packages as defined by Python's import
statement.
* "distribution" refers to separately installable sets of Python
modules as stored in the Python package index, and installed by
distutils or setuptools.
* "vendor package" refers to groups of files installed by an
operating system's packaging mechanism (e.g. Debian or Redhat
packages install on Linux systems).
* "regular package" refers to packages as they are implemented in
Python 3.2 and earlier.
* "portion" refers to a set of files in a single directory (possibly
stored in a zip file) that contribute to a namespace package.
* "legacy portion" refers to a portion that uses ``__path__``
manipulation in order to implement namespace packages.
This PEP defines a new type of package, the "namespace package".
@ -115,16 +120,16 @@ A namespace package will not be constrained by a fixed ``__path__``,
computed from the parent path at namespace package creation time.
Consider the standard library ``encodings`` package:
1. Suppose that ``encodings`` becomes a namespace package.
1. Suppose that ``encodings`` becomes a namespace package.
2. It sometimes gets imported during interpreter startup to
initialize the standard io streams.
2. It sometimes gets imported during interpreter startup to
initialize the standard io streams.
3. An application modifies ``sys.path`` after startup and wants to
contribute additional encodings from new path entries.
3. An application modifies ``sys.path`` after startup and wants to
contribute additional encodings from new path entries.
4. An attempt is made to import an encoding from an ``encodings``
portion that is found on a path entry added in step 3.
4. An attempt is made to import an encoding from an ``encodings``
portion that is found on a path entry added in step 3.
If the import system was restricted to only finding portions along the
value of ``sys.path`` that existed at the time the ``encodings``
@ -158,29 +163,29 @@ iterate over each directory in the parent path as it does in Python
3.2. While looking for a module or package named "foo", for each
directory in the parent path:
* If ``<directory>/foo/__init__.py`` is found, a regular package is
imported and returned.
* If ``<directory>/foo/__init__.py`` is found, a regular package is
imported and returned.
* If not, but ``<directory>/foo.{py,pyc,so,pyd}`` is found, a module
is imported and returned. The exact list of extension varies by
platform and whether the -O flag is specified. The list here is
representative.
* If not, but ``<directory>/foo.{py,pyc,so,pyd}`` is found, a module
is imported and returned. The exact list of extension varies by
platform and whether the -O flag is specified. The list here is
representative.
* If not, but ``<directory>/foo`` is found and is a directory, it is
recorded and the scan continues with the next directory in the
parent path.
* If not, but ``<directory>/foo`` is found and is a directory, it is
recorded and the scan continues with the next directory in the
parent path.
* Otherwise the scan continues with the next directory in the parent
path.
* Otherwise the scan continues with the next directory in the parent
path.
If the scan completes without returning a module or package, and at
least one directory was recorded, then a namespace package is created.
The new namespace package:
* Has a ``__path__`` attribute set to an iterable of the path strings
that were found and recorded during the scan.
* Has a ``__path__`` attribute set to an iterable of the path strings
that were found and recorded during the scan.
* Does not have a ``__file__`` attribute.
* Does not have a ``__file__`` attribute.
Note that if "import foo" is executed and "foo" is found as a
namespace package (using the above rules), then "foo" is immediately
@ -247,20 +252,20 @@ Differences between namespace packages and regular packages
Namespace packages and regular packages are very similar. The
differences are:
* Portions of namespace packages need not all come from the same
directory structure, or even from the same loader. Regular packages
are self-contained: all parts live in the same directory hierarchy.
* Portions of namespace packages need not all come from the same
directory structure, or even from the same loader. Regular packages
are self-contained: all parts live in the same directory hierarchy.
* Namespace packages have no ``__file__`` attribute.
* Namespace packages have no ``__file__`` attribute.
* Namespace packages' ``__path__`` attribute is a read-only iterable
of strings, which is automatically updated when the parent path is
modified.
* Namespace packages' ``__path__`` attribute is a read-only iterable
of strings, which is automatically updated when the parent path is
modified.
* Namespace packages have no ``__init__.py`` module.
* Namespace packages have no ``__init__.py`` module.
* Namespace packages have a different type of object for their
``__loader__`` attribute.
* Namespace packages have a different type of object for their
``__loader__`` attribute.
Namespace packages in the standard library
@ -441,29 +446,29 @@ ImportWarning would be raised.
Nick Coghlan presented a list of his objections to this proposal [4]_.
They are:
1. Implicit package directories go against the Zen of Python.
1. Implicit package directories go against the Zen of Python.
2. Implicit package directories pose awkward backwards compatibility
challenges.
2. Implicit package directories pose awkward backwards compatibility
challenges.
3. Implicit package directories introduce ambiguity into file system
layouts.
3. Implicit package directories introduce ambiguity into file system
layouts.
4. Implicit package directories will permanently entrench current
newbie-hostile behavior in ``__main__``.
4. Implicit package directories will permanently entrench current
newbie-hostile behavior in ``__main__``.
Nick later gave a detailed response to his own objections [5]_, which
is summarized here:
1. The practicality of this PEP wins over other proposals and the
status quo.
1. The practicality of this PEP wins over other proposals and the
status quo.
2. Minor backward compatibility issues are okay, as long as they are
properly documented.
2. Minor backward compatibility issues are okay, as long as they are
properly documented.
3. This will be addressed in PEP 395.
3. This will be addressed in PEP 395.
4. This will also be addressed in PEP 395.
4. This will also be addressed in PEP 395.
The inclusion of namespace packages in the standard library was
motivated by Martin v. Löwis, who wanted the ``encodings`` package to
@ -547,17 +552,21 @@ optional protocol is added to PEP 302 loaders. Loaders can implement a
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.
* If an exception occurs in ``module_repr()``, the exception is
caught and discarded, and the calculation of the module's repr
continues as if ``module_repr()`` did not exist.
* 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.
* 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.
* If an exception occurs in ``module_repr()``, the exception is
caught and discarded, and the calculation of the module's repr
continues as if ``module_repr()`` did not exist.
* 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.
Here is a snippet showing how namespace module reprs are calculated
from its loader::