diff -r 79e82db88f37 pep-0420.txt --- a/pep-0420.txt Thu Apr 28 18:44:22 2016 -0700 +++ b/pep-0420.txt Mon May 02 18:53:27 2016 -0400 @@ -28,20 +28,25 @@ 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 @@ 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 @@ 3.2. While looking for a module or package named "foo", for each directory in the parent path: - * If ``/foo/__init__.py`` is found, a regular package is - imported and returned. +* If ``/foo/__init__.py`` is found, a regular package is + imported and returned. - * If not, but ``/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 ``/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 ``/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 ``/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 @@ 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 @@ 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 @@ 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::