]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39022, bpo-38594: Sync with importlib_metadata 1.3 (GH-17568)
authorJason R. Coombs <jaraco@jaraco.com>
Wed, 11 Dec 2019 01:05:10 +0000 (20:05 -0500)
committerGitHub <noreply@github.com>
Wed, 11 Dec 2019 01:05:10 +0000 (20:05 -0500)
* bpo-39022, bpo-38594: Sync with importlib_metadata 1.3 including improved docs for custom finders and better serialization support in EntryPoints.

* ðŸ“œðŸ¤– Added by blurb_it.

* Correct module reference

Doc/library/importlib.metadata.rst
Lib/importlib/metadata.py
Lib/test/test_importlib/test_main.py
Misc/NEWS.d/next/Library/2019-12-10-23-34-48.bpo-39022.QDtIxI.rst [new file with mode: 0644]

index 4a4a8f7dfa0f871eb6d73a19e24608fc8dac1c49..dc6b66ca384d0423ea91350d7e7259641a4419d1 100644 (file)
@@ -216,9 +216,9 @@ system `finders`_.  To find a distribution package's metadata,
 ``importlib.metadata`` queries the list of `meta path finders`_ on
 `sys.meta_path`_.
 
-By default ``importlib.metadata`` installs a finder for distribution packages
-found on the file system.  This finder doesn't actually find any *packages*,
-but it can find the packages' metadata.
+The default ``PathFinder`` for Python includes a hook that calls into
+``importlib.metadata.MetadataPathFinder`` for finding distributions
+loaded from typical file-system-based paths.
 
 The abstract class :py:class:`importlib.abc.MetaPathFinder` defines the
 interface expected of finders by Python's import system.
@@ -239,9 +239,9 @@ properties indicating the path to search and names to match and may
 supply other relevant context.
 
 What this means in practice is that to support finding distribution package
-metadata in locations other than the file system, you should derive from
-``Distribution`` and implement the ``load_metadata()`` method. Then from
-your finder, return instances of this derived ``Distribution`` in the
+metadata in locations other than the file system, subclass
+``Distribution`` and implement the abstract methods. Then from
+a custom finder, return instances of this derived ``Distribution`` in the
 ``find_distributions()`` method.
 
 
index 8cb45ec1ef3a299dd9b21f1fddb61d50324cb7ee..53f9fb5934668415345fb718e16afdabd19bc1ee 100644 (file)
@@ -37,7 +37,8 @@ class PackageNotFoundError(ModuleNotFoundError):
     """The package was not found."""
 
 
-class EntryPoint(collections.namedtuple('EntryPointBase', 'name value group')):
+class EntryPoint(
+        collections.namedtuple('EntryPointBase', 'name value group')):
     """An entry point as defined by Python packaging conventions.
 
     See `the packaging docs on entry points
@@ -107,6 +108,12 @@ class EntryPoint(collections.namedtuple('EntryPointBase', 'name value group')):
         """
         return iter((self.name, self))
 
+    def __reduce__(self):
+        return (
+            self.__class__,
+            (self.name, self.value, self.group),
+            )
+
 
 class PackagePath(pathlib.PurePosixPath):
     """A reference to a path in a package"""
@@ -334,10 +341,21 @@ class DistributionFinder(MetaPathFinder):
     """
 
     class Context:
+        """
+        Keyword arguments presented by the caller to
+        ``distributions()`` or ``Distribution.discover()``
+        to narrow the scope of a search for distributions
+        in all DistributionFinders.
+
+        Each DistributionFinder may expect any parameters
+        and should attempt to honor the canonical
+        parameters defined below when appropriate.
+        """
 
         name = None
         """
         Specific name for which a distribution finder should match.
+        A name of ``None`` matches all distributions.
         """
 
         def __init__(self, **kwargs):
@@ -347,6 +365,9 @@ class DistributionFinder(MetaPathFinder):
         def path(self):
             """
             The path that a distribution finder should search.
+
+            Typically refers to Python package paths and defaults
+            to ``sys.path``.
             """
             return vars(self).get('path', sys.path)
 
index 4d5b1273d9d1031d63c2130c6f1b6ef0c64a50b0..c5f1dbbae325ed049a32ff0d349ec24b07249cda 100644 (file)
@@ -1,6 +1,8 @@
 # coding: utf-8
 
 import re
+import json
+import pickle
 import textwrap
 import unittest
 import importlib.metadata
@@ -181,3 +183,34 @@ class DirectoryTest(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase):
         with self.add_sys_path(egg):
             with self.assertRaises(PackageNotFoundError):
                 version('foo')
+
+
+class TestEntryPoints(unittest.TestCase):
+    def __init__(self, *args):
+        super(TestEntryPoints, self).__init__(*args)
+        self.ep = importlib.metadata.EntryPoint('name', 'value', 'group')
+
+    def test_entry_point_pickleable(self):
+        revived = pickle.loads(pickle.dumps(self.ep))
+        assert revived == self.ep
+
+    def test_immutable(self):
+        """EntryPoints should be immutable"""
+        with self.assertRaises(AttributeError):
+            self.ep.name = 'badactor'
+
+    def test_repr(self):
+        assert 'EntryPoint' in repr(self.ep)
+        assert 'name=' in repr(self.ep)
+        assert "'name'" in repr(self.ep)
+
+    def test_hashable(self):
+        """EntryPoints should be hashable"""
+        hash(self.ep)
+
+    def test_json_dump(self):
+        """
+        json should not expect to be able to dump an EntryPoint
+        """
+        with self.assertRaises(Exception):
+            json.dumps(self.ep)
diff --git a/Misc/NEWS.d/next/Library/2019-12-10-23-34-48.bpo-39022.QDtIxI.rst b/Misc/NEWS.d/next/Library/2019-12-10-23-34-48.bpo-39022.QDtIxI.rst
new file mode 100644 (file)
index 0000000..4af21be
--- /dev/null
@@ -0,0 +1 @@
+Update importliib.metadata to include improvements from importlib_metadata 1.3 including better serialization of EntryPoints and improved documentation for custom finders.
\ No newline at end of file