Skip to content

Preserve recent multiple-use metadata fields in JSON - #545

Merged
jaraco merged 3 commits into
python:mainfrom
kokotatan:fix-json-multiple-use-metadata
Nov 9, 2026
Merged

jaraco merged 3 commits into
python:mainfrom
kokotatan:fix-json-multiple-use-metadata

Conversation

@kokotatan

Copy link
Copy Markdown
Contributor

metadata(name).json currently returns only the first License-File, Import-Name, or Import-Namespace value as a string. For example, metadata containing both License-File: LICENSE and License-File: NOTICE becomes {"license_file": "LICENSE"}, losing the second file.

Add these three fields to the existing multiple-use field set. Core Metadata defines License-File as multiple-use since 2.4, and Import-Name and Import-Namespace since 2.5. PEP 566's JSON conversion requires multiple-use fields to be lists, including when only one value appears.

The public API regression covers single and repeated values, differently cased duplicate headers, preservation of the ; private suffix, and an empty Import-Name. All seven subcases fail before the fix. A Towncrier bugfix fragment is included.

Validation on Windows with Python 3.12:

  • Focused JSON tests: 4 passed, 11 subtests passed.
  • tox -e py312: 216 passed, 3 skipped, and one pre-existing environment failure in the tests._path.build doctest because this Windows account cannot create symlinks (WinError 1314). The same doctest fails on clean upstream c5acd62.
  • The tox run passes mypy (30 files), Ruff, formatting, and package-description checks. _adapters.py has 100% coverage; overall coverage is 98%.
  • tox -e docs: Sphinx's warning-as-error build and sphinx-lint pass.

AI assistance: implemented and tested with OpenAI Codex; independently reviewed by a second Codex agent.

Comment thread tests/test_api.py Outdated
Comment on lines +284 to +305
@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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there already tests for multi-use fields? If so, I'd prefer to re-use that test. "recent multiple use fields" will have a stale meaning as soon as this is committed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see now there's no test in particular for the multiple use keys. Still, I don't think a regression test is needed to prove that multiple-use keys is working; it's already covered by the checks for keywords above.

jaraco and others added 2 commits November 7, 2026 14:15
That multiple-use keys become lists is already covered by the
'keywords' and 'requires_dist' assertions in the as_json tests, so the
new keys need no test of their own. Its name would also have gone stale
as soon as it was committed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jaraco
jaraco merged commit 93b8d15 into python:main Nov 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants