Skip to content

Commit 46faf8c

Browse files
committed
Non-PEP440 versions shouldn't prevent prerelease versions in empty specifier
1 parent 5c3d8c5 commit 46faf8c

File tree

2 files changed

+36
-15
lines changed

2 files changed

+36
-15
lines changed

src/packaging/specifiers.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,14 +1033,22 @@ def filter(
10331033

10341034
# Finally if prereleases is None, apply PEP 440 logic:
10351035
# exclude prereleases unless there are no final releases that matched.
1036-
filtered: list[UnparsedVersionVar] = []
1036+
filtered_items: list[UnparsedVersionVar] = []
10371037
found_prereleases: list[UnparsedVersionVar] = []
1038+
found_final_release = False
10381039

10391040
for item in iterable:
10401041
parsed_version = _coerce_version(item)
1041-
if parsed_version is not None and parsed_version.is_prerelease:
1042+
# Arbitrary strings are always included as it is not
1043+
# possible to determine if they are prereleases,
1044+
# and they have already passed all specifiers.
1045+
if parsed_version is None:
1046+
filtered_items.append(item)
1047+
found_prereleases.append(item)
1048+
elif parsed_version.is_prerelease:
10421049
found_prereleases.append(item)
10431050
else:
1044-
filtered.append(item)
1051+
filtered_items.append(item)
1052+
found_final_release = True
10451053

1046-
return iter(filtered if filtered else found_prereleases)
1054+
return iter(filtered_items if found_final_release else found_prereleases)

tests/test_specifiers.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ def test_specifier_prereleases_set(
598598
[
599599
("1.0.0", "===1.0", False),
600600
("1.0.dev0", "===1.0", False),
601-
# Test exact arbitrary equality (===)
601+
# Test identity comparison by itself
602602
("1.0", "===1.0", True),
603603
("1.0.dev0", "===1.0.dev0", True),
604604
# Test that local versions don't match
@@ -759,13 +759,7 @@ def test_specifiers_prereleases(
759759
# Test != with invalid versions (should not pass as versions are not valid)
760760
("!=1.0", None, None, ["invalid", "foobar"], []),
761761
("!=1.0", None, None, ["1.0", "invalid", "2.0"], ["2.0"]),
762-
(
763-
"!=2.0.*",
764-
None,
765-
None,
766-
["invalid", "foobar", "2.0"],
767-
[]
768-
),
762+
("!=2.0.*", None, None, ["invalid", "foobar", "2.0"], []),
769763
("!=2.0.*", None, None, ["1.0", "invalid", "2.0.0"], ["1.0"]),
770764
# Test that !== ignores prereleases parameter for non-PEP 440 versions
771765
("!=1.0", None, True, ["invalid", "foobar"], []),
@@ -1020,15 +1014,34 @@ def test_empty_specifier(self, version: str) -> None:
10201014
assert spec.contains(parse(version))
10211015

10221016
@pytest.mark.parametrize(
1023-
"prereleases",
1024-
[None, False, True],
1017+
("prereleases", "versions", "expected"),
1018+
[
1019+
# single arbitrary string
1020+
(None, ["foobar"], ["foobar"]),
1021+
(False, ["foobar"], ["foobar"]),
1022+
(True, ["foobar"], ["foobar"]),
1023+
# arbitrary string with a stable version present
1024+
(None, ["foobar", "1.0"], ["foobar", "1.0"]),
1025+
(False, ["foobar", "1.0"], ["foobar", "1.0"]),
1026+
(True, ["foobar", "1.0"], ["foobar", "1.0"]),
1027+
# arbitrary string with a prerelease only
1028+
(None, ["foobar", "1.0a1"], ["foobar", "1.0a1"]),
1029+
(False, ["foobar", "1.0a1"], ["foobar"]),
1030+
(True, ["foobar", "1.0a1"], ["foobar", "1.0a1"]),
1031+
],
10251032
)
1026-
def test_empty_specifier_arbitrary_string(self, prereleases):
1033+
def test_empty_specifier_arbitrary_string(self, prereleases, versions, expected):
10271034
"""Test empty SpecifierSet accepts arbitrary strings."""
10281035

10291036
spec = SpecifierSet("", prereleases=prereleases)
1037+
1038+
# basic behavior preserved
10301039
assert spec.contains("foobar")
10311040

1041+
# check filter behavior (no override of prereleases passed to filter)
1042+
kwargs = {}
1043+
assert list(spec.filter(versions, **kwargs)) == expected
1044+
10321045
def test_create_from_specifiers(self) -> None:
10331046
spec_strs = [">=1.0", "!=1.1", "!=1.2", "<2.0"]
10341047
specs = [Specifier(s) for s in spec_strs]

0 commit comments

Comments
 (0)