diff --git a/src/poetry/core/version/pep440/segments.py b/src/poetry/core/version/pep440/segments.py index 735f523e8..721cdb2f3 100644 --- a/src/poetry/core/version/pep440/segments.py +++ b/src/poetry/core/version/pep440/segments.py @@ -50,11 +50,11 @@ def __post_init__(self) -> None: ] object.__setattr__(self, "text", ".".join(parts)) object.__setattr__(self, "precision", len(parts)) - object.__setattr__( - self, - "_compare_key", - (self.major, self.minor or 0, self.patch or 0, *self.extra), - ) + + compare_key = [self.major, self.minor or 0, self.patch or 0, *self.extra] + while compare_key and compare_key[-1] == 0: + del compare_key[-1] + object.__setattr__(self, "_compare_key", tuple(compare_key)) @classmethod def from_parts(cls, *parts: int) -> Release: diff --git a/tests/constraints/version/test_version.py b/tests/constraints/version/test_version.py index c53513a5f..dba08787b 100644 --- a/tests/constraints/version/test_version.py +++ b/tests/constraints/version/test_version.py @@ -287,6 +287,7 @@ def test_equality() -> None: def test_allows() -> None: v = Version.parse("1.2.3") assert v.allows(v) + assert not v.allows(Version.parse("1.2")) assert not v.allows(Version.parse("2.2.3")) assert not v.allows(Version.parse("1.3.3")) assert not v.allows(Version.parse("1.2.4")) @@ -296,6 +297,33 @@ def test_allows() -> None: assert v.allows(Version.parse("1.2.3+build")) +@pytest.mark.parametrize( + ("version1", "version2"), + [ + ("1", "1.0"), + ("1", "1.0.0"), + ("1", "1.0.0.0"), + ("1.2", "1.2.0"), + ("1.2", "1.2.0.0"), + ("1.2", "1.2.0.0.0"), + ("1.2.3", "1.2.3.0"), + ("1.2.3", "1.2.3.0.0"), + ("1.2.3.4", "1.2.3.4.0"), + ("1.2.3.4", "1.2.3.4.0.0"), + ("1.2.3.4a1", "1.2.3.4.0a1"), + ], +) +def test_allows_zero_padding(version1: str, version2: str) -> None: + v1 = Version.parse(version1) + v2 = Version.parse(version2) + assert v1.allows(v2) + assert v2.allows(v1) + assert v1.allows_all(v2) + assert v2.allows_all(v1) + assert v1.allows_any(v2) + assert v2.allows_any(v1) + + def test_allows_with_local() -> None: v = Version.parse("1.2.3+build.1") assert v.allows(v) diff --git a/tests/version/pep440/test_segments.py b/tests/version/pep440/test_segments.py index 6df079923..ffa1a231d 100644 --- a/tests/version/pep440/test_segments.py +++ b/tests/version/pep440/test_segments.py @@ -8,11 +8,39 @@ def test_release_post_init_minor_and_patch() -> None: + """ + Minor and patch must not be None but zero if there are extra parts. + """ release = Release(1, extra=(0,)) assert release.minor == 0 assert release.patch == 0 +def test_release_post_init_zero_version() -> None: + """ + Smoke test for edge case (because zeros are stripped for comparison). + """ + Release(0) + + +@pytest.mark.parametrize("precision1", range(1, 6)) +@pytest.mark.parametrize("precision2", range(1, 6)) +def test_release_equal_zero_padding(precision1: int, precision2: int) -> None: + release1 = Release.from_parts(*range(1, precision1 + 1)) + if precision1 > precision2: + # e.g. 1.2.3 != 1.2 + release2 = Release.from_parts(*range(1, precision2 + 1)) + assert release1 != release2 + assert release2 != release1 + else: + # e.g. 1.2 == 1.2.0 + release2 = Release.from_parts( + *range(1, precision1 + 1), *[0] * (precision2 - precision1) + ) + assert release1 == release2 + assert release2 == release1 + + @pytest.mark.parametrize( "parts,result", [