diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2020-10-15 21:05:12 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-15 21:05:12 (GMT) |
commit | 967fddae2fe48f297563c358bdbdde1e2cfed4ee (patch) | |
tree | fb06b0011109dc74ce1ace5b0bfc27c8de315774 | |
parent | aeb66c1abbf4ec214e2e80eb972546996d1a1571 (diff) | |
download | cpython-967fddae2fe48f297563c358bdbdde1e2cfed4ee.zip cpython-967fddae2fe48f297563c358bdbdde1e2cfed4ee.tar.gz cpython-967fddae2fe48f297563c358bdbdde1e2cfed4ee.tar.bz2 |
[3.8] bpo-41855: Fix duplicate results in FastPath.zip_children() (#22404)
* bpo-41855: Backport fixes from importlib_metadata 1.5.2.
* Add blurb.
* Add anchor for finders and loaders
-rw-r--r-- | Doc/library/importlib.metadata.rst | 39 | ||||
-rw-r--r-- | Doc/reference/import.rst | 2 | ||||
-rw-r--r-- | Lib/importlib/metadata.py | 5 | ||||
-rw-r--r-- | Lib/test/test_importlib/test_zip.py | 11 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2020-09-24-16-45-59.bpo-41855.q6Y1nm.rst | 4 |
5 files changed, 34 insertions, 27 deletions
diff --git a/Doc/library/importlib.metadata.rst b/Doc/library/importlib.metadata.rst index dc6b66c..15e58b8 100644 --- a/Doc/library/importlib.metadata.rst +++ b/Doc/library/importlib.metadata.rst @@ -1,8 +1,8 @@ .. _using: -========================== - Using importlib.metadata -========================== +================================= + Using :mod:`!importlib.metadata` +================================= .. note:: This functionality is provisional and may deviate from the usual @@ -12,8 +12,8 @@ package metadata. Built in part on Python's import system, this library intends to replace similar functionality in the `entry point API`_ and `metadata API`_ of ``pkg_resources``. Along with -``importlib.resources`` in `Python 3.7 -and newer`_ (backported as `importlib_resources`_ for older versions of +:mod:`importlib.resources` in Python 3.7 +and newer (backported as `importlib_resources`_ for older versions of Python), this can eliminate the need to use the older and less efficient ``pkg_resources`` package. @@ -21,9 +21,9 @@ By "installed package" we generally mean a third-party package installed into Python's ``site-packages`` directory via tools such as `pip <https://pypi.org/project/pip/>`_. Specifically, it means a package with either a discoverable ``dist-info`` or ``egg-info`` -directory, and metadata defined by `PEP 566`_ or its older specifications. +directory, and metadata defined by :pep:`566` or its older specifications. By default, package metadata can live on the file system or in zip archives on -``sys.path``. Through an extension mechanism, the metadata can live almost +:data:`sys.path`. Through an extension mechanism, the metadata can live almost anywhere. @@ -134,7 +134,7 @@ Distribution files You can also get the full set of files contained within a distribution. The ``files()`` function takes a distribution package name and returns all of the files installed by this distribution. Each file object returned is a -``PackagePath``, a `pathlib.Path`_ derived object with additional ``dist``, +``PackagePath``, a :class:`pathlib.Path` derived object with additional ``dist``, ``size``, and ``hash`` properties as indicated by the metadata. For example:: >>> util = [p for p in files('wheel') if 'util.py' in str(p)][0] # doctest: +SKIP @@ -203,18 +203,18 @@ instance:: >>> d.metadata['License'] # doctest: +SKIP 'MIT' -The full set of available metadata is not described here. See `PEP 566 -<https://www.python.org/dev/peps/pep-0566/>`_ for additional details. +The full set of available metadata is not described here. See :pep:`566` +for additional details. Extending the search algorithm ============================== -Because package metadata is not available through ``sys.path`` searches, or +Because package metadata is not available through :data:`sys.path` searches, or package loaders directly, the metadata for a package is found through import -system `finders`_. To find a distribution package's metadata, -``importlib.metadata`` queries the list of `meta path finders`_ on -`sys.meta_path`_. +system :ref:`finders <finders-and-loaders>`. To find a distribution package's metadata, +``importlib.metadata`` queries the list of :term:`meta path finders <meta path finder>` on +:data:`sys.meta_path`. The default ``PathFinder`` for Python includes a hook that calls into ``importlib.metadata.MetadataPathFinder`` for finding distributions @@ -224,7 +224,7 @@ The abstract class :py:class:`importlib.abc.MetaPathFinder` defines the interface expected of finders by Python's import system. ``importlib.metadata`` extends this protocol by looking for an optional ``find_distributions`` callable on the finders from -``sys.meta_path`` and presents this extended interface as the +:data:`sys.meta_path` and presents this extended interface as the ``DistributionFinder`` abstract base class, which defines this abstract method:: @@ -247,20 +247,13 @@ a custom finder, return instances of this derived ``Distribution`` in the .. _`entry point API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points .. _`metadata API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#metadata-api -.. _`Python 3.7 and newer`: https://docs.python.org/3/library/importlib.html#module-importlib.resources .. _`importlib_resources`: https://importlib-resources.readthedocs.io/en/latest/index.html -.. _`PEP 566`: https://www.python.org/dev/peps/pep-0566/ -.. _`finders`: https://docs.python.org/3/reference/import.html#finders-and-loaders -.. _`meta path finders`: https://docs.python.org/3/glossary.html#term-meta-path-finder -.. _`sys.meta_path`: https://docs.python.org/3/library/sys.html#sys.meta_path -.. _`pathlib.Path`: https://docs.python.org/3/library/pathlib.html#pathlib.Path .. rubric:: Footnotes .. [#f1] Technically, the returned distribution metadata object is an - `email.message.Message - <https://docs.python.org/3/library/email.message.html#email.message.EmailMessage>`_ + :class:`email.message.EmailMessage` instance, but this is an implementation detail, and not part of the stable API. You should only use dictionary-like methods and syntax to access the metadata contents. diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst index 1c98aab..ca23200 100644 --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -202,6 +202,8 @@ named module, the two module objects will *not* be the same. By contrast, reinitialise the module contents by rerunning the module's code. +.. _finders-and-loaders: + Finders and loaders ------------------- diff --git a/Lib/importlib/metadata.py b/Lib/importlib/metadata.py index 831f593..9d2285c 100644 --- a/Lib/importlib/metadata.py +++ b/Lib/importlib/metadata.py @@ -408,8 +408,8 @@ class FastPath: names = zip_path.root.namelist() self.joinpath = zip_path.joinpath - return ( - posixpath.split(child)[0] + return dict.fromkeys( + child.split(posixpath.sep, 1)[0] for child in names ) @@ -475,7 +475,6 @@ class MetadataPathFinder(DistributionFinder): ) - class PathDistribution(Distribution): def __init__(self, path): """Construct a distribution from a path to the metadata directory. diff --git a/Lib/test/test_importlib/test_zip.py b/Lib/test/test_importlib/test_zip.py index 9568c22..18d39f6 100644 --- a/Lib/test/test_importlib/test_zip.py +++ b/Lib/test/test_importlib/test_zip.py @@ -3,11 +3,15 @@ import unittest from contextlib import ExitStack from importlib.metadata import ( - distribution, entry_points, files, PackageNotFoundError, version, + distribution, entry_points, files, PackageNotFoundError, + version, distributions, ) from importlib.resources import path +from test.support import requires_zlib + +@requires_zlib class TestZip(unittest.TestCase): root = 'test.test_importlib.data' @@ -46,7 +50,12 @@ class TestZip(unittest.TestCase): path = str(file.dist.locate_file(file)) assert '.whl/' in path, path + def test_one_distribution(self): + dists = list(distributions(path=sys.path[:1])) + assert len(dists) == 1 + +@requires_zlib class TestEgg(TestZip): def setUp(self): # Find the path to the example-*.egg so we can add it to the front of diff --git a/Misc/NEWS.d/next/Library/2020-09-24-16-45-59.bpo-41855.q6Y1nm.rst b/Misc/NEWS.d/next/Library/2020-09-24-16-45-59.bpo-41855.q6Y1nm.rst new file mode 100644 index 0000000..c499c10 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-09-24-16-45-59.bpo-41855.q6Y1nm.rst @@ -0,0 +1,4 @@ +In ``importlib.metadata``, fix issue where multiple children can be returned +from ``FastPath.zip_children()``. Backport of +`python-devs/importlib_metadata#117 +<https://gitlab.com/python-devs/importlib_metadata/-/issues/117>`_. |