Skip to content

Commit

Permalink
version: fix zero padding for version comparisons (strictly speaking,…
Browse files Browse the repository at this point in the history
… zero padding does not work for building the compare_key, so we do "zero stripping" as a more general approach)
  • Loading branch information
radoering committed Jan 7, 2023
1 parent 78f57f7 commit a917354
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 5 deletions.
10 changes: 5 additions & 5 deletions src/poetry/core/version/pep440/segments.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
28 changes: 28 additions & 0 deletions tests/constraints/version/test_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand All @@ -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)
Expand Down
28 changes: 28 additions & 0 deletions tests/version/pep440/test_segments.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
[
Expand Down

0 comments on commit a917354

Please sign in to comment.