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)) 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. An immutable collection of selectable EntryPoint objects.
""" """
@ -215,6 +308,14 @@ class EntryPoints(tuple):
""" """
Get the EntryPoint in self matching name. 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: try:
return next(iter(self.select(name=name))) return next(iter(self.select(name=name)))
except StopIteration: except StopIteration:

View file

@ -130,6 +130,22 @@ class APITests(
assert expected.category is DeprecationWarning assert expected.category is DeprecationWarning
assert "Construction of dict of EntryPoints is deprecated" in str(expected) 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): def test_entry_points_groups_getitem(self):
# Prior versions of entry_points() returned a dict. Ensure # Prior versions of entry_points() returned a dict. Ensure
# that callers using '.__getitem__()' are supported but warned to # 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]``).