summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2019-12-11 01:05:10 (GMT)
committerGitHub <noreply@github.com>2019-12-11 01:05:10 (GMT)
commitb7a0109cd2bafaa21a4d50aad307e901c68f9156 (patch)
tree744785e406bf815353d7c29c69c8bfe59e24f2c0
parentd0802d07d2c864b95480a9b24c7cc050e19189d5 (diff)
downloadcpython-b7a0109cd2bafaa21a4d50aad307e901c68f9156.zip
cpython-b7a0109cd2bafaa21a4d50aad307e901c68f9156.tar.gz
cpython-b7a0109cd2bafaa21a4d50aad307e901c68f9156.tar.bz2
bpo-39022, bpo-38594: Sync with importlib_metadata 1.3 (GH-17568)
* 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
-rw-r--r--Doc/library/importlib.metadata.rst12
-rw-r--r--Lib/importlib/metadata.py23
-rw-r--r--Lib/test/test_importlib/test_main.py33
-rw-r--r--Misc/NEWS.d/next/Library/2019-12-10-23-34-48.bpo-39022.QDtIxI.rst1
4 files changed, 62 insertions, 7 deletions
diff --git a/Doc/library/importlib.metadata.rst b/Doc/library/importlib.metadata.rst
index 4a4a8f7..dc6b66c 100644
--- a/Doc/library/importlib.metadata.rst
+++ b/Doc/library/importlib.metadata.rst
@@ -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.
diff --git a/Lib/importlib/metadata.py b/Lib/importlib/metadata.py
index 8cb45ec..53f9fb5 100644
--- a/Lib/importlib/metadata.py
+++ b/Lib/importlib/metadata.py
@@ -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)
diff --git a/Lib/test/test_importlib/test_main.py b/Lib/test/test_importlib/test_main.py
index 4d5b127..c5f1dbb 100644
--- a/Lib/test/test_importlib/test_main.py
+++ b/Lib/test/test_importlib/test_main.py
@@ -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
index 0000000..4af21be
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-12-10-23-34-48.bpo-39022.QDtIxI.rst
@@ -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