Skip to content

Commit 6b754c9

Browse files
committed
Non-PEP440 versions shouldn't prevent prerelease versions in empty specifier
1 parent 315f444 commit 6b754c9

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"], []),
@@ -879,15 +873,34 @@ def test_empty_specifier(self, version: str) -> None:
879873
assert spec.contains(parse(version))
880874

881875
@pytest.mark.parametrize(
882-
"prereleases",
883-
[None, False, True],
876+
("prereleases", "versions", "expected"),
877+
[
878+
# single arbitrary string
879+
(None, ["foobar"], ["foobar"]),
880+
(False, ["foobar"], ["foobar"]),
881+
(True, ["foobar"], ["foobar"]),
882+
# arbitrary string with a stable version present
883+
(None, ["foobar", "1.0"], ["foobar", "1.0"]),
884+
(False, ["foobar", "1.0"], ["foobar", "1.0"]),
885+
(True, ["foobar", "1.0"], ["foobar", "1.0"]),
886+
# arbitrary string with a prerelease only
887+
(None, ["foobar", "1.0a1"], ["foobar", "1.0a1"]),
888+
(False, ["foobar", "1.0a1"], ["foobar"]),
889+
(True, ["foobar", "1.0a1"], ["foobar", "1.0a1"]),
890+
],
884891
)
885-
def test_empty_specifier_arbitrary_string(self, prereleases):
892+
def test_empty_specifier_arbitrary_string(self, prereleases, versions, expected):
886893
"""Test empty SpecifierSet accepts arbitrary strings."""
887894

888895
spec = SpecifierSet("", prereleases=prereleases)
896+
897+
# basic behavior preserved
889898
assert spec.contains("foobar")
890899

900+
# check filter behavior (no override of prereleases passed to filter)
901+
kwargs = {}
902+
assert list(spec.filter(versions, **kwargs)) == expected
903+
891904
def test_create_from_specifiers(self) -> None:
892905
spec_strs = [">=1.0", "!=1.1", "!=1.2", "<2.0"]
893906
specs = [Specifier(s) for s in spec_strs]

0 commit comments

Comments
 (0)