Skip to content

Commit 51d6da5

Browse files
committed
Handle invalid versions gracefully for all list formats
1 parent d14ace5 commit 51d6da5

File tree

3 files changed

+15
-8
lines changed

3 files changed

+15
-8
lines changed

news/13345.bugfix.rst

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
``pip list`` with the ``json`` or ``freeze`` format enabled will no longer
2+
crash when encountering a package with an invalid version.

src/pip/_internal/commands/list.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from typing import TYPE_CHECKING, Generator, List, Optional, Sequence, Tuple, cast
66

77
from pip._vendor.packaging.utils import canonicalize_name
8-
from pip._vendor.packaging.version import Version
8+
from pip._vendor.packaging.version import InvalidVersion, Version
99

1010
from pip._internal.cli import cmdoptions
1111
from pip._internal.cli.index_command import IndexGroupCommand
@@ -285,12 +285,14 @@ def output_package_listing(
285285
self.output_package_listing_columns(data, header)
286286
elif options.list_format == "freeze":
287287
for dist in packages:
288+
try:
289+
req_string = f"{dist.raw_name}=={dist.version}"
290+
except InvalidVersion:
291+
req_string = f"{dist.raw_name}==={dist.raw_version}"
288292
if options.verbose >= 1:
289-
write_output(
290-
"%s==%s (%s)", dist.raw_name, dist.version, dist.location
291-
)
293+
write_output("%s (%s)", req_string, dist.location)
292294
else:
293-
write_output("%s==%s", dist.raw_name, dist.version)
295+
write_output(req_string)
294296
elif options.list_format == "json":
295297
write_output(format_for_json(packages, options))
296298

@@ -376,7 +378,7 @@ def format_for_json(packages: "_ProcessedDists", options: Values) -> str:
376378
for dist in packages:
377379
info = {
378380
"name": dist.raw_name,
379-
"version": str(dist.version),
381+
"version": dist.raw_version,
380382
}
381383
if options.verbose >= 1:
382384
info["location"] = dist.location or ""

tests/functional/test_invalid_versions_and_specifiers.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,15 @@ def test_upgrade_require_invalid_version(
9696
script.pip("install", "--index-url", index_url, "require-invalid-version")
9797

9898

99-
def test_list_invalid_version(script: PipTestEnvironment, data: TestData) -> None:
99+
@pytest.mark.parametrize("format", ["columns", "freeze", "json"])
100+
def test_list_invalid_version(
101+
script: PipTestEnvironment, data: TestData, format: str
102+
) -> None:
100103
"""
101104
Test that pip can list an environment containing a package with a legacy version.
102105
"""
103106
_install_invalid_version(script, data)
104-
script.pip("list")
107+
script.pip("list", f"--format={format}")
105108

106109

107110
def test_freeze_invalid_version(script: PipTestEnvironment, data: TestData) -> None:

0 commit comments

Comments
 (0)