diff --git a/packaging/specifiers.py b/packaging/specifiers.py index 37030db9..5920482a 100644 --- a/packaging/specifiers.py +++ b/packaging/specifiers.py @@ -393,18 +393,24 @@ def _compare_equal(self, prospective: Version, spec: str) -> bool: # segment. split_prospective = _version_split(str(prospective)) + if spec_version.is_prerelease or spec_version.is_postrelease: + # the release segment must match exactly + # 0-pad both the prospective and spec versions + padded_spec, padded_prospective = _pad_version( + split_spec, split_prospective + ) + else: + # 0-pad the prospective version before shortening it to get the correct + # shortened version. + _, padded_prospective = _pad_version(split_spec, split_prospective) + padded_spec = split_spec + # Shorten the prospective version to be the same length as the spec # so that we can determine if the specifier is a prefix of the # prospective version or not. - shortened_prospective = split_prospective[: len(split_spec)] - - # Pad out our two sides with zeros so that they both equal the same - # length. - padded_spec, padded_prospective = _pad_version( - split_spec, shortened_prospective - ) + shortened_prospective = padded_prospective[: len(padded_spec)] - return padded_prospective == padded_spec + return shortened_prospective == padded_spec else: # Convert our spec string into a Version spec_version = Version(spec) diff --git a/tests/test_specifiers.py b/tests/test_specifiers.py index cb1f4b61..e8d70b69 100644 --- a/tests/test_specifiers.py +++ b/tests/test_specifiers.py @@ -300,16 +300,34 @@ def test_comparison_non_specifier(self): ("2b1.dev1", "==2.*"), ("2c1", "==2.*"), ("2c1.post1.dev1", "==2.*"), + ("2c1.post1.dev1", "==2.0.*"), ("2rc1", "==2.*"), + ("2rc1", "==2.0.*"), ("2", "==2.*"), + ("2", "==2.0.*"), ("2", "==0!2.*"), ("0!2", "==2.*"), ("2.0", "==2.*"), ("2.0.0", "==2.*"), ("2.0.post1", "==2.0.post1.*"), + ("2.post1", "==2.0.post1.*"), + ("2.0.post1", "==2.post1.*"), ("2.0.post1.dev1", "==2.0.post1.*"), + ("2.post1.dev1", "==2.0.post1.*"), + ("2.0.post1.dev1", "==2.post1.*"), ("2.0.rc1", "==2.0.c1.*"), ("2.0.rc1.post1", "==2.0.c1.*"), + ("2rc1", "==2.0c1.*"), + ("2.0rc1", "==2c1.*"), + ("2.0rc1.post1.dev1", "==2.0c1.*"), + ("2rc1.post1.dev1", "==2.0c1.*"), + ("2.0rc1.post1.dev1", "==2c1.*"), + ("2.0rc1.post0", "==2.0c1.post.*"), + ("2rc1.post0", "==2.0c1.post.*"), + ("2.0rc1.post0", "==2c1.post.*"), + ("2.0rc1.post0.dev1", "==2.0c1.post.*"), + ("2rc1.post0.dev1", "==2.0c1.post.*"), + ("2.0rc1.post0.dev1", "==2c1.post.*"), ("2.1+local.version", "==2.1.*"), # Test the in-equality operation ("2.1", "!=2"), @@ -382,6 +400,9 @@ def test_comparison_non_specifier(self): # Test the equality operation with a prefix ("2.0", "==3.*"), ("2.1", "==2.0.*"), + ("2.0rc1", "==2.0rc.*"), + ("2.0.post1", "==2.0.post.*"), + ("2.0rc1.post1", "==2.0rc1.post.*"), # Test the in-equality operation ("2.0", "!=2"), ("2.0", "!=2.0"), @@ -401,8 +422,11 @@ def test_comparison_non_specifier(self): ("2b1.dev1", "!=2.*"), ("2c1", "!=2.*"), ("2c1.post1.dev1", "!=2.*"), + ("2c1.post1.dev1", "!=2.0.*"), ("2rc1", "!=2.*"), + ("2rc1", "!=2.0.*"), ("2", "!=2.*"), + ("2", "!=2.0.*"), ("2.0", "!=2.*"), ("2.0.0", "!=2.*"), ("2.0.post1", "!=2.0.post1.*"),