We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
License metadata seems to be ignored
When I made the latest release of `python-dateutil`, it came along with a license change from BSD to Apache / BSD dual licensed.  I updated the `license=` metadata in `setup.py`, but I forgot to update the trove classifiers.

[The page on PyPI](https://pypi.python.org/pypi/python-dateutil/2.7.0) shows the license as "Apache 2.0" as I would expect. [The page on warehouse](https://pypi.org/project/python-dateutil/) shows the license as "BSD License". I'm assuming it's pulling that from the trove classifier? Shouldn't it pull it from the `license` field if that is populated?

--- 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 first import first
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 Release, Role
21 
22 
23 @view_config(
24     route_name="packaging.project",
25     renderer="packaging/detail.html",
26     decorator=[
27         origin_cache(
28             1 * 24 * 60 * 60,                         # 1 day
29             stale_while_revalidate=1 * 24 * 60 * 60,  # 1 day
30             stale_if_error=5 * 24 * 60 * 60,          # 5 days
31         ),
32     ],
33 )
34 def project_detail(project, request):
35     if project.name != request.matchdict.get("name", project.name):
36         return HTTPMovedPermanently(
37             request.current_route_path(name=project.name),
38         )
39 
40     try:
41         release = (
42             request.db.query(Release)
43                       .filter(Release.project == project)
44                       .order_by(
45                           Release.is_prerelease.nullslast(),
46                           Release._pypi_ordering.desc())
47                       .limit(1)
48                       .one()
49         )
50     except NoResultFound:
51         return HTTPNotFound()
52 
53     return release_detail(release, request)
54 
55 
56 @view_config(
57     route_name="packaging.release",
58     renderer="packaging/detail.html",
59     decorator=[
60         origin_cache(
61             1 * 24 * 60 * 60,                         # 1 day
62             stale_while_revalidate=1 * 24 * 60 * 60,  # 1 day
63             stale_if_error=5 * 24 * 60 * 60,          # 5 days
64         ),
65     ],
66 )
67 def release_detail(release, request):
68     project = release.project
69 
70     # Check if the requested version is equivalent but not exactly the same as
71     # the release's version. Use `.get` because this view is used by
72     # `project_detail` and there may not be a version.
73     #
74     # This also handles the case where both the version and the project name
75     # need adjusted, and handles it in a single redirect.
76     if release.version != request.matchdict.get("version", release.version):
77         return HTTPMovedPermanently(
78             request.current_route_path(
79                 name=project.name,
80                 version=release.version,
81             ),
82         )
83 
84     # It's possible that the requested version was correct (or not provided),
85     # but we still need to adjust the project name.
86     if project.name != request.matchdict.get("name", project.name):
87         return HTTPMovedPermanently(
88             request.current_route_path(name=project.name),
89         )
90 
91     # Get all of the registered versions for this Project, in order of newest
92     # to oldest.
93     all_releases = (
94         request.db.query(Release)
95                   .filter(Release.project == project)
96                   .with_entities(
97                       Release.version,
98                       Release.is_prerelease,
99                       Release.created)
100                   .order_by(Release._pypi_ordering.desc())
101                   .all()
102     )
103 
104     # Get the latest non-prerelease of this Project, or the latest release if
105     # all releases are prereleases.
106     latest_release = first(
107         all_releases,
108         key=lambda r: not r.is_prerelease,
109         default=all_releases[0],
110     )
111 
112     # Get all of the maintainers for this project.
113     maintainers = [
114         r.user
115         for r in (
116             request.db.query(Role)
117             .join(User)
118             .filter(Role.project == project)
119             .distinct(User.username)
120             .order_by(User.username)
121             .all()
122         )
123     ]
124 
125     # Get the license from the classifiers or metadata, preferring classifiers.
126     license = None
127     if release.license:
128         # Make a best effort when the entire license text is given
129         # by using the first line only.
130         license = release.license.split('\n')[0]
131     license_classifiers = [c.split(" :: ")[-1] for c in release.classifiers
132                            if c.startswith("License")]
133     if license_classifiers:
134         license = ', '.join(license_classifiers)
135 
136     return {
137         "project": project,
138         "release": release,
139         "files": release.files.all(),
140         "latest_release": latest_release,
141         "all_releases": all_releases,
142         "maintainers": maintainers,
143         "license": license,
144     }
145 
146 
147 @view_config(
148     route_name="includes.edit-project-button",
149     renderer="includes/manage-project-button.html",
150     uses_session=True,
151     permission="manage",
152 )
153 def edit_project_button(project, request):
154     return {'project': project}
155
```
--- 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
@@ -122,16 +122,21 @@
         )
     ]
 
-    # Get the license from the classifiers or metadata, preferring classifiers.
-    license = None
-    if release.license:
-        # Make a best effort when the entire license text is given
-        # by using the first line only.
-        license = release.license.split('\n')[0]
-    license_classifiers = [c.split(" :: ")[-1] for c in release.classifiers
-                           if c.startswith("License")]
-    if license_classifiers:
-        license = ', '.join(license_classifiers)
+    # Get the license from both the `Classifier` and `License` metadata fields
+    license_classifiers = ', '.join(
+        c.split(" :: ")[-1]
+        for c in release.classifiers
+        if c.startswith("License")
+    )
+
+    # Make a best effort when the entire license text is given by using the
+    # first line only.
+    short_license = release.license.split('\n')[0] if release.license else None
+
+    if license_classifiers and short_license:
+        license = f'{license_classifiers} ({short_license})'
+    else:
+        license = license_classifiers or short_license or None
 
     return {
         "project": project,

{"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@@ -122,16 +122,21 @@\n         )\n     ]\n \n-    # Get the license from the classifiers or metadata, preferring classifiers.\n-    license = None\n-    if release.license:\n-        # Make a best effort when the entire license text is given\n-        # by using the first line only.\n-        license = release.license.split('\\n')[0]\n-    license_classifiers = [c.split(\" :: \")[-1] for c in release.classifiers\n-                           if c.startswith(\"License\")]\n-    if license_classifiers:\n-        license = ', '.join(license_classifiers)\n+    # Get the license from both the `Classifier` and `License` metadata fields\n+    license_classifiers = ', '.join(\n+        c.split(\" :: \")[-1]\n+        for c in release.classifiers\n+        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     return {\n         \"project\": project,\n", "issue": "License metadata seems to be ignored\nWhen I made the latest release of `python-dateutil`, it came along with a license change from BSD to Apache / BSD dual licensed.  I updated the `license=` metadata in `setup.py`, but I forgot to update the trove classifiers.\r\n\r\n[The page on PyPI](https://pypi.python.org/pypi/python-dateutil/2.7.0) shows the license as \"Apache 2.0\" as I would expect. [The page on warehouse](https://pypi.org/project/python-dateutil/) shows the license as \"BSD License\". I'm assuming it's pulling that from the trove classifier? Shouldn't it pull it from the `license` field if that is populated?\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 first import first\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 Release, Role\n\n\n@view_config(\n    route_name=\"packaging.project\",\n    renderer=\"packaging/detail.html\",\n    decorator=[\n        origin_cache(\n            1 * 24 * 60 * 60,                         # 1 day\n            stale_while_revalidate=1 * 24 * 60 * 60,  # 1 day\n            stale_if_error=5 * 24 * 60 * 60,          # 5 days\n        ),\n    ],\n)\ndef project_detail(project, request):\n    if project.name != request.matchdict.get(\"name\", project.name):\n        return HTTPMovedPermanently(\n            request.current_route_path(name=project.name),\n        )\n\n    try:\n        release = (\n            request.db.query(Release)\n                      .filter(Release.project == project)\n                      .order_by(\n                          Release.is_prerelease.nullslast(),\n                          Release._pypi_ordering.desc())\n                      .limit(1)\n                      .one()\n        )\n    except NoResultFound:\n        return HTTPNotFound()\n\n    return release_detail(release, request)\n\n\n@view_config(\n    route_name=\"packaging.release\",\n    renderer=\"packaging/detail.html\",\n    decorator=[\n        origin_cache(\n            1 * 24 * 60 * 60,                         # 1 day\n            stale_while_revalidate=1 * 24 * 60 * 60,  # 1 day\n            stale_if_error=5 * 24 * 60 * 60,          # 5 days\n        ),\n    ],\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(\n                name=project.name,\n                version=release.version,\n            ),\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(\n            request.current_route_path(name=project.name),\n        )\n\n    # Get all of the registered versions for this Project, in order of newest\n    # to oldest.\n    all_releases = (\n        request.db.query(Release)\n                  .filter(Release.project == project)\n                  .with_entities(\n                      Release.version,\n                      Release.is_prerelease,\n                      Release.created)\n                  .order_by(Release._pypi_ordering.desc())\n                  .all()\n    )\n\n    # Get the latest non-prerelease of this Project, or the latest release if\n    # all releases are prereleases.\n    latest_release = first(\n        all_releases,\n        key=lambda r: not r.is_prerelease,\n        default=all_releases[0],\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 the classifiers or metadata, preferring classifiers.\n    license = None\n    if release.license:\n        # Make a best effort when the entire license text is given\n        # by using the first line only.\n        license = release.license.split('\\n')[0]\n    license_classifiers = [c.split(\" :: \")[-1] for c in release.classifiers\n                           if c.startswith(\"License\")]\n    if license_classifiers:\n        license = ', '.join(license_classifiers)\n\n    return {\n        \"project\": project,\n        \"release\": release,\n        \"files\": release.files.all(),\n        \"latest_release\": latest_release,\n        \"all_releases\": all_releases,\n        \"maintainers\": maintainers,\n        \"license\": license,\n    }\n\n\n@view_config(\n    route_name=\"includes.edit-project-button\",\n    renderer=\"includes/manage-project-button.html\",\n    uses_session=True,\n    permission=\"manage\",\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 first import first\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 Release, Role\n\n\n@view_config(\n    route_name=\"packaging.project\",\n    renderer=\"packaging/detail.html\",\n    decorator=[\n        origin_cache(\n            1 * 24 * 60 * 60,                         # 1 day\n            stale_while_revalidate=1 * 24 * 60 * 60,  # 1 day\n            stale_if_error=5 * 24 * 60 * 60,          # 5 days\n        ),\n    ],\n)\ndef project_detail(project, request):\n    if project.name != request.matchdict.get(\"name\", project.name):\n        return HTTPMovedPermanently(\n            request.current_route_path(name=project.name),\n        )\n\n    try:\n        release = (\n            request.db.query(Release)\n                      .filter(Release.project == project)\n                      .order_by(\n                          Release.is_prerelease.nullslast(),\n                          Release._pypi_ordering.desc())\n                      .limit(1)\n                      .one()\n        )\n    except NoResultFound:\n        return HTTPNotFound()\n\n    return release_detail(release, request)\n\n\n@view_config(\n    route_name=\"packaging.release\",\n    renderer=\"packaging/detail.html\",\n    decorator=[\n        origin_cache(\n            1 * 24 * 60 * 60,                         # 1 day\n            stale_while_revalidate=1 * 24 * 60 * 60,  # 1 day\n            stale_if_error=5 * 24 * 60 * 60,          # 5 days\n        ),\n    ],\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(\n                name=project.name,\n                version=release.version,\n            ),\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(\n            request.current_route_path(name=project.name),\n        )\n\n    # Get all of the registered versions for this Project, in order of newest\n    # to oldest.\n    all_releases = (\n        request.db.query(Release)\n                  .filter(Release.project == project)\n                  .with_entities(\n                      Release.version,\n                      Release.is_prerelease,\n                      Release.created)\n                  .order_by(Release._pypi_ordering.desc())\n                  .all()\n    )\n\n    # Get the latest non-prerelease of this Project, or the latest release if\n    # all releases are prereleases.\n    latest_release = first(\n        all_releases,\n        key=lambda r: not r.is_prerelease,\n        default=all_releases[0],\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]\n        for c in release.classifiers\n        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    return {\n        \"project\": project,\n        \"release\": release,\n        \"files\": release.files.all(),\n        \"latest_release\": latest_release,\n        \"all_releases\": all_releases,\n        \"maintainers\": maintainers,\n        \"license\": license,\n    }\n\n\n@view_config(\n    route_name=\"includes.edit-project-button\",\n    renderer=\"includes/manage-project-button.html\",\n    uses_session=True,\n    permission=\"manage\",\n)\ndef edit_project_button(project, request):\n    return {'project': project}\n", "path": "warehouse/packaging/views.py"}]}