bpo-44246: Restore compatibility in entry_points (GH-26468)

* bpo-44246: Entry points performance improvements.

From importlib_metadata 4.3.1.

* bpo-44246: Sync with importlib_metadata 4.4
This commit is contained in:
Jason R. Coombs 2021-05-31 12:19:42 -04:00 committed by GitHub
parent 410b70d39d
commit c34ed08d97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 125 additions and 1 deletions

View file

@ -204,7 +204,100 @@ class EntryPoint(
return all(map(operator.eq, params.values(), attrs))
class EntryPoints(tuple):
class DeprecatedList(list):
"""
Allow an otherwise immutable object to implement mutability
for compatibility.
>>> recwarn = getfixture('recwarn')
>>> dl = DeprecatedList(range(3))
>>> dl[0] = 1
>>> dl.append(3)
>>> del dl[3]
>>> dl.reverse()
>>> dl.sort()
>>> dl.extend([4])
>>> dl.pop(-1)
4
>>> dl.remove(1)
>>> dl += [5]
>>> dl + [6]
[1, 2, 5, 6]
>>> dl + (6,)
[1, 2, 5, 6]
>>> dl.insert(0, 0)
>>> dl
[0, 1, 2, 5]
>>> dl == [0, 1, 2, 5]
True
>>> dl == (0, 1, 2, 5)
True
>>> len(recwarn)
1
"""
_warn = functools.partial(
warnings.warn,
"EntryPoints list interface is deprecated. Cast to list if needed.",
DeprecationWarning,
stacklevel=2,
)
def __setitem__(self, *args, **kwargs):
self._warn()
return super().__setitem__(*args, **kwargs)
def __delitem__(self, *args, **kwargs):
self._warn()
return super().__delitem__(*args, **kwargs)
def append(self, *args, **kwargs):
self._warn()
return super().append(*args, **kwargs)
def reverse(self, *args, **kwargs):
self._warn()
return super().reverse(*args, **kwargs)
def extend(self, *args, **kwargs):
self._warn()
return super().extend(*args, **kwargs)
def pop(self, *args, **kwargs):
self._warn()
return super().pop(*args, **kwargs)
def remove(self, *args, **kwargs):
self._warn()
return super().remove(*args, **kwargs)
def __iadd__(self, *args, **kwargs):
self._warn()
return super().__iadd__(*args, **kwargs)
def __add__(self, other):
if not isinstance(other, tuple):
self._warn()
other = tuple(other)
return self.__class__(tuple(self) + other)
def insert(self, *args, **kwargs):
self._warn()
return super().insert(*args, **kwargs)
def sort(self, *args, **kwargs):
self._warn()
return super().sort(*args, **kwargs)
def __eq__(self, other):
if not isinstance(other, tuple):
self._warn()
other = tuple(other)
return tuple(self).__eq__(other)
class EntryPoints(DeprecatedList):
"""
An immutable collection of selectable EntryPoint objects.
"""
@ -215,6 +308,14 @@ class EntryPoints(tuple):
"""
Get the EntryPoint in self matching name.
"""
if isinstance(name, int):
warnings.warn(
"Accessing entry points by index is deprecated. "
"Cast to tuple if needed.",
DeprecationWarning,
stacklevel=2,
)
return super().__getitem__(name)
try:
return next(iter(self.select(name=name)))
except StopIteration:

View file

@ -130,6 +130,22 @@ class APITests(
assert expected.category is DeprecationWarning
assert "Construction of dict of EntryPoints is deprecated" in str(expected)
def test_entry_points_by_index(self):
"""
Prior versions of Distribution.entry_points would return a
tuple that allowed access by index.
Capture this now deprecated use-case
See python/importlib_metadata#300 and bpo-44246.
"""
eps = distribution('distinfo-pkg').entry_points
with warnings.catch_warnings(record=True) as caught:
eps[0]
# check warning
expected = next(iter(caught))
assert expected.category is DeprecationWarning
assert "Accessing entry points by index is deprecated" in str(expected)
def test_entry_points_groups_getitem(self):
# Prior versions of entry_points() returned a dict. Ensure
# that callers using '.__getitem__()' are supported but warned to

View file

@ -0,0 +1,7 @@
In ``importlib.metadata``, restore compatibility in the result from
``Distribution.entry_points`` (``EntryPoints``) to honor expectations in
older implementations and issuing deprecation warnings for these cases: A. ``EntryPoints`` objects are once again mutable, allowing for ``sort()``
and other list-based mutation operations. Avoid deprecation warnings by
casting to a mutable sequence (e.g. ``list(dist.entry_points).sort()``). B. ``EntryPoints`` results once again allow for access by index. To avoid
deprecation warnings, cast the result to a Sequence first (e.g.
``tuple(dist.entry_points)[0]``).