diff --git a/lib/importlib_metadata/__init__.py b/lib/importlib_metadata/__init__.py index 304b6d48..26a1388c 100644 --- a/lib/importlib_metadata/__init__.py +++ b/lib/importlib_metadata/__init__.py @@ -139,6 +139,7 @@ class DeprecatedTuple: 1 """ + # Do not remove prior to 2023-05-01 or Python 3.13 _warn = functools.partial( warnings.warn, "EntryPoint tuple interface is deprecated. Access members by name.", @@ -293,8 +294,7 @@ class EntryPoints(tuple): Select entry points from self that match the given parameters (typically group and/or name). """ - candidates = (_py39compat.ep_matches(ep, **params) for ep in self) - return EntryPoints(ep for ep, predicate in candidates if predicate) + return EntryPoints(ep for ep in self if _py39compat.ep_matches(ep, **params)) @property def names(self): diff --git a/lib/importlib_metadata/_adapters.py b/lib/importlib_metadata/_adapters.py index aa460d3e..e33cba5e 100644 --- a/lib/importlib_metadata/_adapters.py +++ b/lib/importlib_metadata/_adapters.py @@ -1,8 +1,20 @@ +import functools +import warnings import re import textwrap import email.message from ._text import FoldedCase +from ._compat import pypy_partial + + +# Do not remove prior to 2024-01-01 or Python 3.14 +_warn = functools.partial( + warnings.warn, + "Implicit None on return values is deprecated and will raise KeyErrors.", + DeprecationWarning, + stacklevel=pypy_partial(2), +) class Message(email.message.Message): @@ -39,6 +51,16 @@ class Message(email.message.Message): def __iter__(self): return super().__iter__() + def __getitem__(self, item): + """ + Warn users that a ``KeyError`` can be expected when a + mising key is supplied. Ref python/importlib_metadata#371. + """ + res = super().__getitem__(item) + if res is None: + _warn() + return res + def _repair_headers(self): def redent(value): "Correct for RFC822 indentation" diff --git a/lib/importlib_metadata/_meta.py b/lib/importlib_metadata/_meta.py index 37ee43e6..259b15ba 100644 --- a/lib/importlib_metadata/_meta.py +++ b/lib/importlib_metadata/_meta.py @@ -30,18 +30,19 @@ class PackageMetadata(Protocol): """ -class SimplePath(Protocol): +class SimplePath(Protocol[_T]): """ A minimal subset of pathlib.Path required by PathDistribution. """ - def joinpath(self) -> 'SimplePath': + def joinpath(self) -> _T: ... # pragma: no cover - def __truediv__(self) -> 'SimplePath': + def __truediv__(self, other: Union[str, _T]) -> _T: ... # pragma: no cover - def parent(self) -> 'SimplePath': + @property + def parent(self) -> _T: ... # pragma: no cover def read_text(self) -> str: diff --git a/lib/importlib_metadata/_py39compat.py b/lib/importlib_metadata/_py39compat.py index cf9cc124..cde4558f 100644 --- a/lib/importlib_metadata/_py39compat.py +++ b/lib/importlib_metadata/_py39compat.py @@ -1,7 +1,7 @@ """ Compatibility layer with Python 3.8/3.9 """ -from typing import TYPE_CHECKING, Any, Optional, Tuple +from typing import TYPE_CHECKING, Any, Optional if TYPE_CHECKING: # pragma: no cover # Prevent circular imports on runtime. @@ -22,27 +22,14 @@ def normalized_name(dist: Distribution) -> Optional[str]: return Prepared.normalize(getattr(dist, "name", None) or dist.metadata['Name']) -def ep_matches(ep: EntryPoint, **params) -> Tuple[EntryPoint, bool]: +def ep_matches(ep: EntryPoint, **params) -> bool: """ Workaround for ``EntryPoint`` objects without the ``matches`` method. - For the sake of convenience, a tuple is returned containing not only the - boolean value corresponding to the predicate evalutation, but also a compatible - ``EntryPoint`` object that can be safely used at a later stage. - - For example, the following sequences of expressions should be compatible: - - # Sequence 1: using the compatibility layer - candidates = (_py39compat.ep_matches(ep, **params) for ep in entry_points) - [ep for ep, predicate in candidates if predicate] - - # Sequence 2: using Python 3.9+ - [ep for ep in entry_points if ep.matches(**params)] """ try: - return ep, ep.matches(**params) + return ep.matches(**params) except AttributeError: from . import EntryPoint # -> delay to prevent circular imports. # Reconstruct the EntryPoint object to make sure it is compatible. - _ep = EntryPoint(ep.name, ep.value, ep.group) - return _ep, _ep.matches(**params) + return EntryPoint(ep.name, ep.value, ep.group).matches(**params) diff --git a/package/requirements-package.txt b/package/requirements-package.txt index 6260d288..82782772 100644 --- a/package/requirements-package.txt +++ b/package/requirements-package.txt @@ -1,5 +1,5 @@ apscheduler==3.9.1.post1 -importlib-metadata==5.0.0 +importlib-metadata==5.2.0 importlib-resources==5.10.1 pyinstaller==5.6.2 pyopenssl==22.1.0 diff --git a/requirements.txt b/requirements.txt index cffb49c5..4fc06668 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,7 +18,7 @@ gntp==1.0.3 html5lib==1.1 httpagentparser==1.9.5 idna==3.4 -importlib-metadata==5.0.0 +importlib-metadata==5.2.0 importlib-resources==5.10.1 git+https://github.com/Tautulli/ipwhois.git@master#egg=ipwhois IPy==1.01