Commit 4c833892 by Sébastien Eustace Committed by GitHub

Fix version comparison for versions with precision > 3 (#351)

Fixes #350
parent 490ddf00
......@@ -6,7 +6,9 @@ MODIFIERS = (
"([+-]?([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?"
)
_COMPLETE_VERSION = "v?(\d+)(?:\.(\d+))?(?:\.(\d+))?{}(?:\+[^\s]+)?".format(MODIFIERS)
_COMPLETE_VERSION = "v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?{}(?:\+[^\s]+)?".format(
MODIFIERS
)
COMPLETE_VERSION = re.compile("(?i)" + _COMPLETE_VERSION)
......
......@@ -20,6 +20,7 @@ class Version(VersionRange):
major, # type: int
minor=None, # type: Union[int, None]
patch=None, # type: Union[int, None]
rest=None, # type: Union[int, None]
pre=None, # type: Union[str, None]
build=None, # type: Union[str, None]
text=None, # type: Union[str, None]
......@@ -44,10 +45,17 @@ class Version(VersionRange):
if self._precision is not None:
self._precision += 1
if rest is None:
rest = 0
else:
if self._precision is not None:
self._precision += 1
if precision is not None:
self._precision = precision
self._patch = int(patch)
self._rest = int(rest)
if text is None:
parts = [str(major)]
......@@ -57,6 +65,9 @@ class Version(VersionRange):
if self._precision >= 3 or patch != 0:
parts.append(str(patch))
if self._precision >= 4 or rest != 0:
parts.append(str(rest))
text = ".".join(parts)
if pre:
text += "-{}".format(pre)
......@@ -94,6 +105,10 @@ class Version(VersionRange):
return self._patch
@property
def rest(self): # type: () -> int
return self._rest
@property
def prerelease(self): # type: () -> List[str]
return self._prerelease
......@@ -185,14 +200,15 @@ class Version(VersionRange):
major = int(match.group(1))
minor = int(match.group(2)) if match.group(2) else None
patch = int(match.group(3)) if match.group(3) else None
rest = int(match.group(4)) if match.group(4) else None
pre = match.group(4)
build = match.group(5)
pre = match.group(5)
build = match.group(6)
if build:
build = build.lstrip("+")
return Version(major, minor, patch, pre, build, text)
return Version(major, minor, patch, rest, pre, build, text)
def is_any(self):
return False
......@@ -289,9 +305,6 @@ class Version(VersionRange):
if not build:
return
if build == "0":
return
if build.startswith("post"):
build = build.lstrip("post")
......@@ -339,6 +352,9 @@ class Version(VersionRange):
if self.patch != other.patch:
return self._cmp_parts(self.patch, other.patch)
if self.rest != other.rest:
return self._cmp_parts(self.rest, other.rest)
# Pre-releases always come before no pre-release string.
if not self.is_prerelease() and other.is_prerelease():
return 1
......@@ -380,7 +396,7 @@ class Version(VersionRange):
if a_part == b_part:
continue
# Missing parts come before present ones.
# Missing parts come after present ones.
if a_part is None:
return -1
......@@ -408,6 +424,7 @@ class Version(VersionRange):
self._major == other.major
and self._minor == other.minor
and self._patch == other.patch
and self._rest == other.rest
and self._prerelease == other.prerelease
and self._build == other.build
)
......
......@@ -22,7 +22,7 @@ from poetry.semver import VersionUnion
("=1.2.3", Version(1, 2, 3)),
("1.2.3", Version(1, 2, 3)),
("=1.0", Version(1, 0, 0)),
("1.2.3b5", Version(1, 2, 3, "b5")),
("1.2.3b5", Version(1, 2, 3, pre="b5")),
(">= 1.2.3", VersionRange(min=Version(1, 2, 3), include_min=True)),
(">dev", VersionRange(min=Version(0, 0, pre="dev"))), # Issue 206
],
......@@ -59,8 +59,11 @@ def test_parse_constraint_wildcard(input, constraint):
("~1.0.0", VersionRange(Version(1, 0, 0), Version(1, 1, 0), True)),
("~1.2", VersionRange(Version(1, 2, 0), Version(1, 3, 0), True)),
("~1.2.3", VersionRange(Version(1, 2, 3), Version(1, 3, 0), True)),
("~1.2-beta", VersionRange(Version(1, 2, 0, "beta"), Version(1, 3, 0), True)),
("~1.2-b2", VersionRange(Version(1, 2, 0, "b2"), Version(1, 3, 0), True)),
(
"~1.2-beta",
VersionRange(Version(1, 2, 0, pre="beta"), Version(1, 3, 0), True),
),
("~1.2-b2", VersionRange(Version(1, 2, 0, pre="b2"), Version(1, 3, 0), True)),
("~0.3", VersionRange(Version(0, 3, 0), Version(0, 4, 0), True)),
("~3.5", VersionRange(Version(3, 5, 0), Version(3, 6, 0), True)),
("~=3.5", VersionRange(Version(3, 5, 0), Version(4, 0, 0), True)), # PEP 440
......@@ -80,7 +83,7 @@ def test_parse_constraint_tilde(input, constraint):
("^1.2", VersionRange(Version(1, 2, 0), Version(2, 0, 0), True)),
(
"^1.2.3-beta.2",
VersionRange(Version(1, 2, 3, "beta.2"), Version(2, 0, 0), True),
VersionRange(Version(1, 2, 3, pre="beta.2"), Version(2, 0, 0), True),
),
("^1.2.3", VersionRange(Version(1, 2, 3), Version(2, 0, 0), True)),
("^0.2.3", VersionRange(Version(0, 2, 3), Version(0, 3, 0), True)),
......@@ -173,3 +176,21 @@ def test_parse_constraints_negative_wildcard(input, constraint):
)
def test_constraints_keep_version_precision(input, expected):
assert str(parse_constraint(input)) == expected
@pytest.mark.parametrize(
"unsorted, sorted_",
[
(["1.0.3", "1.0.2", "1.0.1"], ["1.0.1", "1.0.2", "1.0.3"]),
(["1.0.0.2", "1.0.0.0rc2"], ["1.0.0.0rc2", "1.0.0.2"]),
(["1.0.0.0", "1.0.0.0rc2"], ["1.0.0.0rc2", "1.0.0.0"]),
(["1.0.0.0.0", "1.0.0.0rc2"], ["1.0.0.0rc2", "1.0.0.0.0"]),
(["1.0.0rc2", "1.0.0rc1"], ["1.0.0rc1", "1.0.0rc2"]),
(["1.0.0rc2", "1.0.0b1"], ["1.0.0b1", "1.0.0rc2"]),
],
)
def test_versions_are_sortable(unsorted, sorted_):
unsorted = [parse_constraint(u) for u in unsorted]
sorted_ = [parse_constraint(s) for s in sorted_]
assert sorted(unsorted) == sorted_
......@@ -11,18 +11,18 @@ from poetry.semver import VersionRange
("1.0.0", Version(1, 0, 0)),
("1", Version(1, 0, 0)),
("1.0", Version(1, 0, 0)),
("1b1", Version(1, 0, 0, "beta1")),
("1.0b1", Version(1, 0, 0, "beta1")),
("1.0.0b1", Version(1, 0, 0, "beta1")),
("1.0.0-b1", Version(1, 0, 0, "beta1")),
("1.0.0-beta.1", Version(1, 0, 0, "beta1")),
("1.0.0+1", Version(1, 0, 0, None, "1")),
("1.0.0-1", Version(1, 0, 0, None, "1")),
("1b1", Version(1, 0, 0, pre="beta1")),
("1.0b1", Version(1, 0, 0, pre="beta1")),
("1.0.0b1", Version(1, 0, 0, pre="beta1")),
("1.0.0-b1", Version(1, 0, 0, pre="beta1")),
("1.0.0-beta.1", Version(1, 0, 0, pre="beta1")),
("1.0.0+1", Version(1, 0, 0, build="1")),
("1.0.0-1", Version(1, 0, 0, build="1")),
("1.0.0.0", Version(1, 0, 0)),
("1.0.0-post", Version(1, 0, 0)),
("1.0.0-post1", Version(1, 0, 0, None, "1")),
("0.6c", Version(0, 6, 0, "rc0")),
("0.6pre", Version(0, 6, 0, "rc0")),
("1.0.0-post1", Version(1, 0, 0, build="1")),
("0.6c", Version(0, 6, 0, pre="rc0")),
("0.6pre", Version(0, 6, 0, pre="rc0")),
],
)
def test_parse_valid(input, version):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment