Repository: pypa/pip

Issue:
Show 'home-page' project URL when Home-Page metadata value is not set
### What's the problem this feature will solve?

When installing a pyproject.toml-only project, the `Home-Page` metadata won't be set (as there's no way to specify it: PEP 621 only maps to `Project-Url`). This means `pip show` won't provide any URL to the user.

### Describe the solution you'd like

If `Home-Page` is not set, instead select one of the project URLs (if present), with the following order of preference:
* Home-page
* Homepage
* homepage
* Source
* fallback: the first project-URL in the metadata

### Alternative Solutions

`pip show -v` shows all project URLs, but that still shows an empty `Home-page:` field

### Additional context

Project URLs were included in `pip show -v` in #10827

### Code of Conduct

- [X] I agree to follow the [PSF Code of Conduct](https://www.python.org/psf/conduct/).


Discussion:
Perhaps it is better to match PyPI’s display. This is how warehouse does it:

https://github.com/pypi/warehouse/blob/39daea188d2e1e6494c50753cd48cb5a8da3e8c4/warehouse/packaging/models.py#L537-L558

(`self.home_page` comes from `Home-page`, `self.download_url` is from the legacy `Download-URL`.)
Do you want to see all project URLs (without passing `-v` (`--verbose`))? I think it's best to see exactly one (if any are available) (unless `-v` is passed).

I like Warehouse's logic otherwise.
There’s already discussion on that #11138. It’s probably best to show one by default, and more in verbose mode. (I wouldn’t include `Source` and the fallback in the heuristic though; if there’s nothing that looks like a homepage, I prefer to just show an empty value or something like `<unknown>` instead.)
Hi,
I've come across this issue writing a package with pyproject.toml only. 
Is there any progress on this issue?

Given pep 621, this issue is going to increasingly get attention. 
I initially thought I had written pyproject.toml incorrectly, so this issue may confuse some other developers if not resolved.

This is my suggestion:
pip show --verbose now works well, showing both Home-page and Project-URLs

pip show (non-verbose) should show either but not both:

a. Home-page if it exists, in usual place:
```
Summary: The PyPA recommended tool for installing Python packages.
Home-page: https://pip.pypa.io/
Author: The pip developers
```
at end:
```
Required-by:
```

b. or (if Home-page doesn't exist):
```
Summary: The PyPA recommended tool for installing Python packages.
Author: The pip developers
```
with one of Project-URLs [Homepage, Documentation, Source] on one line at end, e.g.
```
Required-by:
Project-URLs: Homepage, https://pip.pypa.io/
```

c. or Home-page empty, otherwise
```
Summary: A python package blah blah
Home-page:
Author: The package developers
```
```
Required-by:
```

What this does is maintain pip show for all the pre-existing packages using setup.py, setup.cfg.
If there is both Home-page and Project-URLs, Home-page would probably be considered default for the time being.
If Home-page doesn't exist, then the developers are either writing to pep 621 or feel the term "homepage" is ambiguous.
In which case, pip show still shows one url, but clearly to a different metadata variable.

I don't think there is an ideal solution. This means pip show will be inconsistent, sometimes showing `Home-page`, other times showing `Project-URLs: homepage` but it will be informative and, if a url exists, give a url, regardless of where the metadata is written.

I'm happy to write the changes and make a pull request if you agree?

Pull requests are always welcomed.

Resolving patch:
diff --git a/src/pip/_internal/commands/show.py b/src/pip/_internal/commands/show.py
--- a/src/pip/_internal/commands/show.py
+++ b/src/pip/_internal/commands/show.py
@@ -121,6 +121,22 @@ def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]:
 
         metadata = dist.metadata
 
+        project_urls = metadata.get_all("Project-URL", [])
+        homepage = metadata.get("Home-page", "")
+        if not homepage:
+            # It's common that there is a "homepage" Project-URL, but Home-page
+            # remains unset (especially as PEP 621 doesn't surface the field).
+            #
+            # This logic was taken from PyPI's codebase.
+            for url in project_urls:
+                url_label, url = url.split(",", maxsplit=1)
+                normalized_label = (
+                    url_label.casefold().replace("-", "").replace("_", "").strip()
+                )
+                if normalized_label == "homepage":
+                    homepage = url.strip()
+                    break
+
         yield _PackageInfo(
             name=dist.raw_name,
             version=str(dist.version),
@@ -132,8 +148,8 @@ def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]:
             metadata_version=dist.metadata_version or "",
             classifiers=metadata.get_all("Classifier", []),
             summary=metadata.get("Summary", ""),
-            homepage=metadata.get("Home-page", ""),
-            project_urls=metadata.get_all("Project-URL", []),
+            homepage=homepage,
+            project_urls=project_urls,
             author=metadata.get("Author", ""),
             author_email=metadata.get("Author-email", ""),
             license=metadata.get("License", ""),


Test patch:
diff --git a/tests/functional/test_show.py b/tests/functional/test_show.py
--- a/tests/functional/test_show.py
+++ b/tests/functional/test_show.py
@@ -3,6 +3,8 @@
 import re
 import textwrap
 
+import pytest
+
 from pip import __version__
 from pip._internal.commands.show import search_packages_info
 from pip._internal.utils.unpacking import untar_file
@@ -387,3 +389,23 @@ def test_show_deduplicate_requirements(script: PipTestEnvironment) -> None:
     result = script.pip("show", "simple", cwd=pkg_path)
     lines = result.stdout.splitlines()
     assert "Requires: pip" in lines
+
+
+@pytest.mark.parametrize(
+    "project_url", ["Home-page", "home-page", "Homepage", "homepage"]
+)
+def test_show_populate_homepage_from_project_urls(
+    script: PipTestEnvironment, project_url: str
+) -> None:
+    pkg_path = create_test_package_with_setup(
+        script,
+        name="simple",
+        version="1.0",
+        project_urls={project_url: "https://example.com"},
+    )
+    script.run("python", "setup.py", "egg_info", expect_stderr=True, cwd=pkg_path)
+    script.environ.update({"PYTHONPATH": pkg_path})
+
+    result = script.pip("show", "simple", cwd=pkg_path)
+    lines = result.stdout.splitlines()
+    assert "Home-page: https://example.com" in lines