Skip to content

Commit

Permalink
Fix/version range pres (#14814)
Browse files Browse the repository at this point in the history
* wip

* seems to be ok

* fixes

* wip

* fix test
  • Loading branch information
memsharded authored Oct 17, 2023
1 parent c271142 commit 20ed811
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 34 deletions.
11 changes: 7 additions & 4 deletions conans/model/version_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,11 @@ def __init__(self, expression, prerelease):
self.conditions = []
for e in expressions:
e = e.strip()
if e[-1] == "-": # Include pre-releases
e = e[:-1]
self.prerelease = True
self.conditions.extend(self._parse_expression(e))

@staticmethod
def _parse_expression(expression):
if expression == "" or expression == "*":
if expression in ("", "*"):
return [_Condition(">=", Version("0.0.0"))]
elif len(expression) == 1:
raise ConanException(f'Error parsing version range "{expression}"')
Expand All @@ -42,10 +39,14 @@ def _parse_expression(expression):
if version == "":
raise ConanException(f'Error parsing version range "{expression}"')
if operator == "~": # tilde minor
if "-" not in version:
version += "-"
v = Version(version)
index = 1 if len(v.main) > 1 else 0
return [_Condition(">=", v), _Condition("<", v.upper_bound(index))]
elif operator == "^": # caret major
if "-" not in version:
version += "-"
v = Version(version)

def first_non_zero(main):
Expand All @@ -57,6 +58,8 @@ def first_non_zero(main):
initial_index = first_non_zero(v.main)
return [_Condition(">=", v), _Condition("<", v.upper_bound(initial_index))]
else:
if (operator == ">=" or operator == "<") and "-" not in version:
version += "-"
return [_Condition(operator, Version(version))]

def _valid(self, version, conf_resolve_prepreleases):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,23 @@ def test_version_range_conf_explicit_expression():
tc.run("create base/conanfile.py --version=1.5.1")
tc.run("create base/conanfile.py --version=2.5.0-pre")

tc.save({"v1/conanfile.py": GenConanfile("pkg", "1.0").with_requires("base/[>1- <2]"),
"v2/conanfile.py": GenConanfile("pkg", "2.0").with_requires("base/[>2- <3]")})
tc.save({"v1/conanfile.py": GenConanfile("pkg", "1.0").with_requires("base/[>1 <2, include_prerelease]"),
"v2/conanfile.py": GenConanfile("pkg", "2.0").with_requires("base/[>2 <3, include_prerelease]")})

tc.save({"global.conf": "core.version_ranges:resolve_prereleases=False"}, path=tc.cache.cache_folder)
tc.run("create v1/conanfile.py")
assert "base/[>1- <2]: base/1.5.1" in tc.out
assert "base/[>1 <2, include_prerelease]: base/1.5.1" in tc.out
tc.run("create v2/conanfile.py", assert_error=True)
assert "Package 'base/[>2- <3]' not resolved" in tc.out
assert "Package 'base/[>2 <3, include_prerelease]' not resolved" in tc.out

tc.save({"global.conf": "core.version_ranges:resolve_prereleases=True"}, path=tc.cache.cache_folder)
tc.run("create v1/conanfile.py")
assert "base/[>1- <2]: base/1.5.1" in tc.out
assert "base/[>1 <2, include_prerelease]: base/1.5.1" in tc.out
tc.run("create v2/conanfile.py")
assert "base/[>2- <3]: base/2.5.0-pre" in tc.out
assert "base/[>2 <3, include_prerelease]: base/2.5.0-pre" in tc.out

tc.save({"global.conf": "core.version_ranges:resolve_prereleases=None"}, path=tc.cache.cache_folder)
tc.run("create v1/conanfile.py")
assert "base/[>1- <2]: base/1.5.1" in tc.out
assert "base/[>1 <2, include_prerelease]: base/1.5.1" in tc.out
tc.run("create v2/conanfile.py")
assert "base/[>2- <3]: base/2.5.0-pre" in tc.out
assert "base/[>2 <3, include_prerelease]: base/2.5.0-pre" in tc.out
3 changes: 2 additions & 1 deletion conans/test/unittests/model/version/test_version_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
("+build2",
'', None, "build2"),
("1.2.3-pre.4-5-6+build.7-8-9",
"1.2.3", "pre.4-5-6", "build.7-8-9")
"1.2.3", "pre.4-5-6", "build.7-8-9"),
("1-", "1", "", None)
]


Expand Down
52 changes: 31 additions & 21 deletions conans/test/unittests/model/version/test_version_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@

