From 9837340eb3715a366be94378aa6f6186d7a0b059 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 | 31 +++++++++++++++++++++++++++++++ twine/package.py | 11 +++++++++++ 2 files changed, 42 insertions(+) diff --git a/tests/test_package.py b/tests/test_package.py index ee666130..1b36c665 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -467,3 +467,34 @@ 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( + "Metadata-Version: 2.1\n" + "Name: test-package\n" + "Version: 1.0.0\n" + "License-File: LICENSE\n", + True, + id="invalid License-File", + ), + pytest.param( + "Metadata-Version: 2.4\n" + "Name: test-package\n" + "Version: 1.0.0\n" + "License-File: LICENSE\n", + 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 26da5e54..509a2d45 100644 --- a/twine/package.py +++ b/twine/package.py @@ -21,6 +21,7 @@ from typing import Any, Dict, List, NamedTuple, Optional, Tuple from packaging import metadata +from packaging import version from rich import print from twine import bdist @@ -142,6 +143,16 @@ def from_filename(cls, filename: str, comment: Optional[str]) -> "PackageFile": ) ) ) + # 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: