From 880a6219a16911817214827020f272b4b03b54b4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Dec 2022 16:37:30 -0500 Subject: [PATCH] Mark `PackageMetadata.__getitem__` as deprecated for missing values. Ref #371. --- CHANGES.rst | 7 +++++++ importlib_metadata/_adapters.py | 22 ++++++++++++++++++++++ tests/test_api.py | 8 ++++++++ 3 files changed, 37 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index cf7dcf16..a2df91a3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,10 @@ +v5.2.0 +====== + +* #371: Deprecated expectation that ``PackageMetadata.__getitem__`` + will return ``None`` for missing keys. In the future, it will raise a + ``KeyError``. + v5.1.0 ====== diff --git a/importlib_metadata/_adapters.py b/importlib_metadata/_adapters.py index aa460d3e..e33cba5e 100644 --- a/importlib_metadata/_adapters.py +++ b/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 @@ def __init__(self, *args, **kwargs): 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/tests/test_api.py b/tests/test_api.py index f65287a5..504d0553 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -141,6 +141,14 @@ def test_importlib_metadata_version(self): resolved = version('importlib-metadata') assert re.match(self.version_pattern, resolved) + def test_missing_key_legacy(self): + """ + Requesting a missing key will still return None, but warn. + """ + md = metadata('distinfo-pkg') + with suppress_known_deprecation(): + assert md['does-not-exist'] is None + @staticmethod def _test_files(files): root = files[0].root