def _loader(self, current_path=None, user_settings_values=None, package_settings=None, user_options_values=None, scopes=None, env_values=None, use_conaninfo=True): # The disk settings definition, already including the default disk values settings = self._client_cache.settings conaninfo_scopes = Scopes() user_options = OptionsValues(user_options_values) mixed_env_values = EnvValues() mixed_env_values.update(env_values) if current_path: conan_info_path = os.path.join(current_path, CONANINFO) if use_conaninfo and os.path.exists(conan_info_path): existing_info = ConanInfo.load_file(conan_info_path) settings.values = existing_info.full_settings options = existing_info.full_options # Take existing options from conaninfo.txt options.update(user_options) user_options = options conaninfo_scopes = existing_info.scope # Update with info (prioritize user input) mixed_env_values.update(existing_info.env_values) if user_settings_values: aux_values = Values.from_list(user_settings_values) settings.values = aux_values if scopes: conaninfo_scopes.update_scope(scopes) self._current_scopes = conaninfo_scopes return ConanFileLoader(self._runner, settings, package_settings=package_settings, options=user_options, scopes=conaninfo_scopes, env_values=mixed_env_values)
def __init__(self): # Sections self.settings = OrderedDict() self.package_settings = defaultdict(OrderedDict) self.env_values = EnvValues() self.scopes = Scopes() self.options = OptionsValues()
def __init__(self): # Sections self._settings = OrderedDict() self._package_settings = defaultdict(OrderedDict) self._env = OrderedDict() self._package_env = defaultdict(OrderedDict) self.scopes = Scopes()
def _loader(self, current_path=None, user_settings_values=None, user_options_values=None, scopes=None): # The disk settings definition, already including the default disk values settings = self._paths.settings options = OptionsValues() conaninfo_scopes = Scopes() if current_path: conan_info_path = os.path.join(current_path, CONANINFO) if os.path.exists(conan_info_path): existing_info = ConanInfo.load_file(conan_info_path) settings.values = existing_info.full_settings options = existing_info.full_options # Take existing options from conaninfo.txt conaninfo_scopes = existing_info.scope if user_settings_values: aux_values = Values.from_list(user_settings_values) settings.values = aux_values if user_options_values is not None: # Install will pass an empty list [] # Install OVERWRITES options, existing options in CONANINFO are not taken # into account, just those from CONANFILE + user command line options = OptionsValues.from_list(user_options_values) if scopes: conaninfo_scopes.update_scope(scopes) self._current_scopes = conaninfo_scopes return ConanFileLoader(self._runner, settings, options=options, scopes=conaninfo_scopes)
def __init__(self): # Sections self.settings = OrderedDict() self.package_settings = defaultdict(OrderedDict) self.env_values = EnvValues() self.scopes = Scopes() self.options = OptionsValues() self.build_requires = OrderedDict() # conan_ref Pattern: list of conan_ref
def _profile_parse_args(settings, options, envs, scopes): """ return a Profile object result of parsing raw data """ def _get_tuples_list_from_extender_arg(items): if not items: return [] # Validate the pairs for item in items: chunks = item.split("=", 1) if len(chunks) != 2: raise ConanException("Invalid input '%s', use 'name=value'" % item) return [(item[0], item[1]) for item in [item.split("=", 1) for item in items]] def _get_simple_and_package_tuples(items): """Parse items like "thing:item=value or item2=value2 and returns a tuple list for the simple items (name, value) and a dict for the package items {package: [(item, value)...)], ...} """ simple_items = [] package_items = defaultdict(list) tuples = _get_tuples_list_from_extender_arg(items) for name, value in tuples: if ":" in name: # Scoped items tmp = name.split(":", 1) ref_name = tmp[0] name = tmp[1] package_items[ref_name].append((name, value)) else: simple_items.append((name, value)) return simple_items, package_items def _get_env_values(env, package_env): env_values = EnvValues() for name, value in env: env_values.add(name, EnvValues.load_value(value)) for package, data in package_env.items(): for name, value in data: env_values.add(name, EnvValues.load_value(value), package) return env_values result = Profile() options = _get_tuples_list_from_extender_arg(options) result.options = OptionsValues(options) env, package_env = _get_simple_and_package_tuples(envs) env_values = _get_env_values(env, package_env) result.env_values = env_values settings, package_settings = _get_simple_and_package_tuples(settings) result.settings = OrderedDict(settings) for pkg, values in package_settings.items(): result.package_settings[pkg] = OrderedDict(values) result.scopes = Scopes.from_list(scopes) if scopes else Scopes() return result
def loads(text): obj = Profile() doc = ConfigParser(text, allowed_fields=["settings", "env", "scopes"]) for setting in doc.settings.splitlines(): setting = setting.strip() if setting and not setting.startswith("#"): if "=" not in setting: raise ConanException("Invalid setting line '%s'" % setting) name, value = setting.split("=") obj.settings[name.strip()] = value.strip() if doc.scopes: obj.scopes = Scopes.from_list(doc.scopes.splitlines()) for env in doc.env.splitlines(): env = env.strip() if env and not env.startswith("#"): if "=" not in env: raise ConanException("Invalid env line '%s'" % env) varname, value = env.split("=") obj.env[varname.strip()] = value.strip() obj._order() return obj
def loads(text): try: obj = Profile() doc = ConfigParser(text, allowed_fields=["settings", "env", "scopes"]) for setting in doc.settings.splitlines(): setting = setting.strip() if setting and not setting.startswith("#"): if "=" not in setting: raise ConanException("Invalid setting line '%s'" % setting) name, value = setting.split("=", 1) obj.settings[name.strip()] = _clean_value(value) if doc.scopes: obj.scopes = Scopes.from_list(doc.scopes.splitlines()) for env in doc.env.splitlines(): env = env.strip() if env and not env.startswith("#"): if "=" not in env: raise ConanException("Invalid env line '%s'" % env) varname, value = env.split("=", 1) obj.env[varname.strip()] = _clean_value(value) obj._order() return obj except ConanException: raise except Exception as exc: raise ConanException("Error parsing the profile text file: %s" % str(exc))
def create_profile(folder, name, settings=None, scopes=None, package_settings=None, env=None, package_env=None): package_env = package_env or {} profile = Profile() profile._settings = settings or {} if scopes: profile.scopes = Scopes.from_list( ["%s=%s" % (key, value) for key, value in scopes.items()]) if package_settings: profile._package_settings = package_settings for package_name, envs in package_env.items(): for var_name, value in envs: profile.env_values.add(var_name, value, package_name) for var_name, value in env or {}: profile.env_values.add(var_name, value) save(os.path.join(folder, name), profile.dumps())
def test_replace_in_file(self): file_content = ''' from conans import ConanFile from conans.tools import download, unzip, replace_in_file import os class ConanFileToolsTest(ConanFile): name = "test" version = "1.9.10" settings = [] def source(self): pass def build(self): replace_in_file("otherfile.txt", "ONE TWO THREE", "FOUR FIVE SIX") ''' tmp_dir = temp_folder() file_path = os.path.join(tmp_dir, "conanfile.py") other_file = os.path.join(tmp_dir, "otherfile.txt") save(file_path, file_content) save(other_file, "ONE TWO THREE") loader = ConanFileLoader(None, Settings(), None, OptionsValues.loads(""), Scopes(), None, None) ret = loader.load_conan(file_path, None) curdir = os.path.abspath(os.curdir) os.chdir(tmp_dir) try: ret.build() finally: os.chdir(curdir) content = load(other_file) self.assertEquals(content, "FOUR FIVE SIX")
def update_profile(self, profile_name, key, value): first_key, rest_key = self._get_profile_keys(key) profile, _ = read_profile(profile_name, os.getcwd(), self._client_cache.profiles_path) if first_key == "settings": profile.settings[rest_key] = value elif first_key == "options": tmp = OptionsValues([(rest_key, value)]) profile.options.update(tmp) elif first_key == "env": profile.env_values.update( EnvValues.loads("%s=%s" % (rest_key, value))) elif first_key == "scopes": profile.update_scopes( Scopes.from_list(["%s=%s" % (rest_key, value)])) elif first_key == "build_requires": raise ConanException( "Edit the profile manually to change the build_requires") contents = profile.dumps() profile_path = get_profile_path(profile_name, self._client_cache.profiles_path, os.getcwd()) save(profile_path, contents)
def _create_profile(self, name, settings, scopes=None, env=None): profile = Profile() profile.settings = settings or {} if scopes: profile.scopes = Scopes.from_list(["%s=%s" % (key, value) for key, value in scopes.items()]) profile.env = env or {} save(self.client.client_cache.profile_path(name), profile.dumps())
def _create_profile(self, name, settings, scopes=None, env=None): profile = Profile() profile._settings = settings or {} if scopes: profile.scopes = Scopes.from_list( ["%s=%s" % (key, value) for key, value in scopes.items()]) profile._env = env or {} save(self.client.client_cache.profile_path(name), profile.dumps())
def _create_profile(self, name, settings, scopes=None, env=None): env = env or {} profile = Profile() profile._settings = settings or {} if scopes: profile.scopes = Scopes.from_list(["%s=%s" % (key, value) for key, value in scopes.items()]) for varname, value in env.items(): profile.env_values.add(varname, value) save(os.path.join(self.client.client_cache.profiles_path, name), profile.dumps())
def install(self, *args): """ install in the local store the given requirements. Requirements can be defined in the command line or in a conanfile. EX: conan install opencv/2.4.10@lasote/testing """ parser = argparse.ArgumentParser(description=self.install.__doc__, prog="conan install", formatter_class=RawTextHelpFormatter) parser.add_argument("reference", nargs='?', default="", help='package recipe reference' 'e.g., MyPackage/1.2@user/channel or ./my_project/') parser.add_argument("--package", "-p", nargs=1, action=Extender, help='Force install specified package ID (ignore settings/options)') parser.add_argument("--all", action='store_true', default=False, help='Install all packages from the specified package recipe') parser.add_argument("--integrity", "-i", action='store_true', default=False, help='Check that the stored recipe or package manifests are correct') parser.add_argument("--file", "-f", help="specify conanfile filename") parser.add_argument("--update", "-u", action='store_true', default=False, help="update with new upstream packages") parser.add_argument("--scope", "-sc", nargs=1, action=Extender, help='Define scopes for packages') parser.add_argument("--generator", "-g", nargs=1, action=Extender, help='Generators to use') self._parse_args(parser) args = parser.parse_args(*args) current_path = os.getcwd() try: reference = ConanFileReference.loads(args.reference) except: reference = os.path.normpath(os.path.join(current_path, args.reference)) if args.all or args.package: # Install packages without settings (fixed ids or all) if args.all: args.package = [] if not args.reference or not isinstance(reference, ConanFileReference): raise ConanException("Invalid package recipe reference. " "e.g., MyPackage/1.2@user/channel") self._manager.download(reference, args.package, remote=args.remote) else: # Classic install, package chosen with settings and options # Get False or a list of patterns to check args.build = self._get_build_sources_parameter(args.build) options = self._get_tuples_list_from_extender_arg(args.options) settings = self._get_tuples_list_from_extender_arg(args.settings) scopes = Scopes.from_list(args.scope) if args.scope else None self._manager.install(reference=reference, current_path=current_path, remote=args.remote, options=options, settings=settings, build_mode=args.build, filename=args.file, update=args.update, integrity=args.integrity, scopes=scopes, generators=args.generator)
def _apply_inner_profile(doc, base_profile): """ :param doc: ConfigParser object from the current profile (excluding includes and vars, and with values already replaced) :param base_profile: Profile inherited, it's used as a base profile to modify it. :return: None """ def get_package_name_value(item): """Parse items like package:name=value or name=value""" package_name = None if ":" in item: tmp = item.split(":", 1) package_name, item = tmp name, value = item.split("=", 1) name = name.strip() value = unquote(value) return package_name, name, value for setting in doc.settings.splitlines(): setting = setting.strip() if setting and not setting.startswith("#"): if "=" not in setting: raise ConanException("Invalid setting line '%s'" % setting) package_name, name, value = get_package_name_value(setting) if package_name: base_profile.package_settings[package_name][name] = value else: base_profile.settings[name] = value if doc.build_requires: # FIXME CHECKS OF DUPLICATED? for req in doc.build_requires.splitlines(): tokens = req.split(":", 1) if len(tokens) == 1: pattern, req_list = "*", req else: pattern, req_list = tokens req_list = [ ConanFileReference.loads(r.strip()) for r in req_list.split(",") ] base_profile.build_requires.setdefault(pattern, []).extend(req_list) if doc.scopes: base_profile.update_scopes(Scopes.from_list(doc.scopes.splitlines())) if doc.options: base_profile.options.update(OptionsValues.loads(doc.options)) base_profile.env_values.update(EnvValues.loads(doc.env))
def _build_and_check(self, tmp_dir, file_path, text_file, msg): loader = ConanFileLoader(None, Settings(), None, OptionsValues.loads(""), Scopes(), None) ret = loader.load_conan(file_path, None) curdir = os.path.abspath(os.curdir) os.chdir(tmp_dir) try: ret.build() finally: os.chdir(curdir) content = load(text_file) self.assertEquals(content, msg)
def test_package_settings(self): # CREATE A CONANFILE TO LOAD tmp_dir = temp_folder() conanfile_path = os.path.join(tmp_dir, "conanfile.py") conanfile = """from conans import ConanFile class MyTest(ConanFile): requires = {} name = "MyPackage" version = "1.0" settings = "os" """ save(conanfile_path, conanfile) # Apply windows for MyPackage package_settings = {"MyPackage": [("os", "Windows")]} loader = ConanFileLoader(None, Settings({"os": ["Windows", "Linux"]}), package_settings, OptionsValues.loads(""), Scopes(), None, None) recipe = loader.load_conan(conanfile_path, None) self.assertEquals(recipe.settings.os, "Windows") # Apply Linux for MyPackage package_settings = {"MyPackage": [("os", "Linux")]} loader = ConanFileLoader(None, Settings({"os": ["Windows", "Linux"]}), package_settings, OptionsValues.loads(""), Scopes(), None, None) recipe = loader.load_conan(conanfile_path, None) self.assertEquals(recipe.settings.os, "Linux") # If the package name is different from the conanfile one, it wont apply package_settings = {"OtherPACKAGE": [("os", "Linux")]} loader = ConanFileLoader(None, Settings({"os": ["Windows", "Linux"]}), package_settings, OptionsValues.loads(""), Scopes(), None, None) recipe = loader.load_conan(conanfile_path, None) self.assertIsNone(recipe.settings.os.value)
def loads(text): def get_package_name_value(item): '''Parse items like package:name=value or name=value''' package_name = None if ":" in item: tmp = item.split(":", 1) package_name, item = tmp name, value = item.split("=", 1) name = name.strip() value = _clean_value(value) return package_name, name, value try: obj = Profile() doc = ConfigParser(text, allowed_fields=["settings", "env", "scopes"]) for setting in doc.settings.splitlines(): setting = setting.strip() if setting and not setting.startswith("#"): if "=" not in setting: raise ConanException("Invalid setting line '%s'" % setting) package_name, name, value = get_package_name_value(setting) if package_name: obj._package_settings[package_name][name] = value else: obj._settings[name] = value if doc.scopes: obj.scopes = Scopes.from_list(doc.scopes.splitlines()) for env in doc.env.splitlines(): env = env.strip() if env and not env.startswith("#"): if "=" not in env: raise ConanException("Invalid env line '%s'" % env) package_name, name, value = get_package_name_value(env) if package_name: obj._package_env[package_name][name] = value else: obj._env[name] = value obj._order() return obj except ConanException: raise except Exception as exc: raise ConanException("Error parsing the profile text file: %s" % str(exc))
def info(self, *args): """ Prints information about the requirements. Requirements can be defined in the command line or in a conanfile. EX: conan info opencv/2.4.10@lasote/testing """ parser = argparse.ArgumentParser(description=self.info.__doc__, prog="conan info", formatter_class=RawTextHelpFormatter) parser.add_argument("reference", nargs='?', default="", help='reference name or path to conanfile file, ' 'e.g., MyPackage/1.2@user/channel or ./my_project/') parser.add_argument("--file", "-f", help="specify conanfile filename") parser.add_argument("-r", "--remote", help='look for in the remote storage') parser.add_argument("--options", "-o", help='load options to build the package, e.g., -o with_qt=true', nargs=1, action=Extender) parser.add_argument("--settings", "-s", help='load settings to build the package, -s compiler:gcc', nargs=1, action=Extender) parser.add_argument("--only", "-n", help='show fields only') parser.add_argument("--integrity", "-i", action='store_true', default=False, help='Check that the stored recipe or package manifests are correct') parser.add_argument("--update", "-u", action='store_true', default=False, help="check updates exist from upstream remotes") parser.add_argument("--build_order", "-bo", help='given a modified reference, return ordered list to build (CI)', nargs=1, action=Extender) parser.add_argument("--scope", "-sc", nargs=1, action=Extender, help='Define scopes for packages') args = parser.parse_args(*args) options = self._get_tuples_list_from_extender_arg(args.options) settings = self._get_tuples_list_from_extender_arg(args.settings) current_path = os.getcwd() try: reference = ConanFileReference.loads(args.reference) except: reference = os.path.normpath(os.path.join(current_path, args.reference)) scopes = Scopes.from_list(args.scope) if args.scope else None self._manager.info(reference=reference, current_path=current_path, remote=args.remote, options=options, settings=settings, info=args.only or True, check_updates=args.update, integrity=args.integrity, filename=args.file, build_order=args.build_order, scopes=scopes)
def loads(text): parser = ConfigParser(text, ["settings", "full_settings", "options", "full_options", "requires", "full_requires", "scope"]) result = ConanInfo() result.settings = Values.loads(parser.settings) result.full_settings = Values.loads(parser.full_settings) result.options = OptionsValues.loads(parser.options) result.full_options = OptionsValues.loads(parser.full_options) result.full_requires = RequirementsList.loads(parser.full_requires) result.requires = RequirementsInfo(result.full_requires, None) # TODO: Missing handling paring of requires, but not necessary now result.scope = Scopes.loads(parser.scope) return result
def _apply_inner_profile(doc, base_profile): """ :param doc: ConfigParser object from the current profile (excluding includes and vars, and with values already replaced) :param base_profile: Profile inherited, it's used as a base profile to modify it. :return: None """ def get_package_name_value(item): """Parse items like package:name=value or name=value""" package_name = None if ":" in item: tmp = item.split(":", 1) package_name, item = tmp name, value = item.split("=", 1) name = name.strip() value = unquote(value) return package_name, name, value for setting in doc.settings.splitlines(): setting = setting.strip() if setting and not setting.startswith("#"): if "=" not in setting: raise ConanException("Invalid setting line '%s'" % setting) package_name, name, value = get_package_name_value(setting) if package_name: base_profile.package_settings[package_name][name] = value else: base_profile.settings[name] = value if doc.build_requires: # FIXME CHECKS OF DUPLICATED? for req in doc.build_requires.splitlines(): tokens = req.split(":", 1) if len(tokens) == 1: pattern, req_list = "*", req else: pattern, req_list = tokens req_list = [ConanFileReference.loads(r.strip()) for r in req_list.split(",")] base_profile.build_requires.setdefault(pattern, []).extend(req_list) if doc.scopes: base_profile.update_scopes(Scopes.from_list(doc.scopes.splitlines())) if doc.options: base_profile.options.update(OptionsValues.loads(doc.options)) base_profile.env_values.update(EnvValues.loads(doc.env))
def loads(text): def get_package_name_value(item): """Parse items like package:name=value or name=value""" package_name = None if ":" in item: tmp = item.split(":", 1) package_name, item = tmp name, value = item.split("=", 1) name = name.strip() value = _clean_value(value) return package_name, name, value try: obj = Profile() doc = ConfigParser(text, allowed_fields=["settings", "env", "scopes"]) for setting in doc.settings.splitlines(): setting = setting.strip() if setting and not setting.startswith("#"): if "=" not in setting: raise ConanException("Invalid setting line '%s'" % setting) package_name, name, value = get_package_name_value(setting) if package_name: obj._package_settings[package_name][name] = value else: obj._settings[name] = value if doc.scopes: obj.scopes = Scopes.from_list(doc.scopes.splitlines()) for env in doc.env.splitlines(): env = env.strip() if env and not env.startswith("#"): if "=" not in env: raise ConanException("Invalid env line '%s'" % env) package_name, name, value = get_package_name_value(env) if package_name: obj._package_env[package_name][name] = value else: obj._env[name] = value obj._order() return obj except ConanException: raise except Exception as exc: raise ConanException("Error parsing the profile text file: %s" % str(exc))
def loads(text): parser = ConfigParser(text, [ "settings", "full_settings", "options", "full_options", "requires", "full_requires", "scope" ]) result = ConanInfo() result.settings = Values.loads(parser.settings) result.full_settings = Values.loads(parser.full_settings) result.options = OptionsValues.loads(parser.options) result.full_options = OptionsValues.loads(parser.full_options) result.full_requires = RequirementsList.loads(parser.full_requires) result.requires = RequirementsInfo(result.full_requires, None) # TODO: Missing handling paring of requires, but not necessary now result.scope = Scopes.loads(parser.scope) return result
def requires_init_test(self): loader = ConanFileLoader(None, Settings(), None, OptionsValues.loads(""), Scopes(), None, None) tmp_dir = temp_folder() conanfile_path = os.path.join(tmp_dir, "conanfile.py") conanfile = """from conans import ConanFile class MyTest(ConanFile): requires = {} def requirements(self): self.requires("MyPkg/0.1@user/channel") """ for requires in ("''", "[]", "()", "None"): save(conanfile_path, conanfile.format(requires)) result = loader.load_conan(conanfile_path, output=None, consumer=True) result.requirements() self.assertEqual("MyPkg/0.1@user/channel", str(result.requires))
def info(self, *args): """ Prints information about the requirements. Requirements can be defined in the command line or in a conanfile. EX: conan info opencv/2.4.10@lasote/testing """ parser = argparse.ArgumentParser(description=self.info.__doc__, prog="conan info", formatter_class=RawTextHelpFormatter) parser.add_argument("reference", nargs='?', default="", help='reference name or path to conanfile file, ' 'e.g., MyPackage/1.2@user/channel or ./my_project/') parser.add_argument("--file", "-f", help="specify conanfile filename") parser.add_argument("-r", "--remote", help='look for in the remote storage') parser.add_argument("--options", "-o", help='load options to build the package, e.g., -o with_qt=true', nargs=1, action=Extender) parser.add_argument("--settings", "-s", help='load settings to build the package, -s compiler:gcc', nargs=1, action=Extender) parser.add_argument("--only", "-n", help='show fields only') parser.add_argument("--update", "-u", action='store_true', default=False, help="check updates exist from upstream remotes") parser.add_argument("--build_order", "-bo", help='given a modified reference, return ordered list to build (CI)', nargs=1, action=Extender) parser.add_argument("--scope", "-sc", nargs=1, action=Extender, help='Define scopes for packages') args = parser.parse_args(*args) options = self._get_tuples_list_from_extender_arg(args.options) settings = self._get_tuples_list_from_extender_arg(args.settings) current_path = os.getcwd() try: reference = ConanFileReference.loads(args.reference) except: reference = os.path.normpath(os.path.join(current_path, args.reference)) scopes = Scopes.from_list(args.scope) if args.scope else None self._manager.info(reference=reference, current_path=current_path, remote=args.remote, options=options, settings=settings, info=args.only or True, check_updates=args.update, filename=args.file, build_order=args.build_order, scopes=scopes)
def loads(text): parser = ConfigParser(text, ["settings", "full_settings", "options", "full_options", "requires", "full_requires", "scope", "recipe_hash", "env"], raise_unexpected_field=False) result = ConanInfo() result.settings = Values.loads(parser.settings) result.full_settings = Values.loads(parser.full_settings) result.options = OptionsValues.loads(parser.options) result.full_options = OptionsValues.loads(parser.full_options) result.full_requires = RequirementsList.loads(parser.full_requires) result.requires = RequirementsInfo(result.full_requires, None) result.recipe_hash = parser.recipe_hash or None # TODO: Missing handling paring of requires, but not necessary now result.scope = Scopes.loads(parser.scope) result.env_values = EnvValues.loads(parser.env) return result
def test_patch_from_file(self): file_content = ''' from conans import ConanFile from conans.tools import patch import os class ConanFileToolsTest(ConanFile): name = "test" version = "1.9.10" settings = [] def source(self): pass def build(self): patch(patch_file="file.patch") ''' patch_content = '''--- text.txt\t2016-01-25 17:57:11.452848309 +0100 +++ text_new.txt\t2016-01-25 17:57:28.839869950 +0100 @@ -1 +1 @@ -ONE TWO THREE +ONE TWO FOUR''' tmp_dir = temp_folder() file_path = os.path.join(tmp_dir, "conanfile.py") text_file = os.path.join(tmp_dir, "text.txt") patch_file = os.path.join(tmp_dir, "file.patch") save(file_path, file_content) save(text_file, "ONE TWO THREE") save(patch_file, patch_content) loader = ConanFileLoader(None, Settings(), None, OptionsValues.loads(""), Scopes(), None, None) ret = loader.load_conan(file_path, None) curdir = os.path.abspath(os.curdir) os.chdir(tmp_dir) try: ret.build() finally: os.chdir(curdir) content = load(text_file) self.assertEquals(content, "ONE TWO FOUR")
def setUp(self): self.output = TestBufferConanOutput() self.loader = ConanFileLoader(None, Settings.loads(""), None, OptionsValues.loads(""), Scopes(), None, None) self.retriever = Retriever(self.loader, self.output) self.remote_search = MockSearchRemote() self.resolver = RequireResolver(self.output, self.retriever, self.remote_search) self.builder = DepsBuilder(self.retriever, self.output, self.loader, self.resolver) for v in ["0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"]: say_content = """ from conans import ConanFile class SayConan(ConanFile): name = "Say" version = "%s" """ % v say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % v) self.retriever.conan(say_ref, say_content)
def loads(text): """ Parse and return a Profile object from a text config like representation """ def get_package_name_value(item): '''Parse items like package:name=value or name=value''' package_name = None if ":" in item: tmp = item.split(":", 1) package_name, item = tmp name, value = item.split("=", 1) name = name.strip() value = unquote(value) return package_name, name, value try: obj = Profile() doc = ConfigParser(text, allowed_fields=["settings", "env", "scopes", "options"]) for setting in doc.settings.splitlines(): setting = setting.strip() if setting and not setting.startswith("#"): if "=" not in setting: raise ConanException("Invalid setting line '%s'" % setting) package_name, name, value = get_package_name_value(setting) if package_name: obj.package_settings[package_name][name] = value else: obj.settings[name] = value if doc.scopes: obj.scopes = Scopes.from_list(doc.scopes.splitlines()) if doc.options: obj.options = OptionsValues.loads(doc.options) obj.env_values = EnvValues.loads(doc.env) return obj except ConanException: raise except Exception as exc: raise ConanException("Error parsing the profile text file: %s" % str(exc))
def _create_profile(self, name, settings, scopes=None, package_settings=None, env=None, package_env=None): package_env = package_env or {} profile = Profile() profile._settings = settings or {} if scopes: profile.scopes = Scopes.from_list(["%s=%s" % (key, value) for key, value in scopes.items()]) if package_settings: profile._package_settings = package_settings for package_name, envs in package_env.items(): for var_name, value in envs: profile._package_env[package_name][var_name] = value for var_name, value in env or {}: profile._env[var_name] = value save(self.client.client_cache.profile_path(name), profile.dumps())
def create_profile(folder, name, settings=None, scopes=None, package_settings=None, env=None, package_env=None): package_env = package_env or {} profile = Profile() profile._settings = settings or {} if scopes: profile.scopes = Scopes.from_list(["%s=%s" % (key, value) for key, value in scopes.items()]) if package_settings: profile._package_settings = package_settings for package_name, envs in package_env.items(): for var_name, value in envs: profile._package_env[package_name][var_name] = value for var_name, value in env or {}: profile._env[var_name] = value save(os.path.join(folder, name), profile.dumps())
def from_list_test(self): scope = Scopes.from_list(["theroot:thescope=http://conan.io"]) self.assertEquals(scope["theroot"]["thescope"], "http://conan.io") self.assertEquals(scope.package_scope("theroot")["thescope"], "http://conan.io") scope = Scopes.from_list(["thescope=http://conan.io"]) self.assertEquals(scope["0CONAN_ROOT*"]["thescope"], "http://conan.io") scope = Scopes.from_list(["theroot:thescope=TRUE"]) self.assertTrue(scope["theroot"]["thescope"]) scope = Scopes.from_list(["theroot:thescope=true"]) self.assertTrue(scope["theroot"]["thescope"]) scope = Scopes.from_list(["theroot:thescope=FALSE"]) self.assertFalse(scope["theroot"]["thescope"]) scope = Scopes.from_list(["theroot:thescope=false"]) self.assertFalse(scope["theroot"]["thescope"])
def from_list_test(self): scope = Scopes.from_list(["theroot:thescope=http://conan.io"]) self.assertEquals(scope["theroot"]["thescope"], "http://conan.io") self.assertEquals( scope.package_scope("theroot")["thescope"], "http://conan.io") scope = Scopes.from_list(["thescope=http://conan.io"]) self.assertEquals(scope["0CONAN_ROOT*"]["thescope"], "http://conan.io") scope = Scopes.from_list(["theroot:thescope=TRUE"]) self.assertTrue(scope["theroot"]["thescope"]) scope = Scopes.from_list(["theroot:thescope=true"]) self.assertTrue(scope["theroot"]["thescope"]) scope = Scopes.from_list(["theroot:thescope=FALSE"]) self.assertFalse(scope["theroot"]["thescope"]) scope = Scopes.from_list(["theroot:thescope=false"]) self.assertFalse(scope["theroot"]["thescope"])
class Profile(object): """A profile contains a set of setting (with values), environment variables and scopes""" def __init__(self): # Sections self.settings = OrderedDict() self.package_settings = defaultdict(OrderedDict) self.env_values = EnvValues() self.scopes = Scopes() self.options = OptionsValues() self.build_requires = OrderedDict() # conan_ref Pattern: list of conan_ref @property def settings_values(self): return Values.from_list(list(self.settings.items())) @property def package_settings_values(self): result = {} for pkg, settings in self.package_settings.items(): result[pkg] = list(settings.items()) return result def dumps(self): result = ["[build_requires]"] for pattern, req_list in self.build_requires.items(): result.append("%s: %s" % (pattern, ", ".join(str(r) for r in req_list))) result.append("[settings]") for name, value in self.settings.items(): result.append("%s=%s" % (name, value)) for package, values in self.package_settings.items(): for name, value in values.items(): result.append("%s:%s=%s" % (package, name, value)) result.append("[options]") result.append(self.options.dumps()) result.append("[scopes]") if self.scopes[_root].get("dev", None): # FIXME: Ugly _root import del self.scopes[_root]["dev"] # Do not include dev scopes_txt = self.scopes.dumps() result.append(scopes_txt) result.append("[env]") result.append(self.env_values.dumps()) return "\n".join(result).replace("\n\n", "\n") def update(self, other): self.update_settings(other.settings) self.update_package_settings(other.package_settings) self.update_scopes(other.scopes) # this is the opposite other.env_values.update(self.env_values) self.env_values = other.env_values self.options.update(other.options) for pattern, req_list in other.build_requires.items(): self.build_requires.setdefault(pattern, []).extend(req_list) def update_settings(self, new_settings): '''Mix the specified settings with the current profile. Specified settings are prioritized to profile''' # apply the current profile if new_settings: self.settings.update(new_settings) def update_package_settings(self, package_settings): '''Mix the specified package settings with the specified profile. Specified package settings are prioritized to profile''' for package_name, settings in package_settings.items(): self.package_settings[package_name].update(settings) def update_scopes(self, new_scopes): '''Mix the specified settings with the current profile. Specified settings are prioritized to profile''' # apply the current profile if new_scopes: self.scopes.update(new_scopes)
def load_conan_txt_test(self): file_content = '''[requires] OpenCV/2.4.10@phil/stable OpenCV2/2.4.10@phil/stable [generators] one two [imports] OpenCV/bin, * -> ./bin # I need this binaries OpenCV/lib, * -> ./lib [options] OpenCV:use_python=True OpenCV:other_option=False OpenCV2:use_python2=1 OpenCV2:other_option=Cosa ''' tmp_dir = temp_folder() file_path = os.path.join(tmp_dir, "file.txt") save(file_path, file_content) loader = ConanFileLoader(None, Settings(), OptionsValues.loads(""), Scopes()) ret = loader.load_conan_txt(file_path, None) options1 = OptionsValues.loads("""OpenCV:use_python=True OpenCV:other_option=False OpenCV2:use_python2=1 OpenCV2:other_option=Cosa""") requirements = Requirements() requirements.add("OpenCV/2.4.10@phil/stable") requirements.add("OpenCV2/2.4.10@phil/stable") self.assertEquals(ret.requires, requirements) self.assertEquals(ret.generators, ["one", "two"]) self.assertEquals(ret.options.values.dumps(), options1.dumps()) ret.copy = Mock() ret.imports() self.assertTrue(ret.copy.call_args_list, [('*', './bin', 'OpenCV/bin'), ('*', './lib', 'OpenCV/lib')]) # Now something that fails file_content = '''[requires] OpenCV/2.4.104phil/stable <- use_python:True, other_option:False ''' tmp_dir = temp_folder() file_path = os.path.join(tmp_dir, "file.txt") save(file_path, file_content) loader = ConanFileLoader(None, Settings(), OptionsValues.loads(""), Scopes()) with self.assertRaisesRegexp(ConanException, "Wrong package recipe reference(.*)"): loader.load_conan_txt(file_path, None) file_content = '''[requires] OpenCV/2.4.10@phil/stable <- use_python:True, other_option:False [imports] OpenCV/bin/* - ./bin ''' tmp_dir = temp_folder() file_path = os.path.join(tmp_dir, "file.txt") save(file_path, file_content) loader = ConanFileLoader(None, Settings(), OptionsValues.loads(""), Scopes()) with self.assertRaisesRegexp(ConanException, "is too long. Valid names must contain"): loader.load_conan_txt(file_path, None)
class Profile(object): '''A profile contains a set of setting (with values), environment variables and scopes''' def __init__(self): # Sections self.settings = OrderedDict() self.env = OrderedDict() self.scopes = Scopes() @staticmethod def loads(text): obj = Profile() doc = ConfigParser(text, allowed_fields=["settings", "env", "scopes"]) for setting in doc.settings.splitlines(): setting = setting.strip() if setting and not setting.startswith("#"): if "=" not in setting: raise ConanException("Invalid setting line '%s'" % setting) name, value = setting.split("=") obj.settings[name.strip()] = value.strip() if doc.scopes: obj.scopes = Scopes.from_list(doc.scopes.splitlines()) for env in doc.env.splitlines(): env = env.strip() if env and not env.startswith("#"): if "=" not in env: raise ConanException("Invalid env line '%s'" % env) varname, value = env.split("=") obj.env[varname.strip()] = value.strip() obj._order() return obj def dumps(self): self._order() # gets in order the settings result = ["[settings]"] for name, value in self.settings.items(): result.append("%s=%s" % (name, value)) result.append("[scopes]") if self.scopes[_root].get("dev", None): # FIXME: Ugly _root import del self.scopes[_root]["dev"] # Do not include dev scopes_txt = self.scopes.dumps() result.append(scopes_txt) result.append("[env]") for name, value in self.env.items(): result.append("%s=%s" % (name, value)) return "\n".join(result).replace("\n\n", "\n") def update_settings(self, new_settings): '''Mix the specified settings with the current profile. Specified settings are prioritized to profile''' # apply the current profile if new_settings: self.settings.update(new_settings) self._order() def update_scopes(self, new_scopes): '''Mix the specified settings with the current profile. Specified settings are prioritized to profile''' # apply the current profile if new_scopes: self.scopes.update(new_scopes) self._order() def _order(self): tmp_settings = copy.copy(self.settings) self.settings = OrderedDict() # Insert in a good order for func in [lambda x: "." not in x, # First the principal settings lambda x: "." in x]: for name, value in tmp_settings.items(): if func(name): self.settings[name] = value tmp_env = copy.copy(self.env) self.env = OrderedDict() for ordered_key in sorted(tmp_env): self.env[ordered_key] = tmp_env[ordered_key]
def complete_test(self): """ basic installation of a new conans """ client = TestClient() client.init_dynamic_vars() files = hello_source_files() conan_ref = ConanFileReference.loads("Hello/1.2.1/frodo/stable") reg_folder = client.paths.export(conan_ref) client.save(files, path=reg_folder) client.save({CONANFILE: myconan1, CONANINFO: "//empty", "include/no_copy/lib0.h": "NO copy", "include/math/lib1.h": "copy", "include/math/lib2.h": "copy", "include/physics/lib.hpp": "copy", "my_lib/debug/libd.a": "copy", "my_data/readme.txt": "copy", "my_data/readme.md": "NO copy", "contrib/math/math.h": "copy", "contrib/physics/gravity.h": "copy", "contrib/contrib.h": "copy", "include/opencv/opencv.hpp": "copy", "include/opencv2/opencv2.hpp": "copy", "modules/simu/src/simu.cpp": "NO copy", "modules/simu/include/opencv2/simu/simu.hpp": "copy", "modules/3D/doc/readme.md": "NO copy", "modules/3D/include/opencv2/3D/3D.hpp": "copy", "modules/dev/src/dev.cpp": "NO copy", "modules/dev/include/opencv2/dev/dev.hpp": "copy", "modules/opencv_mod.hpp": "copy"}, path=reg_folder) conanfile_path = os.path.join(reg_folder, CONANFILE) package_ref = PackageReference(conan_ref, "myfakeid") build_folder = client.paths.build(package_ref) package_folder = client.paths.package(package_ref) shutil.copytree(reg_folder, build_folder) loader = ConanFileLoader(None, Settings(), None, OptionsValues.loads(""), Scopes(), None) conanfile = loader.load_conan(conanfile_path, None) output = ScopedOutput("", TestBufferConanOutput()) create_package(conanfile, build_folder, package_folder, output) # test build folder self.assertTrue(os.path.exists(build_folder)) self.assertTrue(os.path.exists(os.path.join(package_folder, CONANINFO))) # test pack folder self.assertTrue(os.path.exists(package_folder)) def exist(rel_path): return os.path.exists(os.path.join(package_folder, rel_path)) # Expected files self.assertTrue(exist("include/lib1.h")) self.assertTrue(exist("include/lib2.h")) self.assertTrue(exist("include/physics/lib.hpp")) self.assertTrue(exist("include/contrib/math/math.h")) self.assertTrue(exist("include/contrib/physics/gravity.h")) self.assertTrue(exist("include/contrib/contrib.h")) self.assertTrue(exist("include/opencv/opencv.hpp")) self.assertTrue(exist("include/opencv2/opencv2.hpp")) self.assertTrue(exist("include/opencv2/simu/simu.hpp")) self.assertTrue(exist("include/opencv2/3D/3D.hpp")) self.assertTrue(exist("include/opencv2/dev/dev.hpp")) self.assertTrue(exist("lib/my_lib/libd.a")) self.assertTrue(exist("res/shares/readme.txt")) # Not expected files self.assertFalse(exist("include/opencv2/opencv_mod.hpp")) self.assertFalse(exist("include/opencv2/simu.hpp")) self.assertFalse(exist("include/opencv2/3D.hpp")) self.assertFalse(exist("include/opencv2/dev.hpp")) self.assertFalse(exist("include/modules/simu/src/simu.cpp")) self.assertFalse(exist("include/modules/3D/doc/readme.md")) self.assertFalse(exist("include/modules/dev/src/dev.cpp")) self.assertFalse(exist("include/opencv2/opencv_mod.hpp")) self.assertFalse(exist("include/include/no_copy/lib0.h")) self.assertFalse(exist("res/my_data/readme.md"))
def __init__(self): # Sections self.settings = OrderedDict() self.env = OrderedDict() self.scopes = Scopes()
def test_package(self, *args): """ build and run your package test. Must have conanfile.py with "test" method and "test_package" subfolder with package consumer test project """ parser = argparse.ArgumentParser(description=self.test_package.__doc__, prog="conan test", formatter_class=RawTextHelpFormatter) parser.add_argument("path", nargs='?', default="", help='path to conanfile file, ' 'e.g. /my_project/') parser.add_argument("-f", "--folder", help='alternative test folder name') parser.add_argument("--scope", "-sc", nargs=1, action=Extender, help='Define scopes for packages') self._parse_args(parser) args = parser.parse_args(*args) root_folder = os.path.normpath(os.path.join(os.getcwd(), args.path)) if args.folder: test_folder_name = args.folder test_folder = os.path.join(root_folder, test_folder_name) test_conanfile = os.path.join(test_folder, "conanfile.py") if not os.path.exists(test_conanfile): raise ConanException("test folder '%s' not available, " "or it doesn't have a conanfile.py" % args.folder) else: for name in ["test_package", "test"]: test_folder_name = name test_folder = os.path.join(root_folder, test_folder_name) test_conanfile = os.path.join(test_folder, "conanfile.py") if os.path.exists(test_conanfile): break else: raise ConanException("test folder 'test_package' not available, " "or it doesn't have a conanfile.py") lib_to_test = self._detect_tested_library_name() # Get False or a list of patterns to check if args.build is None and lib_to_test: # Not specified, force build the tested library args.build = [lib_to_test] else: args.build = self._get_build_sources_parameter(args.build) options = args.options or [] settings = args.settings or [] sha = hashlib.sha1("".join(options + settings).encode()).hexdigest() build_folder = os.path.join(test_folder, "build", sha) rmdir(build_folder) # shutil.copytree(test_folder, build_folder) options = self._get_tuples_list_from_extender_arg(args.options) settings = self._get_tuples_list_from_extender_arg(args.settings) scopes = Scopes.from_list(args.scope) if args.scope else None self._manager.install(reference=test_folder, current_path=build_folder, remote=args.remote, options=options, settings=settings, build_mode=args.build, scopes=scopes) self._test_check(test_folder, test_folder_name) self._manager.build(test_folder, build_folder, test=True)
class Profile(object): """A profile contains a set of setting (with values), environment variables and scopes""" def __init__(self): # Sections self._settings = OrderedDict() self._package_settings = defaultdict(OrderedDict) self._env = OrderedDict() self._package_env = defaultdict(OrderedDict) self.scopes = Scopes() @property def package_settings(self): return {package_name: list(settings.items()) for package_name, settings in self._package_settings.items()} @property def settings(self): return list(self._settings.items()) @property def package_env(self): return {package_name: list(env.items()) for package_name, env in self._package_env.items()} @property def env(self): return list(self._env.items()) @staticmethod def loads(text): def get_package_name_value(item): """Parse items like package:name=value or name=value""" package_name = None if ":" in item: tmp = item.split(":", 1) package_name, item = tmp name, value = item.split("=", 1) name = name.strip() value = _clean_value(value) return package_name, name, value try: obj = Profile() doc = ConfigParser(text, allowed_fields=["settings", "env", "scopes"]) for setting in doc.settings.splitlines(): setting = setting.strip() if setting and not setting.startswith("#"): if "=" not in setting: raise ConanException("Invalid setting line '%s'" % setting) package_name, name, value = get_package_name_value(setting) if package_name: obj._package_settings[package_name][name] = value else: obj._settings[name] = value if doc.scopes: obj.scopes = Scopes.from_list(doc.scopes.splitlines()) for env in doc.env.splitlines(): env = env.strip() if env and not env.startswith("#"): if "=" not in env: raise ConanException("Invalid env line '%s'" % env) package_name, name, value = get_package_name_value(env) if package_name: obj._package_env[package_name][name] = value else: obj._env[name] = value obj._order() return obj except ConanException: raise except Exception as exc: raise ConanException("Error parsing the profile text file: %s" % str(exc)) def dumps(self): self._order() # gets in order the settings def dump_simple_items(items, result): for name, value in items: result.append("%s=%s" % (name, value)) def dump_package_items(items, result): for package, values in items: for name, value in values.items(): result.append("%s:%s=%s" % (package, name, value)) result = ["[settings]"] dump_simple_items(self._settings.items(), result) dump_package_items(self._package_settings.items(), result) result.append("[scopes]") if self.scopes[_root].get("dev", None): # FIXME: Ugly _root import del self.scopes[_root]["dev"] # Do not include dev scopes_txt = self.scopes.dumps() result.append(scopes_txt) result.append("[env]") dump_simple_items(self._env.items(), result) dump_package_items(self._package_env.items(), result) return "\n".join(result).replace("\n\n", "\n") def update_settings(self, new_settings): """Mix the specified settings with the current profile. Specified settings are prioritized to profile""" # apply the current profile if new_settings: self._settings.update(new_settings) self._order() def update_package_settings(self, package_settings): """Mix the specified package settings with the specified profile. Specified package settings are prioritized to profile""" for package_name, settings in self._package_settings.items(): if package_name in package_settings: settings.update(dict(package_settings[package_name])) # The rest of new packages settings for package_name, settings in package_settings.items(): if package_name not in self._package_settings: self._package_settings[package_name].update(dict(settings)) self._order() def _mix_env_with_new(self, env_dict, new_env): res_env = OrderedDict() for name, value in new_env: if name in env_dict: del env_dict[name] res_env[name] = value # Insert first in the result for name, value in env_dict.items(): res_env[name] = value # Insert the rest of env vars at the end return res_env def update_env(self, new_env): """Priorize new_env to override the current envs""" if not new_env: return self._env = self._mix_env_with_new(self._env, new_env) def update_packages_env(self, new_packages_env): """Priorize new_packages_env to override the current package_env""" if not new_packages_env: return res_env = defaultdict(OrderedDict) # Mix the common packages env for package, env_vars in self._package_env.items(): new_env = new_packages_env.get(package, []) res_env[package] = self._mix_env_with_new(env_vars, new_env) # The rest of new packages env variables for package, env_vars in new_packages_env.items(): if package not in res_env: for name, value in env_vars: res_env[package][name] = value # Insert the rest of env vars at the end self._package_env = res_env def update_scopes(self, new_scopes): """Mix the specified settings with the current profile. Specified settings are prioritized to profile""" # apply the current profile if new_scopes: self.scopes.update(new_scopes) self._order() def _order(self): def order_single_settings(settings): ret = OrderedDict() # Insert in a good order for func in [lambda x: "." not in x, lambda x: "." in x]: # First the principal settings for name, value in settings.items(): if func(name): ret[name] = value return ret # Order global settings self._settings = order_single_settings(self._settings) # Order package settings for package_name, settings in self._package_settings.items(): self._package_settings[package_name] = order_single_settings(settings) tmp_env = copy.copy(self._env) self._env = OrderedDict() for ordered_key in sorted(tmp_env): self._env[ordered_key] = tmp_env[ordered_key]
class Profile(object): """A profile contains a set of setting (with values), environment variables and scopes""" def __init__(self): # Sections self.settings = OrderedDict() self.package_settings = defaultdict(OrderedDict) self.env_values = EnvValues() self.scopes = Scopes() self.options = OptionsValues() @property def settings_values(self): return Values.from_list(list(self.settings.items())) @property def package_settings_values(self): result = {} for pkg, settings in self.package_settings.items(): result[pkg] = list(settings.items()) return result @staticmethod def read_file(profile_name, cwd, default_folder): """ Will look for "profile_name" in disk if profile_name is absolute path, in current folder if path is relative or in the default folder otherwise. return: a Profile object """ if not profile_name: return None if os.path.isabs(profile_name): profile_path = profile_name folder = os.path.dirname(profile_name) elif profile_name.startswith("."): # relative path name profile_path = os.path.abspath(os.path.join(cwd, profile_name)) folder = os.path.dirname(profile_path) else: folder = default_folder if not os.path.exists(folder): mkdir(folder) profile_path = os.path.join(folder, profile_name) try: text = load(profile_path) except IOError: if os.path.exists(folder): profiles = [name for name in os.listdir(folder) if not os.path.isdir(name)] else: profiles = [] current_profiles = ", ".join(profiles) or "[]" raise ConanException("Specified profile '%s' doesn't exist.\nExisting profiles: " "%s" % (profile_name, current_profiles)) try: text = text.replace("$PROFILE_DIR", os.path.abspath(folder)) # Allows PYTHONPATH=$PROFILE_DIR/pythontools return Profile.loads(text) except ConanException as exc: raise ConanException("Error reading '%s' profile: %s" % (profile_name, exc)) @staticmethod def loads(text): """ Parse and return a Profile object from a text config like representation """ def get_package_name_value(item): '''Parse items like package:name=value or name=value''' package_name = None if ":" in item: tmp = item.split(":", 1) package_name, item = tmp name, value = item.split("=", 1) name = name.strip() value = unquote(value) return package_name, name, value try: obj = Profile() doc = ConfigParser(text, allowed_fields=["settings", "env", "scopes", "options"]) for setting in doc.settings.splitlines(): setting = setting.strip() if setting and not setting.startswith("#"): if "=" not in setting: raise ConanException("Invalid setting line '%s'" % setting) package_name, name, value = get_package_name_value(setting) if package_name: obj.package_settings[package_name][name] = value else: obj.settings[name] = value if doc.scopes: obj.scopes = Scopes.from_list(doc.scopes.splitlines()) if doc.options: obj.options = OptionsValues.loads(doc.options) obj.env_values = EnvValues.loads(doc.env) return obj except ConanException: raise except Exception as exc: raise ConanException("Error parsing the profile text file: %s" % str(exc)) def dumps(self): result = ["[settings]"] for name, value in self.settings.items(): result.append("%s=%s" % (name, value)) for package, values in self.package_settings.items(): for name, value in values.items(): result.append("%s:%s=%s" % (package, name, value)) result.append("[options]") result.append(self.options.dumps()) result.append("[scopes]") if self.scopes[_root].get("dev", None): # FIXME: Ugly _root import del self.scopes[_root]["dev"] # Do not include dev scopes_txt = self.scopes.dumps() result.append(scopes_txt) result.append("[env]") result.append(self.env_values.dumps()) return "\n".join(result).replace("\n\n", "\n") def update(self, other): self.update_settings(other.settings) self.update_package_settings(other.package_settings) self.update_scopes(other.scopes) # this is the opposite other.env_values.update(self.env_values) self.env_values = other.env_values self.options.update(other.options) def update_settings(self, new_settings): '''Mix the specified settings with the current profile. Specified settings are prioritized to profile''' # apply the current profile if new_settings: self.settings.update(new_settings) def update_package_settings(self, package_settings): '''Mix the specified package settings with the specified profile. Specified package settings are prioritized to profile''' for package_name, settings in package_settings.items(): self.package_settings[package_name].update(settings) def update_scopes(self, new_scopes): '''Mix the specified settings with the current profile. Specified settings are prioritized to profile''' # apply the current profile if new_scopes: self.scopes.update(new_scopes)
def test_package(self, *args): """ build and run your package test. Must have conanfile.py with "test" method and "test_package" subfolder with package consumer test project """ parser = argparse.ArgumentParser(description=self.test_package.__doc__, prog="conan test_package", formatter_class=RawTextHelpFormatter) parser.add_argument("path", nargs='?', default="", help='path to conanfile file, ' 'e.g. /my_project/') parser.add_argument("-ne", "--not-export", default=False, action='store_true', help='Do not export the conanfile before test execution') parser.add_argument("-f", "--folder", help='alternative test folder name') parser.add_argument("--scope", "-sc", nargs=1, action=Extender, help='Define scopes for packages') parser.add_argument('--keep-source', '-k', default=False, action='store_true', help='Optional. Do not remove the source folder in local store. ' 'Use for testing purposes only') parser.add_argument("--update", "-u", action='store_true', default=False, help="update with new upstream packages") parser.add_argument("--profile", "-pr", default=None, help='Define a profile') self._parse_args(parser) args = parser.parse_args(*args) root_folder = os.path.normpath(os.path.join(os.getcwd(), args.path)) if args.folder: test_folder_name = args.folder test_folder = os.path.join(root_folder, test_folder_name) test_conanfile = os.path.join(test_folder, "conanfile.py") if not os.path.exists(test_conanfile): raise ConanException("test folder '%s' not available, " "or it doesn't have a conanfile.py" % args.folder) else: for name in ["test_package", "test"]: test_folder_name = name test_folder = os.path.join(root_folder, test_folder_name) test_conanfile = os.path.join(test_folder, "conanfile.py") if os.path.exists(test_conanfile): break else: raise ConanException("test folder 'test_package' not available, " "or it doesn't have a conanfile.py") options = args.options or [] settings = args.settings or [] sha = hashlib.sha1("".join(options + settings).encode()).hexdigest() build_folder = os.path.join(test_folder, "build", sha) rmdir(build_folder) # shutil.copytree(test_folder, build_folder) options = self._get_tuples_list_from_extender_arg(args.options) settings = self._get_tuples_list_from_extender_arg(args.settings) scopes = Scopes.from_list(args.scope) if args.scope else None manager = self._manager loader = manager._loader(None, settings, options, scopes) conanfile = loader.load_conan(test_conanfile, self._user_io.out, consumer=True) try: # convert to list from ItemViews required for python3 reqs = list(conanfile.requires.items()) first_dep = reqs[0][1].conan_reference except Exception: raise ConanException("Unable to retrieve first requirement of test conanfile.py") # Forcing an export! if not args.not_export: self._user_io.out.info("Exporting package recipe") user_channel = "%s/%s" % (first_dep.user, first_dep.channel) self._manager.export(user_channel, root_folder, keep_source=args.keep_source) lib_to_test = first_dep.name + "*" # Get False or a list of patterns to check if args.build is None and lib_to_test: # Not specified, force build the tested library args.build = [lib_to_test] else: args.build = self._get_build_sources_parameter(args.build) self._manager.install(reference=test_folder, current_path=build_folder, remote=args.remote, options=options, settings=settings, build_mode=args.build, scopes=scopes, update=args.update, profile_name=args.profile) self._test_check(test_folder, test_folder_name) self._manager.build(test_folder, build_folder, test=True, profile_name=args.profile)
def install(self, *args): """ install in the local store the given requirements. Requirements can be defined in the command line or in a conanfile. EX: conan install opencv/2.4.10@lasote/testing """ parser = argparse.ArgumentParser(description=self.install.__doc__, prog="conan install", formatter_class=RawTextHelpFormatter) parser.add_argument("reference", nargs='?', default="", help='package recipe reference' 'e.g., MyPackage/1.2@user/channel or ./my_project/') parser.add_argument("--package", "-p", nargs=1, action=Extender, help='Force install specified package ID (ignore settings/options)') parser.add_argument("--all", action='store_true', default=False, help='Install all packages from the specified package recipe') parser.add_argument("--file", "-f", help="specify conanfile filename") parser.add_argument("--update", "-u", action='store_true', default=False, help="update with new upstream packages") parser.add_argument("--scope", "-sc", nargs=1, action=Extender, help='Define scopes for packages') parser.add_argument("--profile", "-pr", default=None, help='Define a profile') parser.add_argument("--generator", "-g", nargs=1, action=Extender, help='Generators to use') parser.add_argument("--werror", action='store_true', default=False, help='Error instead of warnings for graph inconsistencies') # Manifests arguments default_manifest_folder = '.conan_manifests' parser.add_argument("--manifests", "-m", const=default_manifest_folder, nargs="?", help='Install dependencies manifests in folder for later verify.' ' Default folder is .conan_manifests, but can be changed') parser.add_argument("--manifests-interactive", "-mi", const=default_manifest_folder, nargs="?", help='Install dependencies manifests in folder for later verify, ' 'asking user for confirmation. ' 'Default folder is .conan_manifests, but can be changed') parser.add_argument("--verify", "-v", const=default_manifest_folder, nargs="?", help='Verify dependencies manifests against stored ones') self._parse_args(parser) args = parser.parse_args(*args) self._user_io.out.werror_active = args.werror current_path = os.getcwd() try: reference = ConanFileReference.loads(args.reference) except: reference = os.path.normpath(os.path.join(current_path, args.reference)) if args.all or args.package: # Install packages without settings (fixed ids or all) if args.all: args.package = [] if not args.reference or not isinstance(reference, ConanFileReference): raise ConanException("Invalid package recipe reference. " "e.g., MyPackage/1.2@user/channel") self._manager.download(reference, args.package, remote=args.remote) else: # Classic install, package chosen with settings and options # Get False or a list of patterns to check args.build = self._get_build_sources_parameter(args.build) options = self._get_tuples_list_from_extender_arg(args.options) settings = self._get_tuples_list_from_extender_arg(args.settings) scopes = Scopes.from_list(args.scope) if args.scope else None if args.manifests and args.manifests_interactive: raise ConanException("Do not specify both manifests and " "manifests-interactive arguments") if args.verify and (args.manifests or args.manifests_interactive): raise ConanException("Do not specify both 'verify' and " "'manifests' or 'manifests-interactive' arguments") manifest_folder = args.verify or args.manifests or args.manifests_interactive if manifest_folder: if not os.path.isabs(manifest_folder): if isinstance(reference, ConanFileReference): manifest_folder = os.path.join(current_path, manifest_folder) else: manifest_folder = os.path.join(reference, manifest_folder) manifest_verify = args.verify is not None manifest_interactive = args.manifests_interactive is not None else: manifest_verify = manifest_interactive = False self._manager.install(reference=reference, current_path=current_path, remote=args.remote, options=options, settings=settings, build_mode=args.build, filename=args.file, update=args.update, manifest_folder=manifest_folder, manifest_verify=manifest_verify, manifest_interactive=manifest_interactive, scopes=scopes, generators=args.generator, profile_name=args.profile)