values = [
['>1.0.0', [[['>', '1.0.0']]], ["1.0.1"], ["0.1"]],
['<2.0', [[['<', '2.0']]], ["1.0.1"], ["2.1"]],
['>1 <2.0', [[['>', '1'], ['<', '2.0']]], ["1.5.1"], ["0.1", "2.1"]],
['<2.0', [[['<', '2.0-']]], ["1.0.1"], ["2.1"]],
['>1 <2.0', [[['>', '1'], ['<', '2.0-']]], ["1.5.1"], ["0.1", "2.1"]],
# tilde
['~2.5', [[['>=', '2.5'], ['<', '2.6-']]], ["2.5.0", "2.5.3"], ["2.7", "2.6.1"]],
['~2.5.1', [[['>=', '2.5.1'], ['<', '2.6.0-']]], ["2.5.1", "2.5.3"], ["2.5", "2.6.1"]],
['~1', [[['>=', '1'], ['<', '2-']]], ["1.3", "1.8.1"], ["0.8", "2.2"]],
['~2.5', [[['>=', '2.5-'], ['<', '2.6-']]], ["2.5.0", "2.5.3"], ["2.7", "2.6.1"]],
['~2.5.1', [[['>=', '2.5.1-'], ['<', '2.6.0-']]], ["2.5.1", "2.5.3"], ["2.5", "2.6.1"]],
['~1', [[['>=', '1-'], ['<', '2-']]], ["1.3", "1.8.1"], ["0.8", "2.2"]],
# caret
['^1.2', [[['>=', '1.2'], ['<', '2.0-']]], ["1.2.1", "1.51"], ["1", "2", "2.0.1"]],
['^1.2.3', [[['>=', '1.2.3'], ["<", '2.0.0-']]], ["1.2.3", "1.2.4"], ["2", "2.1", "2.0.1"]],
['^0.1.2', [[['>=', '0.1.2'], ['<', '0.2.0-']]], ["0.1.3", "0.1.44"], ["1", "0.3", "0.2.1"]],
['^1.2', [[['>=', '1.2-'], ['<', '2.0-']]], ["1.2.1", "1.51"], ["1", "2", "2.0.1"]],
['^1.2.3', [[['>=', '1.2.3-'], ["<", '2.0.0-']]], ["1.2.3", "1.2.4"], ["2", "2.1", "2.0.1"]],
['^0.1.2', [[['>=', '0.1.2-'], ['<', '0.2.0-']]], ["0.1.3", "0.1.44"], ["1", "0.3", "0.2.1"]],
# Identity
['1.0.0', [[["=", "1.0.0"]]], ["1.0.0"], ["2", "1.0.1"]],
['=1.0.0', [[["=", "1.0.0"]]], ["1.0.0"], ["2", "1.0.1"]],
Expand All @@ -24,17 +24,20 @@
['', [[[">=", "0.0.0"]]], ["1.0", "a.b"], []],
# Unions
['1.0.0 || 2.1.3', [[["=", "1.0.0"]], [["=", "2.1.3"]]], ["1.0.0", "2.1.3"], ["2", "1.0.1"]],
['>1 <2.0 || ^3.2 ', [[['>', '1'], ['<', '2.0']],
[['>=', '3.2'], ['<', '4.0-']]], ["1.5", "3.3"], ["2.1", "0.1", "5"]],
['>1 <2.0 || ^3.2 ', [[['>', '1'], ['<', '2.0-']],
[['>=', '3.2-'], ['<', '4.0-']]], ["1.5", "3.3"], ["2.1", "0.1", "5"]],
# pre-releases
['', [[[">=", "0.0.0"]]], ["1.0"], ["1.0-pre.1"]],
['*, include_prerelease=True', [[[">=", "0.0.0"]]], ["1.0", "1.0-pre.1"], []],
['*-', [[[">=", "0.0.0"]]], ["1.0", "1.0-pre.1"], []],
['>1- <2.0', [[['>', '1'], ['<', '2.0']]], ["1.5.1-pre1"], ["2.1-pre1"]],
['>1- <2.0 || ^3.2 ', [[['>', '1'], ['<', '2.0']],
[['>=', '3.2'], ['<', '4.0-']]], ["1.5-a1", "3.3"], ["3.3-a1"]],
['^1.1.2-', [[['>=', '1.1.2'], ['<', '2.0.0-']]], ["1.2.3", "1.2.0-alpha1"], ["2.0.0-alpha1"]],
['~1.1.2-', [[['>=', '1.1.2'], ['<', '1.2.0-']]], ["1.1.3", "1.1.3-alpha1"], ["1.2.0-alpha1"]],
['>1- <2.0', [[['>', '1-'], ['<', '2.0-']]],
["1.0", "1.1", "1.9"], ["1-pre.1", "1.5.1-pre1", "2.1-pre1"]],
['>1- <2.0 || ^3.2 ', [[['>', '1-'], ['<', '2.0-']], [['>=', '3.2-'], ['<', '4.0-']]],
["1.0", "1.2", "3.3"], ["1-pre.1", "1.5-a1", "3.3-a1"]],
['^1.1.2', [[['>=', '1.1.2-'], ['<', '2.0.0-']]], ["1.2.3"], ["1.2.0-alpha1", "2.0.0-alpha1"]],
['~1.1.2', [[['>=', '1.1.2-'], ['<', '1.2.0-']]], ["1.1.3"], ["1.1.3-alpha1", "1.2.0-alpha1"]],
['>=2.0-pre.0 <3', [[['>=', '2.0-pre.0'], ['<', '3-']]], ["2.1"], ["2.0-pre.1","2.0-alpha.1"]],
# Or explicitly
['>=2.0-pre.0, include_prerelease', [[['>=', '2.0-pre.0']]], ["2.1", "2.0-pre.1"], ["1.5"]]
]


