From 69ec928e5959b17f0d6489d06a0e36d2759b6ba2 Mon Sep 17 00:00:00 2001 From: kokotatan Date: Sat, 3 Oct 2026 20:20:32 +0900 Subject: [PATCH] Preserve recent multiple-use metadata fields in JSON Assisted-by: OpenAI Codex --- importlib_metadata/_adapters.py | 5 ++++- newsfragments/+json-multiple-use.bugfix.rst | 1 + tests/test_api.py | 23 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 newsfragments/+json-multiple-use.bugfix.rst diff --git a/importlib_metadata/_adapters.py b/importlib_metadata/_adapters.py index 0bc23000..3c5a7db9 100644 --- a/importlib_metadata/_adapters.py +++ b/importlib_metadata/_adapters.py @@ -59,6 +59,9 @@ class Message(email.message.Message): FoldedCase, [ 'Classifier', + 'Import-Name', + 'Import-Namespace', + 'License-File', 'Obsoletes-Dist', 'Platform', 'Project-URL', @@ -72,7 +75,7 @@ class Message(email.message.Message): ) ) """ - Keys that may be indicated multiple times per PEP 566. + Keys that may be indicated multiple times in Core Metadata. """ def __new__(cls, orig: email.message.Message): diff --git a/newsfragments/+json-multiple-use.bugfix.rst b/newsfragments/+json-multiple-use.bugfix.rst new file mode 100644 index 00000000..cad1ea4a --- /dev/null +++ b/newsfragments/+json-multiple-use.bugfix.rst @@ -0,0 +1 @@ +Return ``License-File``, ``Import-Name``, and ``Import-Namespace`` as lists in JSON-compatible metadata, including when only one value is present, and retain all repeated values as required by PEP 566. diff --git a/tests/test_api.py b/tests/test_api.py index 1468e0a9..23b117af 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -281,6 +281,29 @@ def test_as_json_odd_case(self): assert len(md['requires_dist']) == 2 assert md['keywords'] == ['SAMPLE', 'PACKAGE'] + @fixtures.parameterize( + dict(key='License-File', values=['LICENSE', 'NOTICE']), + dict(key='Import-Name', values=['example', '_example ; private']), + dict(key='Import-Namespace', values=['example', 'another']), + dict(key='Import-Name', values=['']), + ) + def test_as_json_recent_multiple_use_fields(self, key, values): + for count in range(1, len(values) + 1): + with self.subTest(count=count): + selected = values[:count] + headers = '\n'.join( + f'{key if index == 0 else key.upper()}: {value}' + for index, value in enumerate(selected) + ) + content = ( + 'Metadata-Version: 2.5\nName: distinfo-pkg\nVersion: 1.0.0\n' + + headers + ) + path = self.site_dir / 'distinfo_pkg-1.0.0.dist-info' / 'METADATA' + path.write_text(content, encoding='utf-8') + md = metadata('distinfo-pkg').json + assert md[key.lower().replace('-', '_')] == selected + class LegacyDots(fixtures.DistInfoPkgWithDotLegacy, unittest.TestCase): def test_name_normalization(self):