Repository: pypi/warehouse

Issue:
PEP 621-style license field shows the entire license text
**Describe the bug**
When using PEP 621-style project metadata with a license file (see https://peps.python.org/pep-0621/#license), the entire license text is shown in the Meta -> License section of a package on pypi. For an example see https://pypi.org/project/pytest-logikal/ and the relevant pyproject.toml file https://github.com/logikal-io/pytest-logikal/blob/main/pyproject.toml#L10. Showing the entire license text makes the Meta section almost useless by pushing the rest of the metadata quite far to the bottom.

**Expected behavior**
The license text should be hidden by default and perhaps shown with a modal upon clicking "see full text". Note that the issue is similar to https://github.com/pypi/warehouse/issues/1354, however, it is a little different due to the PEP 621 standard causing this behavior. With more and more projects adopting PEP 621 I would expect this to be a bigger issue over time.


Discussion:
Some related discussion is here: https://github.com/FFY00/meson-python/issues/129
Thanks for the context! I think that the current UX needs to be improved regardless of how PEP 639 goes, the "Meta" section is really messed up for anyone who follows PEP 621 right now (which is the accepted standard at the moment). I think showing the (short) license name from the trove classifier there is more than enough (when available) with a fallback to the first line of the license text or so. PEP 639 would use different fields anyways, so even if that gets accepted you need to be able to deal with all the "legacy" approaches like PEP 621 or anything from before.

It seems to me that that area in the PyPI UI is not meant for displaying anything more than a short-ish line anyhow, so at the very least the excess text should be truncated/hidden.
I must add that currently setuptools just copies the contents of the referenced license file into the "License" field in PKG-INFO, so it can be interpreted that the contents of the field are the actual license text of the package. I can imagine that displaying the entire license on PyPI would be potentially useful, just not in the way it is done at the moment.
Lastly, I see what you mean by https://packaging.python.org/en/latest/specifications/core-metadata/#license and so I believe setuptools does the right thing, we should probably just not use the license field together with the trove classifiers (in light of the core metadata specification). Nonetheless, even if someone used the license field according to the PyPA specification and added a longer custom license text there, the Meta section on PyPI would be still messed up, so I think this is indeed a valid bug, regardless of the slightly confusing specifications surrounding license information.
> Some related discussion is here: https://github.com/FFY00/meson-python/issues/129

The repo moved, here is the new link: https://github.com/mesonbuild/meson-python/issues/129

Resolving patch:
diff --git a/warehouse/packaging/views.py b/warehouse/packaging/views.py
--- a/warehouse/packaging/views.py
+++ b/warehouse/packaging/views.py
@@ -117,6 +117,10 @@ def release_detail(release, request):
     # first line only.
     short_license = release.license.split("\n")[0] if release.license else None
 
+    # Truncate the short license if we were unable to shorten it with newlines
+    if short_license and len(short_license) > 100 and short_license == release.license:
+        short_license = short_license[:100] + "..."
+
     if license_classifiers and short_license:
         license = f"{license_classifiers} ({short_license})"
     else:


Test patch:
diff --git a/tests/unit/packaging/test_views.py b/tests/unit/packaging/test_views.py
--- a/tests/unit/packaging/test_views.py
+++ b/tests/unit/packaging/test_views.py
@@ -400,6 +400,20 @@ def test_multiple_licenses_from_classifiers(self, db_request):
 
         assert result["license"] == "BSD License, MIT License"
 
+    def test_long_singleline_license(self, db_request):
+        """When license metadata contains no newlines, it gets truncated"""
+        release = ReleaseFactory.create(
+            license="Multiline License is very long, so long that it is far longer than"
+            " 100 characters, it's really so long, how terrible"
+        )
+
+        result = views.release_detail(release, db_request)
+
+        assert result["license"] == (
+            "Multiline License is very long, so long that it is far longer than 100 "
+            "characters, it's really so lo..."
+        )
+
 
 class TestEditProjectButton:
     def test_edit_project_button_returns_project(self):