We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN 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.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `warehouse/packaging/views.py`
Content:
```
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 # See the License for the specific language governing permissions and
11 # limitations under the License.
12 
13 from natsort import natsorted
14 from pyramid.httpexceptions import HTTPMovedPermanently, HTTPNotFound
15 from pyramid.view import view_config
16 from sqlalchemy.orm.exc import NoResultFound
17 
18 from warehouse.accounts.models import User
19 from warehouse.cache.origin import origin_cache
20 from warehouse.packaging.models import File, Project, Release, Role
21 from warehouse.utils import readme
22 
23 
24 @view_config(
25     route_name="packaging.project",
26     context=Project,
27     renderer="packaging/detail.html",
28     decorator=[
29         origin_cache(
30             1 * 24 * 60 * 60, stale_if_error=5 * 24 * 60 * 60  # 1 day, 5 days stale
31         )
32     ],
33     has_translations=True,
34 )
35 def project_detail(project, request):
36     if project.name != request.matchdict.get("name", project.name):
37         return HTTPMovedPermanently(request.current_route_path(name=project.name))
38 
39     try:
40         release = (
41             request.db.query(Release)
42             .filter(Release.project == project)
43             .order_by(
44                 Release.yanked,
45                 Release.is_prerelease.nullslast(),
46                 Release._pypi_ordering.desc(),
47             )
48             .limit(1)
49             .one()
50         )
51     except NoResultFound:
52         raise HTTPNotFound
53 
54     return release_detail(release, request)
55 
56 
57 @view_config(
58     route_name="packaging.release",
59     context=Release,
60     renderer="packaging/detail.html",
61     decorator=[
62         origin_cache(
63             1 * 24 * 60 * 60, stale_if_error=5 * 24 * 60 * 60  # 1 day, 5 days stale
64         )
65     ],
66     has_translations=True,
67 )
68 def release_detail(release, request):
69     project = release.project
70 
71     # Check if the requested version is equivalent but not exactly the same as
72     # the release's version. Use `.get` because this view is used by
73     # `project_detail` and there may not be a version.
74     #
75     # This also handles the case where both the version and the project name
76     # need adjusted, and handles it in a single redirect.
77     if release.version != request.matchdict.get("version", release.version):
78         return HTTPMovedPermanently(
79             request.current_route_path(name=project.name, version=release.version)
80         )
81 
82     # It's possible that the requested version was correct (or not provided),
83     # but we still need to adjust the project name.
84     if project.name != request.matchdict.get("name", project.name):
85         return HTTPMovedPermanently(request.current_route_path(name=project.name))
86 
87     # Grab the rendered description if it exists, and if it doesn't, then we will render
88     # it inline.
89     # TODO: Remove the fallback to rendering inline and only support displaying the
90     #       already rendered content.
91     if release.description.html:
92         description = release.description.html
93     else:
94         description = readme.render(
95             release.description.raw, release.description.content_type
96         )
97 
98     # Get all of the maintainers for this project.
99     maintainers = [
100         r.user
101         for r in (
102             request.db.query(Role)
103             .join(User)
104             .filter(Role.project == project)
105             .distinct(User.username)
106             .order_by(User.username)
107             .all()
108         )
109     ]
110 
111     # Get the license from both the `Classifier` and `License` metadata fields
112     license_classifiers = ", ".join(
113         c.split(" :: ")[-1] for c in release.classifiers if c.startswith("License")
114     )
115 
116     # Make a best effort when the entire license text is given by using the
117     # first line only.
118     short_license = release.license.split("\n")[0] if release.license else None
119 
120     if license_classifiers and short_license:
121         license = f"{license_classifiers} ({short_license})"
122     else:
123         license = license_classifiers or short_license or None
124 
125     # We cannot easily sort naturally in SQL, sort here and pass to template
126     sdists = natsorted(
127         release.files.filter(File.packagetype == "sdist").all(),
128         reverse=True,
129         key=lambda f: f.filename,
130     )
131     bdists = natsorted(
132         release.files.filter(File.packagetype != "sdist").all(),
133         reverse=True,
134         key=lambda f: f.filename,
135     )
136 
137     return {
138         "project": project,
139         "release": release,
140         "description": description,
141         "files": sdists + bdists,
142         "sdists": sdists,
143         "bdists": bdists,
144         "latest_version": project.latest_version,
145         "all_versions": project.all_versions,
146         "maintainers": maintainers,
147         "license": license,
148     }
149 
150 
151 @view_config(
152     route_name="includes.edit-project-button",
153     context=Project,
154     renderer="includes/manage-project-button.html",
155     uses_session=True,
156     permission="manage:project",
157     has_translations=True,
158 )
159 def edit_project_button(project, request):
160     return {"project": project}
161
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

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 @@
     # 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:

{"golden_diff": "diff --git a/warehouse/packaging/views.py b/warehouse/packaging/views.py\n--- a/warehouse/packaging/views.py\n+++ b/warehouse/packaging/views.py\n@@ -117,6 +117,10 @@\n     # first line only.\n     short_license = release.license.split(\"\\n\")[0] if release.license else None\n \n+    # Truncate the short license if we were unable to shorten it with newlines\n+    if short_license and len(short_license) > 100 and short_license == release.license:\n+        short_license = short_license[:100] + \"...\"\n+\n     if license_classifiers and short_license:\n         license = f\"{license_classifiers} ({short_license})\"\n     else:\n", "issue": "PEP 621-style license field shows the entire license text\n**Describe the bug**\r\nWhen 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.\r\n\r\n**Expected behavior**\r\nThe 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.\n", "before_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom natsort import natsorted\nfrom pyramid.httpexceptions import HTTPMovedPermanently, HTTPNotFound\nfrom pyramid.view import view_config\nfrom sqlalchemy.orm.exc import NoResultFound\n\nfrom warehouse.accounts.models import User\nfrom warehouse.cache.origin import origin_cache\nfrom warehouse.packaging.models import File, Project, Release, Role\nfrom warehouse.utils import readme\n\n\n@view_config(\n    route_name=\"packaging.project\",\n    context=Project,\n    renderer=\"packaging/detail.html\",\n    decorator=[\n        origin_cache(\n            1 * 24 * 60 * 60, stale_if_error=5 * 24 * 60 * 60  # 1 day, 5 days stale\n        )\n    ],\n    has_translations=True,\n)\ndef project_detail(project, request):\n    if project.name != request.matchdict.get(\"name\", project.name):\n        return HTTPMovedPermanently(request.current_route_path(name=project.name))\n\n    try:\n        release = (\n            request.db.query(Release)\n            .filter(Release.project == project)\n            .order_by(\n                Release.yanked,\n                Release.is_prerelease.nullslast(),\n                Release._pypi_ordering.desc(),\n            )\n            .limit(1)\n            .one()\n        )\n    except NoResultFound:\n        raise HTTPNotFound\n\n    return release_detail(release, request)\n\n\n@view_config(\n    route_name=\"packaging.release\",\n    context=Release,\n    renderer=\"packaging/detail.html\",\n    decorator=[\n        origin_cache(\n            1 * 24 * 60 * 60, stale_if_error=5 * 24 * 60 * 60  # 1 day, 5 days stale\n        )\n    ],\n    has_translations=True,\n)\ndef release_detail(release, request):\n    project = release.project\n\n    # Check if the requested version is equivalent but not exactly the same as\n    # the release's version. Use `.get` because this view is used by\n    # `project_detail` and there may not be a version.\n    #\n    # This also handles the case where both the version and the project name\n    # need adjusted, and handles it in a single redirect.\n    if release.version != request.matchdict.get(\"version\", release.version):\n        return HTTPMovedPermanently(\n            request.current_route_path(name=project.name, version=release.version)\n        )\n\n    # It's possible that the requested version was correct (or not provided),\n    # but we still need to adjust the project name.\n    if project.name != request.matchdict.get(\"name\", project.name):\n        return HTTPMovedPermanently(request.current_route_path(name=project.name))\n\n    # Grab the rendered description if it exists, and if it doesn't, then we will render\n    # it inline.\n    # TODO: Remove the fallback to rendering inline and only support displaying the\n    #       already rendered content.\n    if release.description.html:\n        description = release.description.html\n    else:\n        description = readme.render(\n            release.description.raw, release.description.content_type\n        )\n\n    # Get all of the maintainers for this project.\n    maintainers = [\n        r.user\n        for r in (\n            request.db.query(Role)\n            .join(User)\n            .filter(Role.project == project)\n            .distinct(User.username)\n            .order_by(User.username)\n            .all()\n        )\n    ]\n\n    # Get the license from both the `Classifier` and `License` metadata fields\n    license_classifiers = \", \".join(\n        c.split(\" :: \")[-1] for c in release.classifiers if c.startswith(\"License\")\n    )\n\n    # Make a best effort when the entire license text is given by using the\n    # first line only.\n    short_license = release.license.split(\"\\n\")[0] if release.license else None\n\n    if license_classifiers and short_license:\n        license = f\"{license_classifiers} ({short_license})\"\n    else:\n        license = license_classifiers or short_license or None\n\n    # We cannot easily sort naturally in SQL, sort here and pass to template\n    sdists = natsorted(\n        release.files.filter(File.packagetype == \"sdist\").all(),\n        reverse=True,\n        key=lambda f: f.filename,\n    )\n    bdists = natsorted(\n        release.files.filter(File.packagetype != \"sdist\").all(),\n        reverse=True,\n        key=lambda f: f.filename,\n    )\n\n    return {\n        \"project\": project,\n        \"release\": release,\n        \"description\": description,\n        \"files\": sdists + bdists,\n        \"sdists\": sdists,\n        \"bdists\": bdists,\n        \"latest_version\": project.latest_version,\n        \"all_versions\": project.all_versions,\n        \"maintainers\": maintainers,\n        \"license\": license,\n    }\n\n\n@view_config(\n    route_name=\"includes.edit-project-button\",\n    context=Project,\n    renderer=\"includes/manage-project-button.html\",\n    uses_session=True,\n    permission=\"manage:project\",\n    has_translations=True,\n)\ndef edit_project_button(project, request):\n    return {\"project\": project}\n", "path": "warehouse/packaging/views.py"}], "after_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom natsort import natsorted\nfrom pyramid.httpexceptions import HTTPMovedPermanently, HTTPNotFound\nfrom pyramid.view import view_config\nfrom sqlalchemy.orm.exc import NoResultFound\n\nfrom warehouse.accounts.models import User\nfrom warehouse.cache.origin import origin_cache\nfrom warehouse.packaging.models import File, Project, Release, Role\nfrom warehouse.utils import readme\n\n\n@view_config(\n    route_name=\"packaging.project\",\n    context=Project,\n    renderer=\"packaging/detail.html\",\n    decorator=[\n        origin_cache(\n            1 * 24 * 60 * 60, stale_if_error=5 * 24 * 60 * 60  # 1 day, 5 days stale\n        )\n    ],\n    has_translations=True,\n)\ndef project_detail(project, request):\n    if project.name != request.matchdict.get(\"name\", project.name):\n        return HTTPMovedPermanently(request.current_route_path(name=project.name))\n\n    try:\n        release = (\n            request.db.query(Release)\n            .filter(Release.project == project)\n            .order_by(\n                Release.yanked,\n                Release.is_prerelease.nullslast(),\n                Release._pypi_ordering.desc(),\n            )\n            .limit(1)\n            .one()\n        )\n    except NoResultFound:\n        raise HTTPNotFound\n\n    return release_detail(release, request)\n\n\n@view_config(\n    route_name=\"packaging.release\",\n    context=Release,\n    renderer=\"packaging/detail.html\",\n    decorator=[\n        origin_cache(\n            1 * 24 * 60 * 60, stale_if_error=5 * 24 * 60 * 60  # 1 day, 5 days stale\n        )\n    ],\n    has_translations=True,\n)\ndef release_detail(release, request):\n    project = release.project\n\n    # Check if the requested version is equivalent but not exactly the same as\n    # the release's version. Use `.get` because this view is used by\n    # `project_detail` and there may not be a version.\n    #\n    # This also handles the case where both the version and the project name\n    # need adjusted, and handles it in a single redirect.\n    if release.version != request.matchdict.get(\"version\", release.version):\n        return HTTPMovedPermanently(\n            request.current_route_path(name=project.name, version=release.version)\n        )\n\n    # It's possible that the requested version was correct (or not provided),\n    # but we still need to adjust the project name.\n    if project.name != request.matchdict.get(\"name\", project.name):\n        return HTTPMovedPermanently(request.current_route_path(name=project.name))\n\n    # Grab the rendered description if it exists, and if it doesn't, then we will render\n    # it inline.\n    # TODO: Remove the fallback to rendering inline and only support displaying the\n    #       already rendered content.\n    if release.description.html:\n        description = release.description.html\n    else:\n        description = readme.render(\n            release.description.raw, release.description.content_type\n        )\n\n    # Get all of the maintainers for this project.\n    maintainers = [\n        r.user\n        for r in (\n            request.db.query(Role)\n            .join(User)\n            .filter(Role.project == project)\n            .distinct(User.username)\n            .order_by(User.username)\n            .all()\n        )\n    ]\n\n    # Get the license from both the `Classifier` and `License` metadata fields\n    license_classifiers = \", \".join(\n        c.split(\" :: \")[-1] for c in release.classifiers if c.startswith(\"License\")\n    )\n\n    # Make a best effort when the entire license text is given by using the\n    # first line only.\n    short_license = release.license.split(\"\\n\")[0] if release.license else None\n\n    # Truncate the short license if we were unable to shorten it with newlines\n    if short_license and len(short_license) > 100 and short_license == release.license:\n        short_license = short_license[:100] + \"...\"\n\n    if license_classifiers and short_license:\n        license = f\"{license_classifiers} ({short_license})\"\n    else:\n        license = license_classifiers or short_license or None\n\n    # We cannot easily sort naturally in SQL, sort here and pass to template\n    sdists = natsorted(\n        release.files.filter(File.packagetype == \"sdist\").all(),\n        reverse=True,\n        key=lambda f: f.filename,\n    )\n    bdists = natsorted(\n        release.files.filter(File.packagetype != \"sdist\").all(),\n        reverse=True,\n        key=lambda f: f.filename,\n    )\n\n    return {\n        \"project\": project,\n        \"release\": release,\n        \"description\": description,\n        \"files\": sdists + bdists,\n        \"sdists\": sdists,\n        \"bdists\": bdists,\n        \"latest_version\": project.latest_version,\n        \"all_versions\": project.all_versions,\n        \"maintainers\": maintainers,\n        \"license\": license,\n    }\n\n\n@view_config(\n    route_name=\"includes.edit-project-button\",\n    context=Project,\n    renderer=\"includes/manage-project-button.html\",\n    uses_session=True,\n    permission=\"manage:project\",\n    has_translations=True,\n)\ndef edit_project_button(project, request):\n    return {\"project\": project}\n", "path": "warehouse/packaging/views.py"}]}