diff --git a/CHANGES.rst b/CHANGES.rst index cf7dcf16..4a03eb0b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,18 @@ +v6.0.0 +====== + +* #371: When a key is missing from metadata, raise a ``KeyError`` + instead of returning ``None``, matching the usual expectation for + mapping objects and also the protocol definition. + + Projects should update to expect the ``KeyError`` or wrap the call + to replace a ``KeyError`` with a ``None`` return, e.g.:: + + try: + value = metadata(pkg)['Name'] + except KeyError: + value = None + v5.1.0 ====== diff --git a/importlib_metadata/_adapters.py b/importlib_metadata/_adapters.py index aa460d3e..c8576cd9 100644 --- a/importlib_metadata/_adapters.py +++ b/importlib_metadata/_adapters.py @@ -39,6 +39,20 @@ def __init__(self, *args, **kwargs): def __iter__(self): return super().__iter__() + def __getitem__(self, item): + """ + Prefer dict-like behavior for __getitem__ when keys are missing. + >>> msg = Message(email.message.Message()) + >>> msg['thing'] + Traceback (most recent call last): + ... + KeyError: 'thing' + """ + res = super().__getitem__(item) + if res is None: + raise KeyError(item) + 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..d3ae8144 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(self): + """ + Attempting to request missing metadata raises KeyError. + """ + md = metadata('distinfo-pkg') + with self.assertRaises(KeyError): + md['does-not-exist'] + @staticmethod def _test_files(files): root = files[0].root