Skip to content

Commit

Permalink
Fix constraint upper bound including prereleases
Browse files Browse the repository at this point in the history
  • Loading branch information
sdispater committed Jan 31, 2021
1 parent 76e64cb commit 8996940
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 41 deletions.
29 changes: 5 additions & 24 deletions poetry/core/semver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ def parse_single_constraint(constraint): # type: (str) -> VersionTypes
if len(m.group(1).split(".")) == 1:
high = version.stable.next_major

return VersionRange(
version, high, include_min=True, always_include_max_prerelease=True
)
return VersionRange(version, high, include_min=True)

# PEP 440 Tilde range (~=)
m = TILDE_PEP440_CONSTRAINT.match(constraint)
Expand All @@ -86,21 +84,14 @@ def parse_single_constraint(constraint): # type: (str) -> VersionTypes
else:
high = version.stable.next_minor

return VersionRange(
version, high, include_min=True, always_include_max_prerelease=True
)
return VersionRange(version, high, include_min=True)

# Caret range
m = CARET_CONSTRAINT.match(constraint)
if m:
version = Version.parse(m.group(1))

return VersionRange(
version,
version.next_breaking,
include_min=True,
always_include_max_prerelease=True,
)
return VersionRange(version, version.next_breaking, include_min=True)

# X Range
m = X_CONSTRAINT.match(constraint)
Expand All @@ -112,24 +103,14 @@ def parse_single_constraint(constraint): # type: (str) -> VersionTypes
if minor is not None:
version = Version(major, int(minor), 0)

result = VersionRange(
version,
version.next_minor,
include_min=True,
always_include_max_prerelease=True,
)
result = VersionRange(version, version.next_minor, include_min=True)
else:
if major == 0:
result = VersionRange(max=Version(1, 0, 0))
else:
version = Version(major, 0, 0)

result = VersionRange(
version,
version.next_major,
include_min=True,
always_include_max_prerelease=True,
)
result = VersionRange(version, version.next_major, include_min=True)

if op == "!=":
result = VersionRange().difference(result)
Expand Down
23 changes: 12 additions & 11 deletions poetry/core/semver/version_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ def __init__(
):
full_max = max
if (
always_include_max_prerelease
not always_include_max_prerelease
and not include_max
and full_max is not None
and not full_max.is_prerelease()
and not full_max.build
and (
Expand Down Expand Up @@ -77,11 +78,11 @@ def allows(self, other): # type: ("Version") -> bool
if not self._include_min and other == self._min:
return False

if self._max is not None:
if other > self._max:
if self._full_max is not None:
if other > self._full_max:
return False

if not self._include_max and other == self._max:
if not self._include_max and other == self._full_max:
return False

return True
Expand Down Expand Up @@ -335,28 +336,28 @@ def allows_lower(self, other): # type: (VersionRange) -> bool
return self.include_min and not other.include_min

def allows_higher(self, other): # type: (VersionRange) -> bool
if self.max is None:
if self._full_max is None:
return other.max is not None

if other.max is None:
if other.full_max is None:
return False

if self.max < other.max:
if self._full_max < other.full_max:
return False

if self.max > other.max:
if self._full_max > other.full_max:
return True

return self.include_max and not other.include_max

def is_strictly_lower(self, other): # type: (VersionRange) -> bool
if self.max is None or other.min is None:
if self._full_max is None or other.min is None:
return False

if self.full_max < other.min:
if self._full_max < other.min:
return True

if self.full_max > other.min:
if self._full_max > other.min:
return False

return not self.include_max or not other.include_min
Expand Down
26 changes: 20 additions & 6 deletions tests/semver/test_version_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ def v300():
return Version.parse("3.0.0")


@pytest.fixture()
def v300b1():
return Version.parse("3.0.0b1")


def test_allows_all(v003, v010, v080, v114, v123, v124, v140, v200, v234, v250, v300):
assert VersionRange(v123, v250).allows_all(EmptyConstraint())

Expand Down Expand Up @@ -173,12 +178,7 @@ def test_allows_any(
# pre-release min does not allow lesser than itself
range = VersionRange(Version.parse("1.9b1"), include_min=True)
assert not range.allows_any(
VersionRange(
Version.parse("1.8.0"),
Version.parse("1.9.0"),
include_min=True,
always_include_max_prerelease=True,
)
VersionRange(Version.parse("1.8.0"), Version.parse("1.9.0"), include_min=True)
)


Expand Down Expand Up @@ -258,3 +258,17 @@ def test_union(
assert result == VersionRange(v003, v200)
result = VersionRange(v003, v114).union(VersionRange(v114, v200, include_min=True))
assert result == VersionRange(v003, v200)


def test_include_max_prerelease(v200, v300, v300b1):
result = VersionRange(v200, v300)

assert not result.allows(v300b1)
assert not result.allows_any(VersionRange(v300b1))
assert not result.allows_all(VersionRange(v200, v300b1))

result = VersionRange(v200, v300, always_include_max_prerelease=True)

assert result.allows(v300b1)
assert result.allows_any(VersionRange(v300b1))
assert result.allows_all(VersionRange(v200, v300b1))

0 comments on commit 8996940

Please sign in to comment.