Skip to content

Commit b7a0109

Browse files
authored
bpo-39022, bpo-38594: Sync with importlib_metadata 1.3 (pythonGH-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
1 parent d0802d0 commit b7a0109

File tree

4 files changed

+62
-7
lines changed

4 files changed

+62
-7
lines changed

β€ŽDoc/library/importlib.metadata.rstβ€Ž

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,9 @@ system `finders`_. To find a distribution package's metadata,
216216
``importlib.metadata`` queries the list of `meta path finders`_ on
217217
`sys.meta_path`_.
218218

219-
By default ``importlib.metadata`` installs a finder for distribution packages
220-
found on the file system. This finder doesn't actually find any *packages*,
221-
but it can find the packages' metadata.
219+
The default ``PathFinder`` for Python includes a hook that calls into
220+
``importlib.metadata.MetadataPathFinder`` for finding distributions
221+
loaded from typical file-system-based paths.
222222

223223
The abstract class :py:class:`importlib.abc.MetaPathFinder` defines the
224224
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
239239
supply other relevant context.
240240

241241
What this means in practice is that to support finding distribution package
242-
metadata in locations other than the file system, you should derive from
243-
``Distribution`` and implement the ``load_metadata()`` method. Then from
244-
your finder, return instances of this derived ``Distribution`` in the
242+
metadata in locations other than the file system, subclass
243+
``Distribution`` and implement the abstract methods. Then from
244+
a custom finder, return instances of this derived ``Distribution`` in the
245245
``find_distributions()`` method.
246246

247247

β€ŽLib/importlib/metadata.pyβ€Ž

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ class PackageNotFoundError(ModuleNotFoundError):
3737
"""The package was not found."""
3838

3939

40-
class EntryPoint(collections.namedtuple('EntryPointBase', 'name value group')):
40+
class EntryPoint(
41+
collections.namedtuple('EntryPointBase', 'name value group')):
4142
"""An entry point as defined by Python packaging conventions.
4243
4344
See `the packaging docs on entry points
@@ -107,6 +108,12 @@ def __iter__(self):
107108
"""
108109
return iter((self.name, self))
109110

111+
def __reduce__(self):
112+
return (
113+
self.__class__,
114+
(self.name, self.value, self.group),
115+
)
116+
110117

111118
class PackagePath(pathlib.PurePosixPath):
112119
"""A reference to a path in a package"""
@@ -334,10 +341,21 @@ class DistributionFinder(MetaPathFinder):
334341
"""
335342

336343
class Context:
344+
"""
345+
Keyword arguments presented by the caller to
346+
``distributions()`` or ``Distribution.discover()``
347+
to narrow the scope of a search for distributions
348+
in all DistributionFinders.
349+
350+
Each DistributionFinder may expect any parameters
351+
and should attempt to honor the canonical
352+
parameters defined below when appropriate.
353+
"""
337354

338355
name = None
339356
"""
340357
Specific name for which a distribution finder should match.
358+
A name of ``None`` matches all distributions.
341359
"""
342360

343361
def __init__(self, **kwargs):
@@ -347,6 +365,9 @@ def __init__(self, **kwargs):
347365
def path(self):
348366
"""
349367
The path that a distribution finder should search.
368+
369+
Typically refers to Python package paths and defaults
370+
to ``sys.path``.
350371
"""
351372
return vars(self).get('path', sys.path)
352373

β€ŽLib/test/test_importlib/test_main.pyβ€Ž

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# coding: utf-8
22

33
import re
4+
import json
5+
import pickle
46
import textwrap
57
import unittest
68
import importlib.metadata
@@ -181,3 +183,34 @@ def test_egg(self):
181183
with self.add_sys_path(egg):
182184
with self.assertRaises(PackageNotFoundError):
183185
version('foo')
186+
187+
188+
class TestEntryPoints(unittest.TestCase):
189+
def __init__(self, *args):
190+
super(TestEntryPoints, self).__init__(*args)
191+
self.ep = importlib.metadata.EntryPoint('name', 'value', 'group')
192+
193+
def test_entry_point_pickleable(self):
194+
revived = pickle.loads(pickle.dumps(self.ep))
195+
assert revived == self.ep
196+
197+
def test_immutable(self):
198+
"""EntryPoints should be immutable"""
199+
with self.assertRaises(AttributeError):
200+
self.ep.name = 'badactor'
201+
202+
def test_repr(self):
203+
assert 'EntryPoint' in repr(self.ep)
204+
assert 'name=' in repr(self.ep)
205+
assert "'name'" in repr(self.ep)
206+
207+
def test_hashable(self):
208+
"""EntryPoints should be hashable"""
209+
hash(self.ep)
210+
211+
def test_json_dump(self):
212+
"""
213+
json should not expect to be able to dump an EntryPoint
214+
"""
215+
with self.assertRaises(Exception):
216+
json.dumps(self.ep)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Update importliib.metadata to include improvements from importlib_metadata 1.3 including better serialization of EntryPoints and improved documentation for custom finders.

0 commit comments

Comments
Β (0)