From 7fe14892934fee3b86439164887e4c93a8524de5 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Wed, 27 Nov 2024 11:53:38 +0100 Subject: [PATCH] Accommodate for invalid metadata produced by setuptools See pypa/setuptools#4759. --- tests/test_package.py | 25 +++++++++++++++++++++++++ twine/package.py | 11 +++++++++++ 2 files changed, 36 insertions(+) diff --git a/tests/test_package.py b/tests/test_package.py index cf3da5e8..878231ba 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -457,3 +457,28 @@ def test_malformed_from_file(monkeypatch): def test_package_from_egg(): filename = "tests/fixtures/twine-3.3.0-py3.9.egg" package_file.PackageFile.from_filename(filename, comment=None) + + +@pytest.mark.parametrize( + "read_data, filtered", + [ + pytest.param( + b"Metadata-Version: 2.1\nName: test-package\nVersion: 1.0.0\nLicense-File: LICENSE", + True, + id="invalid License-File", + ), + pytest.param( + b"Metadata-Version: 2.4\nName: test-package\nVersion: 1.0.0\nLicense-File: LICENSE", + False, + id="valid License-File", + ), + ] +) +def test_setuptools_license_file(read_data, filtered, monkeypatch): + """Drop License-File metadata entries if Metadata-Version is less than 2.4""" + monkeypatch.setattr(package_file.wheel.Wheel, "read", lambda _: read_data) + filename = "tests/fixtures/twine-1.5.0-py2.py3-none-any.whl" + + package = package_file.PackageFile.from_filename(filename, comment=None) + meta = package.metadata_dictionary() + assert filtered != ("license_files" in meta) diff --git a/twine/package.py b/twine/package.py index 8f3cbee9..00c74177 100644 --- a/twine/package.py +++ b/twine/package.py @@ -21,6 +21,7 @@ from typing import Any, Dict, List, NamedTuple, Optional, Sequence, Tuple, Union from packaging import metadata +from packaging import version from rich import print from twine import bdist @@ -141,6 +142,16 @@ def from_filename(cls, filename: str, comment: Optional[str]) -> "PackageFile": for key in unparsed ) ) + # setuptools emits License-File metadata fields while declaring + # Metadata-Version 2.1. This is invalid because the metadata + # specification does not allow to add arbitrary fields, and because + # the semantic implemented by setuptools is different than the one + # described in PEP 639. However, rejecting these packages would be + # too disruptive. Drop License-File metadata entries from the data + # sent to the package index if the declared metadata version is less + # than 2.4. + if version.Version(meta.get("metadata_version", "0")) < version.Version("2.4"): + meta.pop("license_files", None) try: metadata.Metadata.from_raw(meta) except metadata.ExceptionGroup as group: