Skip to content
25 changes: 15 additions & 10 deletions setuptools/dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,22 +406,27 @@ def _normalize_requires(self):

def _finalize_license_expression(self) -> None:
"""Normalize license and license_expression."""
classifiers = self.metadata.get_classifiers()
license_classifiers = {cl for cl in classifiers if cl.startswith("License :: ")}

if license_classifiers:
SetuptoolsDeprecationWarning.emit(
"License classifier are deprecated in favor of the license expression.",
"Please remove the classifiers:\n\n" + "\n".join(license_classifiers),
see_url="https://peps.python.org/pep-0639/",
due_date=(2027, 2, 17), # Introduced 2025-02-17
)

license_expr = self.metadata.license_expression
if license_expr:
normalized = canonicalize_license_expression(license_expr)
if license_expr != normalized:
InformationOnly.emit(f"Normalizing '{license_expr}' to '{normalized}'")
self.metadata.license_expression = normalized

for cl in self.metadata.get_classifiers():
if not cl.startswith("License :: "):
continue
SetuptoolsDeprecationWarning.emit(
"License classifier are deprecated in favor of the license expression.",
f"Please remove the '{cl}' classifier.",
see_url="https://peps.python.org/pep-0639/",
due_date=(2027, 2, 17), # Introduced 2025-02-17
)
if license_classifiers:
# Filter classifiers but preserve "static-ness" of metadata
Copy link
Contributor Author

@abravalheri abravalheri Feb 17, 2025

Choose a reason for hiding this comment

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

Not sure if we should indeed preserve the "static-ness" of the classifiers, or simply let Dynamic: classifier appear in the core metadata (we are modifying them after all...)

filtered = [cl for cl in classifiers if cl not in license_classifiers]
self.metadata.set_classifiers(classifiers.__class__(filtered))

def _finalize_license_files(self) -> None:
"""Compute names of all license files which should be included."""
Expand Down
8 changes: 4 additions & 4 deletions setuptools/tests/config/test_apply_pyprojecttoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,18 +327,18 @@ def test_license_expression_with_bad_classifier(tmp_path):
"README",
f"{text}\n \"License :: OSI Approved :: MIT License\"\n]",
)
msg = "License classifier are deprecated(?:.|\n)*'License :: OSI Approved :: MIT License'"
with pytest.raises(SetuptoolsDeprecationWarning, match=msg):
msg = "License classifier are deprecated"
with pytest.raises(SetuptoolsDeprecationWarning, match=msg) as exc:
pyprojecttoml.apply_configuration(makedist(tmp_path), pyproject)
assert "License :: OSI Approved :: MIT License" in str(exc.value)

with warnings.catch_warnings():
warnings.simplefilter("ignore", SetuptoolsDeprecationWarning)
dist = pyprojecttoml.apply_configuration(makedist(tmp_path), pyproject)
# Check license classifier is still included
# Check 'License :: OSI Approved :: MIT License' is removed
assert dist.metadata.get_classifiers() == [
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python",
"License :: OSI Approved :: MIT License",
]


Expand Down
Loading