From: Stefano Rivera <stefano@rivera.za.net>
Date: Tue, 3 Dec 2024 17:03:52 -0400
Subject: Handle missing optional dependencies in dep_versions()

PR #1159 made keyring optional on some (non-Desktop) architectures.
However the CLI attempts to determine dependency versions, in failure
codepaths. Rather than blow up entirely, report the dependency as
missing.

Part of: #1158

Forwarded: https://github.com/pypa/twine/pull/1193
---
 twine/cli.py | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/twine/cli.py b/twine/cli.py
index 749a645..6ff60d4 100644
--- a/twine/cli.py
+++ b/twine/cli.py
@@ -76,7 +76,7 @@ def configure_output() -> None:
 
 def list_dependencies_and_versions() -> List[Tuple[str, str]]:
     deps = [
-        "keyring",
+        "keyring",  # optional for non-desktop use
         "pkginfo",
         "requests",
         "requests-toolbelt",
@@ -84,7 +84,16 @@ def list_dependencies_and_versions() -> List[Tuple[str, str]]:
     ]
     if sys.version_info < (3, 10):
         deps.append("importlib-metadata")
-    return [(dep, importlib_metadata.version(dep)) for dep in deps]
+
+    result: List[Tuple[str, str]] = []
+    for dep in deps:
+        try:
+            version = importlib_metadata.version(dep)
+        except importlib_metadata.PackageNotFoundError:
+            version = "NOT INSTALLED"
+        result.append((dep, version))
+
+    return result
 
 
 def dep_versions() -> str:
