Skip to content

Commit

Permalink
Feature/min conan version (conan-io#7360)
Browse files Browse the repository at this point in the history
* min_conan_version proposal

* removed wrong test

* fix test

* made min_conan_version global

* required_conan_version is now a range

* renamed tests

* review
  • Loading branch information
memsharded authored Jul 22, 2020
1 parent eb5ff51 commit 72b12e7
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 20 deletions.
24 changes: 12 additions & 12 deletions conans/client/conf/required_version.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
from conans.client.cache.cache import ClientCache
from semver import satisfies, Range
from semver import satisfies
from conans import __version__ as client_version
from conans.errors import ConanException


def validate_conan_version(required_range):
result = satisfies(client_version, required_range, loose=True)
if not result:
raise ConanException("Current Conan version ({}) does not satisfy "
"the defined one ({}).".format(client_version, required_range))


def check_required_conan_version(cache_folder, out):
""" Check if the required Conan version in config file matches to the current Conan version
Expand All @@ -17,14 +24,7 @@ def check_required_conan_version(cache_folder, out):
:return: None
"""
cache = ClientCache(cache_folder, out)
required_version = cache.config.required_conan_version
if required_version:
try:
Range(required_version, False)
except ValueError:
raise ConanException("The required version expression '{}' is not valid."
.format(required_version))
result = satisfies(client_version, required_version)
if not result:
raise ConanException("The current Conan version ({}) does not match to the required"
" version ({}).".format(client_version, required_version))
required_range = cache.config.required_conan_version
if required_range:
validate_conan_version(required_range)

13 changes: 11 additions & 2 deletions conans/client/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import yaml

from conans.client.conf.required_version import validate_conan_version
from conans.client.generators import registered_generators
from conans.client.loader_txt import ConanFileTextLoader
from conans.client.tools.files import chdir
Expand Down Expand Up @@ -202,8 +203,12 @@ def load_conanfile(self, conanfile_path, profile, ref, lock_python_requires=None
""" load a conanfile with a full reference, name, version, user and channel are obtained
from the reference, not evaluated. Main way to load from the cache
"""
conanfile, _ = self.load_basic_module(conanfile_path, lock_python_requires,
ref.user, ref.channel, str(ref))
try:
conanfile, _ = self.load_basic_module(conanfile_path, lock_python_requires,
ref.user, ref.channel, str(ref))
except Exception as e:
raise ConanException("%s: Cannot load recipe.\n%s" % (str(ref), str(e)))

conanfile.name = ref.name
conanfile.version = str(ref.version) \
if os.environ.get(CONAN_V2_MODE_ENVVAR, False) else ref.version
Expand Down Expand Up @@ -356,6 +361,10 @@ def _parse_conanfile(conan_file_path):
loaded = imp.load_source(module_id, conan_file_path)
sys.dont_write_bytecode = False

required_conan_version = getattr(loaded, "required_conan_version", None)
if required_conan_version:
validate_conan_version(required_conan_version)

# These lines are necessary, otherwise local conanfile imports with same name
# collide, but no error, and overwrite other packages imports!!
added_modules = set(sys.modules).difference(old_modules)
Expand Down
3 changes: 3 additions & 0 deletions conans/client/tools/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ def __init__(self, value):
except ValueError:
raise ConanException("Invalid version '{}'".format(value))

def __str__(self):
return str(self._semver)

@property
def major(self):
return str(self._semver.major)
Expand Down
34 changes: 34 additions & 0 deletions conans/test/functional/conanfile/required_conan_version_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import textwrap
import unittest

import mock

from conans import __version__
from conans.test.utils.tools import TestClient


class RequiredConanVersionTest(unittest.TestCase):

def required_conan_version_test(self):
client = TestClient()
conanfile = textwrap.dedent("""
from conans import ConanFile
required_conan_version = ">=100.0"
class Lib(ConanFile):
pass
""")
client.save({"conanfile.py": conanfile})
client.run("export . pkg/1.0@", assert_error=True)
self.assertIn("Current Conan version (%s) does not satisfy the defined one (>=100.0)"
% __version__, client.out)
client.run("inspect . ", assert_error=True)
self.assertIn("Current Conan version (%s) does not satisfy the defined one (>=100.0)"
% __version__, client.out)
with mock.patch("conans.client.conf.required_version.client_version", "101.0"):
client.run("export . pkg/1.0@")

client.run("install pkg/1.0@", assert_error=True)
self.assertIn("Current Conan version (%s) does not satisfy the defined one (>=100.0)"
% __version__, client.out)
13 changes: 7 additions & 6 deletions conans/test/functional/configuration/required_version_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import unittest
import mock
from conans.test.utils.tools import TestClient

from conans import __version__
from conans.errors import ConanException
from conans.test.utils.tools import TestClient


class RequiredVersionTest(unittest.TestCase):
Expand All @@ -13,9 +15,8 @@ def test_wrong_version(self):
client.run("config set general.required_conan_version={}".format(required_version))
with self.assertRaises(ConanException) as error:
client.run("help")
self.assertIn("The current Conan version ({}) "
"does not match to the required version ({})."
.format("1.26.0", required_version), str(error.exception))
self.assertIn("Current Conan version (1.26.0) does not satisfy the defined "
"one ({})".format(required_version), str(error.exception))

@mock.patch("conans.client.conf.required_version.client_version", "1.22.0")
def test_exact_version(self):
Expand Down Expand Up @@ -44,5 +45,5 @@ def test_bad_format(self):
client.run("config set general.required_conan_version={}".format(required_version))
with self.assertRaises(ConanException) as error:
client.run("help", assert_error=True)
self.assertIn("The required version expression '{}' is not valid.".format(required_version),
str(error.exception))
self.assertIn("Current Conan version ({}) does not satisfy the defined one ({})"
.format(__version__, required_version), str(error.exception))

0 comments on commit 72b12e7

Please sign in to comment.