From f31d1050d6b8245cb4b7f7b61866948307fb5a95 Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Sun, 22 Feb 2026 20:17:41 -0800 Subject: [PATCH 1/2] Fix > comparison for versions with dev+local segments The greater-than specifier incorrectly rejected versions like 4.1.0a2.dev1235+local against >4.1.0a2.dev1234. The local version guard used _base_version which strips pre/dev/post segments, making different dev versions appear equal. Replaced with _public_version which only strips the local segment, correctly identifying when a local version genuinely differs from the spec version. Fixes #810 --- src/packaging/specifiers.py | 4 ++-- tests/test_specifiers.py | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/packaging/specifiers.py b/src/packaging/specifiers.py index 13bc9bda..05ea893a 100644 --- a/src/packaging/specifiers.py +++ b/src/packaging/specifiers.py @@ -588,9 +588,9 @@ def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool: # Ensure that we do not allow a local version of the version mentioned # in the specifier, which is technically greater than, to match. - if prospective.local is not None and _base_version( + if prospective.local is not None and _public_version( prospective - ) == _base_version(spec): + ) == _public_version(spec): return False # If we've gotten to here, it means that prospective version is both diff --git a/tests/test_specifiers.py b/tests/test_specifiers.py index f5949424..f99dd069 100644 --- a/tests/test_specifiers.py +++ b/tests/test_specifiers.py @@ -398,6 +398,9 @@ def test_comparison_non_specifier(self) -> None: ("2!1.0", ">2.0"), # Test some normalization rules ("2.0.5", ">2.0dev"), + # Test local+dev versions with greater than + ("1.0+local", ">1.0.dev1"), + ("4.1.0a2.dev1235+local", ">4.1.0a2.dev1234"), ] ] + [ @@ -465,7 +468,7 @@ def test_comparison_non_specifier(self) -> None: ("2.0.post1", ">2"), ("2.0.post1.dev1", ">2"), ("2.0+local.version", ">2"), - ("1.0+local", ">1.0.dev1"), + ("4.1.0a2.dev1234+local", ">4.1.0a2.dev1234"), # Test the less than operation ("2.0.dev1", "<2"), ("2.0a1", "<2"), From 7ca06ec1d2ce506924026c127c85a1aa8de7611b Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Mon, 23 Feb 2026 23:29:29 -0800 Subject: [PATCH 2/2] Add tests for > specifier with local+pre/dev/post segments Cover the behavior change from _base_version to _public_version by testing that local versions with varying pre, dev, and post segments are correctly accepted or rejected by the > operator. True cases: local versions whose public part genuinely exceeds the spec (e.g. 1.0a2+local > 1.0a1, 1.0.dev2+local > 1.0.dev1). False cases: local versions whose public part matches the spec exactly (e.g. 1.0a1+local should not match >1.0a1). --- tests/test_specifiers.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/test_specifiers.py b/tests/test_specifiers.py index f99dd069..2407824d 100644 --- a/tests/test_specifiers.py +++ b/tests/test_specifiers.py @@ -398,9 +398,17 @@ def test_comparison_non_specifier(self) -> None: ("2!1.0", ">2.0"), # Test some normalization rules ("2.0.5", ">2.0dev"), - # Test local+dev versions with greater than + # Test local versions with pre/dev/post segments and > + # (verifies _public_version keeps pre/dev/post in the guard) ("1.0+local", ">1.0.dev1"), ("4.1.0a2.dev1235+local", ">4.1.0a2.dev1234"), + ("1.0a2+local", ">1.0a1"), + ("1.0b2+local", ">1.0b1"), + ("1.0rc2+local", ">1.0rc1"), + ("1.0.post2+local", ">1.0.post1"), + ("1.0.dev2+local", ">1.0.dev1"), + ("1.0a1.dev2+local", ">1.0a1.dev1"), + ("1.0.post1.dev2+local", ">1.0.post1.dev1"), ] ] + [ @@ -469,6 +477,15 @@ def test_comparison_non_specifier(self) -> None: ("2.0.post1.dev1", ">2"), ("2.0+local.version", ">2"), ("4.1.0a2.dev1234+local", ">4.1.0a2.dev1234"), + # Test local versions with pre/dev/post segments and > + # (local variant of the exact spec version must not match) + ("1.0a1+local", ">1.0a1"), + ("1.0b1+local", ">1.0b1"), + ("1.0rc1+local", ">1.0rc1"), + ("1.0.post1+local", ">1.0.post1"), + ("1.0.dev1+local", ">1.0.dev1"), + ("1.0a1.dev1+local", ">1.0a1.dev1"), + ("1.0.post1.dev1+local", ">1.0.post1.dev1"), # Test the less than operation ("2.0.dev1", "<2"), ("2.0a1", "<2"),