Expand All @@ -58,10 +61,6 @@ def test_range(version_range, conditions, versions_in, versions_out):
['*', False, ["1.5.1"], ["1.5.1-pre1", "2.1-pre1"]],
['*', None, ["1.5.1"], ["1.5.1-pre1", "2.1-pre1"]],
['*-', True, ["1.5.1", "1.5.1-pre1", "2.1-pre1"], []],
['*-', False, ["1.5.1"], ["1.5.1-pre1", "2.1-pre1"]],
['*-', None, ["1.5.1", "1.5.1-pre1", "2.1-pre1"], []],
['*, include_prerelease', True, ["1.5.1", "1.5.1-pre1", "2.1-pre1"], []],
['*, include_prerelease', False, ["1.5.1"], ["1.5.1-pre1", "2.1-pre1"]],
['*, include_prerelease', None, ["1.5.1", "1.5.1-pre1", "2.1-pre1"], []],
Expand All @@ -72,11 +71,21 @@ def test_range(version_range, conditions, versions_in, versions_out):
['>1- <2.0', True, ["1.5.1", "1.5.1-pre1"], ["2.1-pre1"]],
['>1- <2.0', False, ["1.5.1"], ["1.5.1-pre1", "2.1-pre1"]],
['>1- <2.0', None, ["1.5.1", "1.5.1-pre1"], ["2.1-pre1"]],
['>1- <2.0, include_prerelease', None, ["1.5.1", "1.5.1-pre1"], ["2.1-pre1"]],
['>1 <2.0, include_prerelease', True, ["1.5.1", "1.5.1-pre1"], ["2.1-pre1"]],
['>1 <2.0, include_prerelease', False, ["1.5.1"], ["1.5.1-pre1", "2.1-pre1"]],
['>1 <2.0, include_prerelease', None, ["1.5.1", "1.5.1-pre1"], ["2.1-pre1"]],
# Summary of new behaviors
['>=1 <2.0', False, ["1.0", "1.1", "1.9"], ["0.9", "1.0-pre.1", "1.1-pre.1", "2.0-pre", "2.0"]],
# OLD
# ['>=1 <2.0', True, ["1.0", "1.1-pre.1", "1.1", "1.9", "2.0-pre"], ["0.9", "1.0-pre.1", "2.0"]],
# NEW
['>=1 <2.0', True, ["1.0-pre.1", "1.0", "1.1-pre.1", "1.1", "1.9"], ["0.9", "2.0", "2.0-pre"]],
['>1 <=2.0', False, ["1.1", "1.9", "2.0"], ["0.9", "1.0-pre.1", "1.0", "1.1-pre.1", "2.0-pre"]],
# This should be old and new behaviors remain the same
['>1 <=2.0', True, ["1.1-pre.1", "1.1", "1.9", "2.0", "2.0-pre"], ["0.9", "1.0", "1.0-pre.1"]],
])
def test_range_prereleases_conf(version_range, resolve_prereleases, versions_in, versions_out):
r = VersionRange(version_range)
Expand All @@ -87,6 +96,7 @@ def test_range_prereleases_conf(version_range, resolve_prereleases, versions_in,
for v in versions_out:
assert not r.contains(Version(v), resolve_prereleases), f"Expected '{version_range}' NOT to contain '{v}' (conf.ranges_resolve_prereleases={resolve_prereleases})"


@pytest.mark.parametrize("version_range", [
">= 1.0", # https://github.com/conan-io/conan/issues/12692
">=0.0.1 < 1.0" # https://github.com/conan-io/conan/issues/14612
Expand Down

0 comments on commit 20ed811

Please sign in to comment.