def change_option_txt_test(self): self._create("Hello0", "0.1") client = TestClient(base_folder=self.client.base_folder) files = {CONANFILE_TXT: """[requires] Hello0/0.1@lasote/stable [options] Hello0:language=1 """} client.save(files) client.run("install %s --build missing" % self.settings) info_path = os.path.join(client.current_folder, CONANINFO) conan_info = ConanInfo.load_file(info_path) self.assertEqual("", conan_info.options.dumps()) self.assertIn("Hello0:language=1", conan_info.full_options.dumps()) self.assertIn("Hello0/0.1@lasote/stable:8b964e421a5b7e48b7bc19b94782672be126be8b", conan_info.full_requires.dumps()) files = {CONANFILE_TXT: """[requires] Hello0/0.1@lasote/stable [options] Hello0:language=0 """} client.save(files) client.run("install %s --build missing" % self.settings) info_path = os.path.join(client.current_folder, CONANINFO) conan_info = ConanInfo.load_file(info_path) self.assertEqual("", conan_info.options.dumps()) self.assertIn("Hello0:language=0", conan_info.full_options.dumps()) self.assertIn("Hello0/0.1@lasote/stable:2e38bbc2c3ef1425197c8e2ffa8532894c347d26", conan_info.full_requires.dumps())
def reuse_test(self): self._create("Hello0", "0.1") self._create("Hello1", "0.1", ["Hello0/0.1@lasote/stable"]) self._create("Hello2", "0.1", ["Hello1/0.1@lasote/stable"], export=False) for lang, id0, id1 in [(0, "2e38bbc2c3ef1425197c8e2ffa8532894c347d26", "44671ecdd9c606eb7166f2197ab50be8d36a3c3b"), (1, "8b964e421a5b7e48b7bc19b94782672be126be8b", "3eeab577a3134fa3afdcd82881751789ec48e08f")]: self.client.run("install -o language=%d %s --build missing" % (lang, self.settings)) info_path = os.path.join(self.client.current_folder, CONANINFO) conan_info = ConanInfo.load_file(info_path) self.assertEqual("arch=x86\n" "compiler=Visual Studio\n" "compiler.runtime=MD\n" "compiler.version=12\n" "os=Windows", conan_info.settings.dumps()) self.assertEqual("language=%s\nstatic=True" % lang, conan_info.options.dumps()) conan_ref = ConanFileReference.loads("Hello0/0.1@lasote/stable") hello0 = self.client.paths.package(PackageReference(conan_ref, id0)) hello0_info = os.path.join(hello0, CONANINFO) hello0_conan_info = ConanInfo.load_file(hello0_info) self.assertEqual(lang, hello0_conan_info.options.language) package_ref1 = PackageReference(ConanFileReference.loads("Hello1/0.1@lasote/stable"), id1) hello1 = self.client.paths.package(package_ref1) hello1_info = os.path.join(hello1, CONANINFO) hello1_conan_info = ConanInfo.load_file(hello1_info) self.assertEqual(lang, hello1_conan_info.options.language)
def test_search(self): """ check the dict is returned by get_packages_info service """ # Creating and saving conans, packages, and conans.vars conan_ref2 = ConanFileReference("openssl", "3.0", "lasote", "stable") conan_ref3 = ConanFileReference("Assimp", "1.10", "fenix", "stable") conan_ref4 = ConanFileReference("assimpFake", "0.1", "phil", "stable") package_ref2 = PackageReference(conan_ref2, "12345587754") package_ref3 = PackageReference(conan_ref3, "77777777777") conan_vars = """ [options] use_Qt=%s """ conan_vars1 = conan_vars % "True" conan_vars2 = conan_vars % "False" conan_vars3 = conan_vars % "True" save_files(self.paths.package(self.package_reference), {CONANINFO: conan_vars1}) save_files(self.paths.package(package_ref2), {CONANINFO: conan_vars2}) save_files(self.paths.package(package_ref3), {CONANINFO: conan_vars3}) save_files(self.paths.export(conan_ref4), {"dummy.txt": "//"}) info = self.service.search() expected = {self.conan_reference: {"123123123": ConanInfo.loads("[options]\nuse_Qt=True")}, conan_ref2: {"12345587754": ConanInfo.loads("[options]\nuse_Qt=False")}, conan_ref3: {"77777777777": ConanInfo.loads("[options]\nuse_Qt=True")}, conan_ref4: {}} self.assertEqual(expected, info) info = self.service.search(pattern="Assimp*", ignorecase=False) self.assertEqual(info, {conan_ref3: {"77777777777": ConanInfo.loads("[options]\nuse_Qt=True")}})
def inverse_upper_option_test(self): self._create("Hello0", "0.1", no_config=True) self._create("Hello1", "0.1", ["Hello0/0.1@lasote/stable"], no_config=True) self._create("Hello2", "0.1", ["Hello1/0.1@lasote/stable"], export=False, no_config=True) self.client.run("install -o language=0 -o Hello1:language=1 -o Hello0:language=0 %s " "--build missing" % self.settings) info_path = os.path.join(self.client.current_folder, CONANINFO) conan_info = ConanInfo.load_file(info_path) self.assertEqual("language=0\nstatic=True", conan_info.options.dumps()) conan_ref = ConanFileReference.loads("Hello0/0.1@lasote/stable") hello0 = self.client.paths.package(PackageReference(conan_ref, "2e38bbc2c3ef1425197c8e2ffa8532894c347d26")) hello0_info = os.path.join(hello0, CONANINFO) hello0_conan_info = ConanInfo.load_file(hello0_info) self.assertEqual("language=0\nstatic=True", hello0_conan_info.options.dumps()) package_ref1 = PackageReference(ConanFileReference.loads("Hello1/0.1@lasote/stable"), "3eeab577a3134fa3afdcd82881751789ec48e08f") hello1 = self.client.paths.package(package_ref1) hello1_info = os.path.join(hello1, CONANINFO) hello1_conan_info = ConanInfo.load_file(hello1_info) self.assertEqual("language=1\nstatic=True", hello1_conan_info.options.dumps())
def upper_option_txt_test(self): self._create("Hello0", "0.1", no_config=True) self._create("Hello1", "0.1", ["Hello0/0.1@lasote/stable"], no_config=True) files = cpp_hello_conan_files("Hello2", "0.1", ["Hello1/0.1@lasote/stable"]) files.pop(CONANFILE) files[CONANFILE_TXT] = """[requires] Hello1/0.1@lasote/stable [options] Hello0:language=1 Hello1:language=0 """ self.client.save(files, clean_first=True) self.client.run("install %s --build missing" % self.settings) info_path = os.path.join(self.client.current_folder, CONANINFO) conan_info = ConanInfo.load_file(info_path) self.assertEqual("", conan_info.options.dumps()) conan_ref = ConanFileReference.loads("Hello0/0.1@lasote/stable") hello0 = self.client.paths.package(PackageReference(conan_ref, "8b964e421a5b7e48b7bc19b94782672be126be8b")) hello0_info = os.path.join(hello0, CONANINFO) hello0_conan_info = ConanInfo.load_file(hello0_info) self.assertEqual(1, hello0_conan_info.options.language) package_ref1 = PackageReference(ConanFileReference.loads("Hello1/0.1@lasote/stable"), "44671ecdd9c606eb7166f2197ab50be8d36a3c3b") hello1 = self.client.paths.package(package_ref1) hello1_info = os.path.join(hello1, CONANINFO) hello1_conan_info = ConanInfo.load_file(hello1_info) self.assertEqual(0, hello1_conan_info.options.language)
def invalid_settings_test4(self): content = """ from conans import ConanFile class SayConan(ConanFile): name = "Say" version = "0.1" settings = "os" """ self.client.save({CONANFILE: content}) self.client.run("install . -s os=ChromeOS --build missing", ignore_error=True) self.assertIn(bad_value_msg("settings.os", "ChromeOS", ['Android', 'Arduino', 'FreeBSD', 'Linux', 'Macos', 'SunOS', 'Windows', 'WindowsStore', 'iOS', 'tvOS', 'watchOS']), str(self.client.user_io.out)) # Now add new settings to config and try again config = load(self.client.paths.settings_path) config = config.replace("Windows:%s" % os.linesep, "Windows:%s ChromeOS:%s" % (os.linesep, os.linesep)) save(self.client.paths.settings_path, config) self.client.run("install . -s os=ChromeOS --build missing") self.assertIn('Generated conaninfo.txt', str(self.client.user_io.out)) # Settings is None content = """ from conans import ConanFile class SayConan(ConanFile): name = "Say" version = "0.1" settings = None """ self.client.save({CONANFILE: content}) self.client.run("install . --build missing") self.assertIn('Generated conaninfo.txt', str(self.client.user_io.out)) conan_info = ConanInfo.loads(load(os.path.join(self.client.current_folder, CONANINFO))) self.assertEquals(conan_info.settings.dumps(), "") # Settings is {} content = """ from conans import ConanFile class SayConan(ConanFile): name = "Say" version = "0.1" settings = {} """ self.client.save({CONANFILE: content}) self.client.run("install . --build missing") self.assertIn('Generated conaninfo.txt', str(self.client.user_io.out)) conan_info = ConanInfo.loads(load(os.path.join(self.client.current_folder, CONANINFO))) self.assertEquals(conan_info.settings.dumps(), "")
def search_test(self): # Upload a conan1 conan_name1 = "HelloOnly/0.10@private_user/testing" conan_reference1 = ConanFileReference.loads(conan_name1) self._upload_recipe(conan_reference1) # Upload a package conan_info = """[settings] arch=x86_64 compiler=gcc os=Linux [options] 386=False [requires] Hello Bye/2.9 Say/2.1@user/testing Chat/2.1@user/testing:SHA_ABC """ package_reference = PackageReference(conan_reference1, "1F23223EFDA") self._upload_package(package_reference, {CONANINFO: conan_info}) # Upload a conan2 conan_name2 = "helloonlyToo/2.1@private_user/stable" conan_reference2 = ConanFileReference.loads(conan_name2) self._upload_recipe(conan_reference2) # Get the info about this ConanFileReference info = self.api.search_packages(conan_reference1, None) self.assertEqual(ConanInfo.loads(conan_info).serialize_min(), info["1F23223EFDA"]) # Search packages results = self.api.search("HelloOnly*", ignorecase=False) self.assertEqual(results, [conan_reference1])
def get_package_info_test(self): # Upload a conans conan_reference = ConanFileReference.loads("conan3/1.0.0@private_user/testing") self._upload_recipe(conan_reference) # Upload an package package_reference = PackageReference(conan_reference, "1F23223EFDA") conan_info = """[settings] arch=x86_64 compiler=gcc os=Linux [options] 386=False [requires] Hello Bye/2.9 Say/2.1@user/testing Chat/2.1@user/testing:SHA_ABC """ self._upload_package(package_reference, {CONANINFO: conan_info}) # Get the package info info = self.api.get_package_info(package_reference) self.assertIsInstance(info, ConanInfo) self.assertEquals(info, ConanInfo.loads(conan_info))
def basic_test2(self): conan_ref1 = ConanFileReference.loads("opencv/2.4.10@lasote/testing") root_folder = str(conan_ref1).replace("@", "/") artifacts = ["a", "b", "c"] reg1 = "%s/%s" % (root_folder, EXPORT_FOLDER) os.makedirs(reg1) for artif_id in artifacts: build1 = "%s/%s/%s" % (root_folder, BUILD_FOLDER, artif_id) artif1 = "%s/%s/%s" % (root_folder, PACKAGES_FOLDER, artif_id) os.makedirs(build1) info = ConanInfo().loads("[settings]\n[options]") save(os.path.join(artif1, CONANINFO), info.dumps()) packages = self.search_manager.search_packages(conan_ref1, "") all_artif = [_artif for _artif in sorted(packages)] self.assertEqual(all_artif, artifacts)
def complete_build_flow_test(self): """In local user folder""" client = TestClient() command = os.sep.join([".", "bin", "say_hello"]) for install, lang, static in [("install", 0, True), ("install -o language=1", 1, True), ("install -o language=1 -o static=False", 1, False), ("install -o static=False", 0, False)]: dll_export = client.default_compiler_visual_studio and not static files = cpp_hello_conan_files("Hello0", "0.1", dll_export=dll_export) client.save(files) client.run(install) time.sleep(1) # necessary so the conaninfo.txt is flushed to disc client.run('build') client.runner(command, client.current_folder) msg = "Hello" if lang == 0 else "Hola" self.assertIn("%s Hello0" % msg, client.user_io.out) conan_info_path = os.path.join(client.current_folder, CONANINFO) conan_info = ConanInfo.loads(load(conan_info_path)) self.assertTrue(conan_info.full_options.language == lang) if static: self.assertTrue(conan_info.full_options.static) else: self.assertFalse(conan_info.full_options.static)
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 search_packages(self, reference, query): """ Return a dict like this: {package_ID: {name: "OpenCV", version: "2.14", settings: {os: Windows}}} param conan_ref: ConanFileReference object """ # GET PROPERTIES FROM QUERY properties = get_properties_from_query(query) logger.debug("SEARCH PACKAGE PROPERTIES: %s" % properties) result = {} packages_path = self._paths.packages(reference) subdirs = self._adapter.list_folder_subdirs(packages_path, level=1) for package_id in subdirs: try: package_reference = PackageReference(reference, package_id) info_path = self._adapter.join_paths(self._paths.package(package_reference, short_paths=None), CONANINFO) if not self._adapter.path_exists(info_path, self._paths.store): raise NotFoundException("") conan_info_content = self._adapter.load(info_path) conan_vars_info = ConanInfo.loads(conan_info_content) if not self._filtered_by_properties(conan_vars_info, properties): result[package_id] = conan_vars_info.serialize_min() except Exception as exc: logger.error("Package %s has not ConanInfo file" % str(package_reference)) if str(exc): logger.error(str(exc)) return result
def test_conaninfo_filtered(self): client = TestClient() # Try injecting some package level ENV in the install, but without priority self._export(client, "A", [], {}, {"VAR1": "900", "VAR2": "23", "VAR3": "-23"}) self._export(client, "B", ["A"], {}, {"VAR1": "800", "VAR2": "24"}) self._export(client, "B2", ["A"], {}, {"VAR1": "800_2", "VAR2": "24_2"}) self._export(client, "C", ["B", "B2"], {"VAR3": "bestvalue"}, {"VAR1": "700"}) def load_conaninfo(lib): # Read the LIB_A conaninfo packages_path = client.client_cache.packages(ConanFileReference.loads("LIB_%s/1.0@lasote/stable" % lib)) package_path = os.path.join(packages_path, os.listdir(packages_path)[0]) info = ConanInfo.loads(load(os.path.join(package_path, CONANINFO))) return info # Test "A" conaninfo, should filter the FAKE_LIB client.save({"conanfile.py": reuse}) client.run("install . --build missing -e LIB_A:VAR3=override " "-e GLOBAL=99 -e FAKE_LIB:VAR1=-90 -e LIB_B:VAR2=222 " "-e LIB_B2:NEWVAR=VALUE -e VAR3=[newappend]") info = load_conaninfo("A") self.assertEquals(info.env_values.env_dicts("LIB_A"), ({"VAR3": "override", "GLOBAL": "99"}, {})) self.assertEquals(info.env_values.env_dicts(""), ({'GLOBAL': '99'}, {'VAR3': ['newappend']})) info = load_conaninfo("B") self.assertEquals(info.env_values.env_dicts("LIB_A"), ({'GLOBAL': '99', 'VAR3': "override"}, {'VAR2': ['23'], 'VAR1': ['900']})) self.assertEquals(info.env_values.env_dicts("LIB_B"), ({'GLOBAL': '99', "VAR2": "222"}, {'VAR3': ['newappend', '-23'], 'VAR1': ["900"]})) info = load_conaninfo("B2") self.assertEquals(info.env_values.env_dicts("LIB_A"), ({'GLOBAL': '99', 'VAR3': 'override'}, {'VAR2': ['23'], 'VAR1': ['900']})) self.assertEquals(info.env_values.env_dicts("LIB_B2"), ({'GLOBAL': '99', 'NEWVAR': "VALUE"}, {'VAR2': ['23'], 'VAR1': ['900'], 'VAR3': ['newappend', '-23']})) info = load_conaninfo("C") self.assertEquals(info.env_values.env_dicts("LIB_B2"), ({'GLOBAL': '99', 'NEWVAR': "VALUE"}, {'VAR3': ['newappend', '-23'], 'VAR1': ['800', '800_2', '900'], 'VAR2': ['24', '24_2', '23']})) self.assertEquals(info.env_values.env_dicts("LIB_C"), ({'GLOBAL': '99'}, {'VAR2': ['24', '24_2', '23'], 'VAR1': ['800', '800_2', '900'], 'VAR3': ['newappend', "-23"]})) # Now check the info for the project info = ConanInfo.loads(load(os.path.join(client.current_folder, CONANINFO))) self.assertEquals(info.env_values.env_dicts("PROJECT"), ({'GLOBAL': '99'}, {'VAR2': ['24', '24_2', '23'], 'VAR1': ['700', '800', '800_2', '900'], 'VAR3': ['newappend', 'bestvalue']}))
def read_conaninfo_profile(current_path): conan_info_path = os.path.join(current_path, CONANINFO) if not os.path.exists(conan_info_path): return None existing_info = ConanInfo.load_file(conan_info_path) profile = Profile() profile.settings = OrderedDict(existing_info.full_settings.as_list()) profile.options = existing_info.full_options profile.env_values = existing_info.env_values return profile
def settings_as_a_str_test(self): content = """ from conans import ConanFile class SayConan(ConanFile): name = "Say" version = "0.1" settings = "os" """ self.client.save({CONANFILE: content}) self.client.run("install -s os=Windows --build missing") # Now read the conaninfo and verify that settings applied is only os and value is windows conan_info = ConanInfo.loads(load(os.path.join(self.client.current_folder, CONANINFO))) self.assertEquals(conan_info.settings.os, "Windows") self.client.run("install -s os=Linux --build missing") # Now read the conaninfo and verify that settings applied is only os and value is windows conan_info = ConanInfo.loads(load(os.path.join(self.client.current_folder, CONANINFO))) self.assertEquals(conan_info.settings.os, "Linux")
def deserialize(data): tmp = json.loads(decode_text(data)) ret = SearchInfo() for conan_ref, packages in tmp.items(): conan_ref = ConanFileReference.loads(conan_ref) ret[conan_ref] = {} for package_id, info in packages.items(): ret[conan_ref][package_id] = ConanInfo.deserialize(info) return ret
def test_serialize(self): info = ConanInfo.loads(info_text) min_serial = info.serialize_min() expected = {'full_requires': ['bzip2/1.0.6@lasote/stable:c6c01ee5ea2cf4af63e7b83b722b0a2d90640641', 'zlib/1.2.8@lasote/stable:2dec3996ef8de7edb0304eaf4efdd96a0477d3a3'], 'options': {'shared': 'False', 'fPIC': 'True', 'header_only': 'False'}, 'settings': {'arch': 'x86_64', 'compiler.libcxx': 'libstdc++11', 'compiler.version': '5.2', 'os': 'Linux', 'build_type': 'Debug', 'compiler': 'gcc'}} self.assertEquals(min_serial, expected)
def search_test(self): # Upload a conan1 conan_name1 = "HelloOnly/0.10@private_user/testing" conan_reference1 = ConanFileReference.loads(conan_name1) self._upload_conan(conan_reference1) # Upload an package conan_info = """[settings] arch: x86_64 compiler: gcc os: Linux [options] 386: False [requires] Hello Bye/2.9 Say/2.1@user/testing Chat/2.1@user/testing:SHA_ABC """ package_reference = PackageReference(conan_reference1, "1F23223EFDA") self._upload_package(package_reference, {CONANINFO: conan_info}) # Upload a conan2 conan_name2 = "helloonlyToo/2.1@private_user/stable" conan_reference2 = ConanFileReference.loads(conan_name2) self._upload_conan(conan_reference2) # Get the info about this ConanFileReference info = self.api.search("helloonly*") expected_info1 = {"1F23223EFDA": ConanInfo.loads(conan_info)} expected_info2 = {} self.assertEqual(expected_info1, info[conan_reference1]) self.assertEqual(expected_info2, info[conan_reference2]) # Get the info about this ConanFileReference info = self.api.search("HelloOnly*", ignorecase=False) expected_info = {"1F23223EFDA": ConanInfo.loads(conan_info)} self.assertEqual({conan_reference1: expected_info}, info)
def upper_option_test(self): self._create("Hello0", "0.1", no_config=True) self._create("Hello1", "0.1", ["Hello0/0.1@lasote/stable"], no_config=True) self._create("Hello2", "0.1", ["Hello1/0.1@lasote/stable"], export=False, no_config=True) self.client.run("install -o language=1 -o Hello1:language=0 -o Hello0:language=1 %s " "--build missing" % self.settings) info_path = os.path.join(self.client.current_folder, CONANINFO) conan_info = ConanInfo.load_file(info_path) self.assertEqual("language=1\nstatic=True", conan_info.options.dumps()) conan_ref = ConanFileReference.loads("Hello0/0.1@lasote/stable") hello0 = self.client.paths.package(PackageReference(conan_ref, "8b964e421a5b7e48b7bc19b94782672be126be8b")) hello0_info = os.path.join(hello0, CONANINFO) hello0_conan_info = ConanInfo.load_file(hello0_info) self.assertEqual(1, hello0_conan_info.options.language) package_ref1 = PackageReference(ConanFileReference.loads("Hello1/0.1@lasote/stable"), "44671ecdd9c606eb7166f2197ab50be8d36a3c3b") hello1 = self.client.paths.package(package_ref1) hello1_info = os.path.join(hello1, CONANINFO) hello1_conan_info = ConanInfo.load_file(hello1_info) self.assertEqual(0, hello1_conan_info.options.language)
def settings_as_a_dict_conanfile_test(self): """Declare settings as a dict""" # Now with conanfile as a dict content = """ from conans import ConanFile class SayConan(ConanFile): name = "Say" version = "0.1" settings = {"os": ["Windows"], "arch": ["x86_64"]} """ self.client.save({CONANFILE: content}) self.client.run("install -s os=Windows --build missing") conan_info = ConanInfo.loads(load(os.path.join(self.client.current_folder, CONANINFO))) self.assertEquals(conan_info.settings.os, "Windows") self.assertEquals(conan_info.settings.fields, ["arch", "os"])
def propagate_info(self): """ takes the exports from upper level and updates the imports right now also the imports are propagated, but should be checked E.g. Conan A, depends on B. A=>B B exports an include directory "my_dir", with root "/...../0123efe" A imports are the exports of B, plus any other conans it depends on A.imports.include_dirs = B.export.include_paths. Note the difference, include_paths used to compute full paths as the user defines export relative to its folder """ ordered = self.by_levels() for level in ordered: for node in level: _, conanfile = node neighbors = self._neighbors[node] direct_reqs = [] # of PackageReference indirect_reqs = set() # of PackageReference, avoid duplicates for nref, nconan in neighbors: package_id = nconan.info.package_id() package_reference = PackageReference(nref, package_id) direct_reqs.append(package_reference) indirect_reqs.update(nconan.info.requires.refs()) conanfile.options.propagate_downstream(nref, nconan.info.full_options) # Might be never used, but update original requirement, just in case conanfile.requires[nref.name].conan_reference = nref # Make sure not duplicated indirect_reqs.difference_update(direct_reqs) # There might be options that are not upstream conanfile.options.clear_unused(indirect_reqs.union(direct_reqs)) non_devs = self.non_dev_nodes(node) conanfile.info = ConanInfo.create(conanfile.settings.values, conanfile.options.values, direct_reqs, indirect_reqs, non_devs) # Once we are done, call package_id() to narrow and change possible values if hasattr(conanfile, "conan_info"): # Deprecated in 0.19 conanfile.conan_info() else: with conanfile_exception_formatter(str(conanfile), "package_id"): conanfile.package_id() return ordered
def download_packages(self, reference, package_ids): assert(isinstance(package_ids, list)) remote, _ = self._get_remote(reference) conanfile_path = self._client_cache.conanfile(reference) if not os.path.exists(conanfile_path): raise Exception("Download recipe first") conanfile = load_conanfile_class(conanfile_path) # FIXME: This is a hack to provide a info object in case it fails and raise_package_not_found_error doesnt fail conanfile.info = ConanInfo.loads("") short_paths = conanfile.short_paths self._registry.set_ref(reference, remote) output = ScopedOutput(str(reference), self._out) for package_id in package_ids: package_ref = PackageReference(reference, package_id) package_folder = self._client_cache.package(package_ref, short_paths=short_paths) self._out.info("Downloading %s" % str(package_ref)) self._remote_manager.get_package(conanfile, package_ref, package_folder, remote, output, self._recorder)
def install_and_get_info(package_id_text): self.client.run("remove * -f") self._export("Hello", "1.2.0", package_id_text=package_id_text, channel="user/testing", settings='"os", "os_build", "arch", "arch_build"') self.client.run('install Hello/1.2.0@user/testing ' ' -s os="Windows" ' ' -s os_build="Linux"' ' -s arch="x86_64"' ' -s arch_build="x86"' ' --build missing') ref = ConanFileReference.loads("Hello/1.2.0@user/testing") pkg = os.listdir(self.client.client_cache.packages(ref)) pid = PackageReference(ref, pkg[0]) pkg_folder = self.client.client_cache.package(pid) return ConanInfo.loads(load(os.path.join(pkg_folder, CONANINFO)))
def get_package_info(self, package_reference): """Gets a ConanInfo file from a package""" url = "%s/conans/%s/packages/%s/download_urls" % (self._remote_api_url, "/".join(package_reference.conan), package_reference.package_id) urls = self._get_json(url) if not urls: raise NotFoundException("Package not found!") if CONANINFO not in urls: raise NotFoundException("Package %s doesn't have the %s file!" % (package_reference, CONANINFO)) # Get the info (in memory) contents = self.download_files({CONANINFO: urls[CONANINFO]}) # Unroll generator and decode shas (plain text) contents = {key: decode_text(value) for key, value in dict(contents).items()} return ConanInfo.loads(contents[CONANINFO])
def reuse_test(self): self._create("Hello0", "0.1") self._create("Hello1", "0.1", ["Hello0/0.1@lasote/stable"]) self._create("Hello2", "0.1", ["Hello1/0.1@lasote/stable"], export=False) current_folder = self.client.current_folder h00 = "2e38bbc2c3ef1425197c8e2ffa8532894c347d26" h10 = "44671ecdd9c606eb7166f2197ab50be8d36a3c3b" h01 = "8b964e421a5b7e48b7bc19b94782672be126be8b" h11 = "3eeab577a3134fa3afdcd82881751789ec48e08f" for lang, id0, id1, id2, id3 in [(0, h00, h10, h01, h11), (1, h01, h11, h00, h10)]: self.client.current_folder = os.path.join(current_folder, "lang%dbuild" % lang) mkdir(self.client.current_folder) self.client.run("install .. -o language=%d %s --build missing" % (lang, self.settings)) info_path = os.path.join(self.client.current_folder, CONANINFO) conan_info = ConanInfo.load_file(info_path) self.assertEqual("arch=x86\n" "compiler=Visual Studio\n" "compiler.runtime=MD\n" "compiler.version=12\n" "os=Windows", conan_info.settings.dumps()) conan_info_text = load(info_path) self.assertIn(id0, conan_info_text) self.assertIn(id1, conan_info_text) self.assertNotIn(id2, conan_info_text) self.assertNotIn(id3, conan_info_text) self.assertEqual("language=%s\nstatic=True" % lang, conan_info.options.dumps()) build_cmake = os.path.join(self.client.current_folder, BUILD_INFO_CMAKE) build_cmake_text = load(build_cmake) self.assertIn(id0, build_cmake_text) self.assertIn(id1, build_cmake_text) self.assertNotIn(id2, build_cmake_text) self.assertNotIn(id3, build_cmake_text) # Now test "build" command in subfolders for lang, id0, id1, id2, id3 in [(0, h00, h10, h01, h11), (1, h01, h11, h00, h10)]: self.client.current_folder = os.path.join(current_folder, "lang%dbuild" % lang) self.client.run("build ..") self.assertIn("compiler=Visual Studio", self.client.user_io.out) self.assertIn("language=%d" % lang, self.client.user_io.out) self.assertNotIn("language=%d" % (not lang), self.client.user_io.out)
def _loader(self, current_path=None, user_settings_values=None, package_settings=None, user_options_values=None, scopes=None, env=None, package_env=None): # The disk settings definition, already including the default disk values settings = self._client_cache.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, package_settings=package_settings, options=options, scopes=conaninfo_scopes, env=env, package_env=package_env)
def install_and_get_info(package_id_text): self.client.run("remove * -f") self._export("Hello", "1.2.0", package_id_text=package_id_text, channel="user/testing", settings='"os", "os_build", "arch", "arch_build"') self.client.run('install Hello/1.2.0@user/testing ' ' -s os="Windows" ' ' -s os_build="Linux"' ' -s arch="x86_64"' ' -s arch_build="x86"' ' --build missing') ref = ConanFileReference.loads("Hello/1.2.0@user/testing") pkg = os.listdir(self.client.cache.packages(ref)) pref = PackageReference(ref, pkg[0]) pkg_folder = self.client.cache.package(pref) return ConanInfo.loads(load(os.path.join(pkg_folder, CONANINFO)))
def propagate_info(self): """ takes the exports from upper level and updates the imports right now also the imports are propagated, but should be checked E.g. Conan A, depends on B. A=>B B exports an include directory "my_dir", with root "/...../0123efe" A imports are the exports of B, plus any other conans it depends on A.imports.include_dirs = B.export.include_paths. Note the difference, include_paths used to compute full paths as the user defines export relative to its folder """ ordered = self.by_levels() for level in ordered: for node in level: _, conanfile = node neighbors = self.neighbors(node) direct_reqs = [] # of PackageReference indirect_reqs = set() # of PackageReference, avoid duplicates for nref, nconan in neighbors: package_id = nconan.info.package_id() package_reference = PackageReference(nref, package_id) direct_reqs.append(package_reference) indirect_reqs.update(nconan.info.requires.refs()) conanfile.options.propagate_downstream( nref, nconan.info.full_options) # Might be never used, but update original requirement, just in case conanfile.requires[nref.name].conan_reference = nref # Make sure not duplicated indirect_reqs.difference_update(direct_reqs) # There might be options that are not upstream conanfile.options.clear_unused( indirect_reqs.union(direct_reqs)) non_devs = self.non_dev_nodes(node) conanfile.info = ConanInfo.create(conanfile.settings.values, conanfile.options.values, direct_reqs, indirect_reqs, non_devs) # Once we are done, call conan_info() to narrow and change possible values conanfile.conan_info() return ordered
def _get_upload_modules_with_deps(uploaded_files, downloaded_files): modules = [] deps = defaultdict(set) # Reference: [Reference, Reference] # Extract needed information for module_id, mod_doc in uploaded_files.items(): module_id = ConanFileReference.loads(module_id) if mod_doc["type"] == "recipe" \ else PackageReference.loads(module_id) # Store recipe and package dependencies if mod_doc["type"] == "package": conan_infos = [ file_doc for file_doc in mod_doc["files"] if file_doc["name"] == "conaninfo.txt" ] if conan_infos: conan_info = conan_infos[0]["path"] info = ConanInfo.loads(load(conan_info)) for package_reference in info.full_requires: deps[str(module_id.conan)].add(str( package_reference.conan)) deps[str(module_id)].add(str(package_reference)) # Add the modules for module_id, mod_doc in uploaded_files.items(): module = BuildInfoModule() module.id = str(module_id) # Add artifacts for file_doc in mod_doc["files"]: artifact = _get_build_info_artifact(file_doc) module.artifacts.append(artifact) # Add dependencies, for each module dep modules for mod_dep_id in deps[module_id]: if mod_dep_id in downloaded_files: down_module = downloaded_files[mod_dep_id] # Check if the remote from the uploaded package matches the remote from the downloaded dependency if down_module.get("remote", None) == mod_doc["remote"]: for file_doc in down_module["files"]: module.dependencies.append( _get_dependency(file_doc, mod_dep_id)) modules.append(module) return modules
def install_and_get_info(package_id_text): self.client.run("remove * -f") self._export("Hello", "1.2.0", package_id_text=package_id_text, channel="user/testing", settings=["os", "os_build", "arch", "arch_build"]) self.client.run('install Hello/1.2.0@user/testing ' ' -s os="Windows" ' ' -s os_build="Linux"' ' -s arch="x86_64"' ' -s arch_build="x86"' ' --build missing') hello_ref = ConanFileReference.loads("Hello/1.2.0@user/testing") layout = self.client.cache.package_layout(hello_ref) pkg_ids = layout.package_ids() hello_pref = PackageReference(hello_ref, pkg_ids[0]) return ConanInfo.loads( load(os.path.join(layout.package(hello_pref), CONANINFO)))
def _build(self, cmd, static, pure_c, use_cmake, lang): client = TestClient() dll_export = client.default_compiler_visual_studio and not static files = cpp_hello_conan_files("Hello0", "0.1", dll_export=dll_export, pure_c=pure_c, use_cmake=use_cmake) client.save(files) client.run(cmd) client.run("build") ld_path = "LD_LIBRARY_PATH=$(pwd)" if not static and not platform.system() == "Windows" else "" command = os.sep.join([".", "bin", "say_hello"]) client.runner("%s %s" % (ld_path, command), cwd=client.current_folder) msg = "Hello" if lang == 0 else "Hola" self.assertIn("%s Hello0" % msg, client.user_io.out) conan_info_path = os.path.join(client.current_folder, CONANINFO) conan_info = ConanInfo.loads(load(conan_info_path)) self.assertTrue(conan_info.full_options.language == lang) if static: self.assertTrue(conan_info.full_options.static) else: self.assertFalse(conan_info.full_options.static)
def _build(self, cmd, static, pure_c, use_cmake, lang): dll_export = self.client.default_compiler_visual_studio and not static files = cpp_hello_conan_files("Hello0", "0.1", dll_export=dll_export, pure_c=pure_c, use_cmake=use_cmake) self.client.save(files, clean_first=True) self.client.run(cmd) time.sleep(1) # necessary so the conaninfo.txt is flushed to disc self.client.run('build') ld_path = ("LD_LIBRARY_PATH=$(pwd)" if not static and not platform.system() == "Windows" else "") self.client.runner("%s %s" % (ld_path, self.command), cwd=self.client.current_folder) msg = "Hello" if lang == 0 else "Hola" self.assertIn("%s Hello0" % msg, self.client.user_io.out) conan_info_path = os.path.join(self.client.current_folder, CONANINFO) conan_info = ConanInfo.loads(load(conan_info_path)) self.assertTrue(conan_info.full_options.language == lang) if static: self.assertTrue(conan_info.full_options.static) else: self.assertFalse(conan_info.full_options.static)
def get_package_info(self, package_reference): """Gets a ConanInfo file from a package""" url = self.conans_router.package_download_urls(package_reference) urls = self._get_file_to_url_dict(url) if not urls: raise NotFoundException("Package not found!") if CONANINFO not in urls: raise NotFoundException("Package %s doesn't have the %s file!" % (package_reference, CONANINFO)) # Get the info (in memory) contents = self._download_files({CONANINFO: urls[CONANINFO]}, quiet=True) # Unroll generator and decode shas (plain text) contents = { key: decode_text(value) for key, value in dict(contents).items() } return ConanInfo.loads(contents[CONANINFO])
def _compute_package_id(node, default_package_id_mode, default_python_requires_id_mode): """ Compute the binary package ID of this node :param node: the node to compute the package-ID :param default_package_id_mode: configuration of the package-ID mode """ # TODO Conan 2.0. To separate the propagation of the graph (options) of the package-ID # A bit risky to be done now conanfile = node.conanfile neighbors = node.neighbors() direct_reqs = [] # of PackageReference indirect_reqs = set() # of PackageReference, avoid duplicates for neighbor in neighbors: ref, nconan = neighbor.ref, neighbor.conanfile direct_reqs.append(neighbor.pref) indirect_reqs.update(nconan.info.requires.refs()) # Make sure not duplicated indirect_reqs.difference_update(direct_reqs) python_requires = getattr(conanfile, "python_requires", None) if python_requires: if isinstance(python_requires, dict): python_requires = None # Legacy python-requires do not change package-ID else: python_requires = python_requires.all_refs() conanfile.info = ConanInfo.create( conanfile.settings.values, conanfile.options.values, direct_reqs, indirect_reqs, default_package_id_mode=default_package_id_mode, python_requires=python_requires, default_python_requires_id_mode=default_python_requires_id_mode) # Once we are done, call package_id() to narrow and change possible values with conanfile_exception_formatter(str(conanfile), "package_id"): conanfile.package_id() info = conanfile.info node.package_id = info.package_id()
def get_package_info(self, pref): """Gets a ConanInfo file from a package""" pref = pref.copy_with_revs(None, None) url = self.router.package_download_urls(pref) urls = self._get_file_to_url_dict(url) if not urls: raise PackageNotFoundException(pref) if CONANINFO not in urls: raise NotFoundException("Package %s doesn't have the %s file!" % (pref, CONANINFO)) md5s = self.get_package_snapshot( pref) if self._config.download_cache else None # Get the info (in memory) contents = self._download_files({CONANINFO: urls[CONANINFO]}, md5s) # Unroll generator and decode shas (plain text) contents = { key: decode_text(value) for key, value in dict(contents).items() } return ConanInfo.loads(contents[CONANINFO])
def get_package_info(self, package_reference): """Gets a ConanInfo file from a package""" url = "%s/conans/%s/packages/%s/download_urls" % ( self._remote_api_url, "/".join( package_reference.conan), package_reference.package_id) urls = self._get_json(url) if not urls: raise NotFoundException("Package not found!") if CONANINFO not in urls: raise NotFoundException("Package %s doesn't have the %s file!" % (package_reference, CONANINFO)) # Get the info (in memory) contents = self.download_files({CONANINFO: urls[CONANINFO]}) # Unroll generator and decode shas (plain text) contents = { key: decode_text(value) for key, value in dict(contents).items() } return ConanInfo.loads(contents[CONANINFO])
def _build(self, cmd, static, pure_c, use_cmake, lang): client = TestClient() dll_export = client.default_compiler_visual_studio and not static files = cpp_hello_conan_files("Hello0", "0.1", dll_export=dll_export, pure_c=pure_c, use_cmake=use_cmake) client.save(files) client.run(cmd) client.run('build .') ld_path = ("LD_LIBRARY_PATH=`pwd`" if not static and not platform.system() == "Windows" else "") command = os.sep.join([".", "bin", "say_hello"]) client.runner("%s %s" % (ld_path, command), cwd=client.current_folder) msg = "Hello" if lang == 0 else "Hola" self.assertIn("%s Hello0" % msg, client.user_io.out) conan_info_path = os.path.join(client.current_folder, CONANINFO) conan_info = ConanInfo.loads(load(conan_info_path)) self.assertTrue(conan_info.full_options.language == lang) if static: self.assertTrue(conan_info.full_options.static) else: self.assertFalse(conan_info.full_options.static)
def build(tester, cmd, static, pure_c, use_cmake, lang): client = TestClient() files = cpp_hello_conan_files("Hello0", "0.1", pure_c=pure_c, use_cmake=use_cmake) client.save(files) client.run(cmd) client.run('build .') ld_path = ("LD_LIBRARY_PATH=`pwd`" if not static and not platform.system() == "Windows" else "") if platform.system() == "Darwin": ld_path += ' DYLD_LIBRARY_PATH="%s"' % os.path.join(client.current_folder, 'lib') command = os.sep.join([".", "bin", "say_hello"]) client.run_command("%s %s" % (ld_path, command)) msg = "Hello" if lang == 0 else "Hola" tester.assertIn("%s Hello0" % msg, client.out) conan_info_path = os.path.join(client.current_folder, CONANINFO) conan_info = ConanInfo.loads(load(conan_info_path)) tester.assertTrue(conan_info.full_options.language == lang) if static: tester.assertTrue(conan_info.full_options.static) else: tester.assertFalse(conan_info.full_options.static)
def _get_local_infos_min(self, reference): result = {} packages_path = self._paths.packages(reference) subdirs = list_folder_subdirs(packages_path, level=1) for package_id in subdirs: # Read conaninfo try: package_reference = PackageReference(reference, package_id) info_path = os.path.join(self._paths.package(package_reference, short_paths=None), CONANINFO) if not os.path.exists(info_path): raise NotFoundException("") conan_info_content = load(info_path) conan_vars_info = ConanInfo.loads(conan_info_content).serialize_min() result[package_id] = conan_vars_info except Exception as exc: logger.error("Package %s has no ConanInfo file" % str(package_reference)) if str(exc): logger.error(str(exc)) return result
def _single_conan_search(self, conan_ref): """ Return a dict like this: {package_ID: {name: "OpenCV", version: "2.14", settings: {os: Windows}}} param conan_ref: ConanFileReference object """ result = {} packages_path = self.paths.packages(conan_ref) subdirs = self._file_adapter.list_folder_subdirs(packages_path, level=1) for package_id in subdirs: try: package_reference = PackageReference(conan_ref, package_id) info_path = os.path.join(self.paths.package(package_reference), CONANINFO) conan_info_content = self._file_adapter.get_file(info_path) conan_vars_info = ConanInfo.loads(conan_info_content) result[package_id] = conan_vars_info except Exception: logger.error("Package %s has not ConanInfo file" % str(package_reference)) return result
def _get_upload_modules_with_deps(uploaded_files, downloaded_files): modules = [] deps = defaultdict(set) # Reference: [Reference, Reference] # Extract needed information for module_id, mod_doc in uploaded_files.items(): module_id = ConanFileReference.loads(module_id) if mod_doc["type"] == "recipe" \ else PackageReference.loads(module_id) # Store recipe and package dependencies if mod_doc["type"] == "package": conan_infos = [file_doc for file_doc in mod_doc["files"] if file_doc["name"] == "conaninfo.txt"] if conan_infos: conan_info = conan_infos[0]["path"] info = ConanInfo.loads(load(conan_info)) for package_reference in info.full_requires: deps[str(module_id.conan)].add(str(package_reference.conan)) deps[str(module_id)].add(str(package_reference)) # Add the modules for module_id, mod_doc in uploaded_files.items(): module = BuildInfoModule() module.id = str(module_id) # Add artifacts for file_doc in mod_doc["files"]: artifact = _get_build_info_artifact(file_doc) module.artifacts.append(artifact) # Add dependencies, for each module dep modules for mod_dep_id in deps[module_id]: if mod_dep_id in downloaded_files: down_module = downloaded_files[mod_dep_id] # Check if the remote from the uploaded package matches the remote from the downloaded dependency if down_module.get("remote", None) == mod_doc["remote"]: for file_doc in down_module["files"]: module.dependencies.append(_get_dependency(file_doc, mod_dep_id)) modules.append(module) return modules
def _get_local_infos_min(server_store, ref, look_in_all_rrevs): result = {} rrevs = server_store.get_recipe_revisions(ref) if look_in_all_rrevs else [ None ] for rrev in rrevs: new_ref = ref.copy_with_rev(rrev.revision) if rrev else ref subdirs = list_folder_subdirs(server_store.packages(new_ref), level=1) for package_id in subdirs: if package_id in result: continue # Read conaninfo try: pref = PackageReference(new_ref, package_id) revision_entry = server_store.get_last_package_revision(pref) if not revision_entry: raise NotFoundException("") pref = PackageReference(new_ref, package_id, revision_entry.revision) info_path = os.path.join(server_store.package(pref), CONANINFO) if not os.path.exists(info_path): raise NotFoundException("") content = load(info_path) info = ConanInfo.loads(content) # From Conan 1.48 the conaninfo.txt is sent raw. result[package_id] = {"content": content} # FIXME: This could be removed in the conan_server, Artifactory should keep it # to guarantee compatibility with old conan clients. conan_vars_info = info.serialize_min() result[package_id].update(conan_vars_info) except Exception as exc: # FIXME: Too wide logger.error("Package %s has no ConanInfo file" % str(pref)) if str(exc): logger.error(str(exc)) return result
def _get_local_infos_min(paths, reference): result = {} packages_path = paths.packages(reference) subdirs = list_folder_subdirs(packages_path, level=1) for package_id in subdirs: # Read conaninfo try: package_reference = PackageReference(reference, package_id) info_path = os.path.join( paths.package(package_reference, short_paths=None), CONANINFO) if not os.path.exists(info_path): raise NotFoundException("") conan_info_content = load(info_path) conan_vars_info = ConanInfo.loads( conan_info_content).serialize_min() result[package_id] = conan_vars_info except Exception as exc: logger.error("Package %s has no ConanInfo file" % str(package_reference)) if str(exc): logger.error(str(exc)) return result
def test_serialize(self): info = ConanInfo.loads(info_text) min_serial = info.serialize_min() expected = { 'full_requires': [ 'bzip2/1.0.6@lasote/stable:c6c01ee5ea2cf4af63e7b83b722b0a2d90640641', 'zlib/1.2.8@lasote/stable:2dec3996ef8de7edb0304eaf4efdd96a0477d3a3' ], 'options': { 'shared': 'False', 'fPIC': 'True', 'header_only': 'False' }, 'settings': { 'arch': 'x86_64', 'compiler.libcxx': 'libstdc++11', 'compiler.version': '5.2', 'os': 'Linux', 'build_type': 'Debug', 'compiler': 'gcc' } } self.assertEquals(min_serial, expected)
def _get_local_infos_min(package_layout): result = OrderedDict() package_ids = package_layout.package_ids() for package_id in package_ids: # Read conaninfo pref = PackageReference(package_layout.ref, package_id) info_path = os.path.join(package_layout.package(pref), CONANINFO) if not os.path.exists(info_path): logger.error("There is no ConanInfo: %s" % str(info_path)) continue conan_info_content = load(info_path) info = ConanInfo.loads(conan_info_content) if package_layout.ref.revision: metadata = package_layout.load_metadata() recipe_revision = metadata.packages[package_id].recipe_revision if recipe_revision and recipe_revision != package_layout.ref.revision: continue conan_vars_info = info.serialize_min() result[package_id] = conan_vars_info return result
def compute_package_ids(self): ordered = self.by_levels() for level in ordered: for node in level: conanfile = node.conanfile neighbors = node.neighbors() direct_reqs = [] # of PackageReference indirect_reqs = set() # of PackageReference, avoid duplicates for neighbor in neighbors: nref, nconan = neighbor.conan_ref, neighbor.conanfile package_id = nconan.info.package_id() package_reference = PackageReference(nref, package_id) direct_reqs.append(package_reference) indirect_reqs.update(nconan.info.requires.refs()) conanfile.options.propagate_downstream( nref, nconan.info.full_options) # Might be never used, but update original requirement, just in case conanfile.requires[nref.name].conan_reference = nref # Make sure not duplicated indirect_reqs.difference_update(direct_reqs) # There might be options that are not upstream, backup them, might be # for build-requires conanfile.build_requires_options = conanfile.options.values conanfile.options.clear_unused( indirect_reqs.union(direct_reqs)) conanfile.info = ConanInfo.create(conanfile.settings.values, conanfile.options.values, direct_reqs, indirect_reqs) # Once we are done, call package_id() to narrow and change possible values with conanfile_exception_formatter(str(conanfile), "package_id"): conanfile.package_id() return ordered
def search_test(self): # Upload a conan1 conan_name1 = "HelloOnly/0.10@private_user/testing" conan_reference1 = ConanFileReference.loads(conan_name1) self._upload_recipe(conan_reference1) # Upload a package conan_info = """[settings] arch=x86_64 compiler=gcc os=Linux [options] 386=False [requires] Hello Bye/2.9 Say/2.1@user/testing Chat/2.1@user/testing:SHA_ABC """ package_reference = PackageReference(conan_reference1, "1F23223EFDA") self._upload_package(package_reference, {CONANINFO: conan_info}) # Upload a conan2 conan_name2 = "helloonlyToo/2.1@private_user/stable" conan_reference2 = ConanFileReference.loads(conan_name2) self._upload_recipe(conan_reference2) # Get the info about this ConanFileReference info = self.api.search_packages(conan_reference1, None) self.assertEqual( ConanInfo.loads(conan_info).serialize_min(), info["1F23223EFDA"]) # Search packages results = self.api.search("HelloOnly*", ignorecase=False) self.assertEqual(results, [conan_reference1])
def read_package_recipe_hash(self, package_folder): filename = os.path.join(package_folder, CONANINFO) info = ConanInfo.loads(load(filename)) return info.recipe_hash
def load_conaninfo(lib): # Read the LIB_A conaninfo packages_path = client.cache.package_layout(ConanFileReference.loads("LIB_%s/1.0@lasote/stable" % lib)).packages() package_path = os.path.join(packages_path, os.listdir(packages_path)[0]) info = ConanInfo.loads(load(os.path.join(package_path, CONANINFO))) return info
def _evaluate_node(self, node, build_mode, update, evaluated_references, remote_name): assert node.binary is None conan_ref, conanfile = node.conan_ref, node.conanfile package_id = conanfile.info.package_id() package_ref = PackageReference(conan_ref, package_id) # Check that this same reference hasn't already been checked previous_node = evaluated_references.get(package_ref) if previous_node: node.binary = previous_node.binary node.binary_remote = previous_node.binary_remote return evaluated_references[package_ref] = node output = ScopedOutput(str(conan_ref), self._out) if build_mode.forced(conanfile, conan_ref): output.warn('Forced build from source') node.binary = BINARY_BUILD return package_folder = self._client_cache.package( package_ref, short_paths=conanfile.short_paths) # Check if dirty, to remove it local_project = self._workspace[conan_ref] if self._workspace else None if local_project: node.binary = BINARY_WORKSPACE return with self._client_cache.package_lock(package_ref): if is_dirty(package_folder): output.warn("Package is corrupted, removing folder: %s" % package_folder) rmdir(package_folder) if remote_name: remote = self._registry.remote(remote_name) else: remote = self._registry.get_recipe_remote(conan_ref) remotes = self._registry.remotes if os.path.exists(package_folder): if update: if remote: if self._check_update(package_folder, package_ref, remote, output): node.binary = BINARY_UPDATE if build_mode.outdated: package_hash = self._get_package_info( package_ref, remote).recipe_hash elif remotes: pass else: output.warn("Can't update, no remote defined") if not node.binary: node.binary = BINARY_CACHE package_hash = ConanInfo.load_from_package( package_folder).recipe_hash else: # Binary does NOT exist locally remote_info = None if remote: remote_info = self._get_package_info(package_ref, remote) elif remotes: # Iterate all remotes to get this binary for r in remotes: remote_info = self._get_package_info(package_ref, r) if remote_info: remote = r break if remote_info: node.binary = BINARY_DOWNLOAD package_hash = remote_info.recipe_hash else: if build_mode.allowed(conanfile, conan_ref): node.binary = BINARY_BUILD else: node.binary = BINARY_MISSING if build_mode.outdated: if node.binary in (BINARY_CACHE, BINARY_DOWNLOAD, BINARY_UPDATE): local_recipe_hash = self._client_cache.load_manifest( package_ref.conan).summary_hash if local_recipe_hash != package_hash: output.info("Outdated package!") node.binary = BINARY_BUILD else: output.info("Package is up to date") node.binary_remote = remote
def _process_node(self, node, pref, build_mode, update, remotes): # Check that this same reference hasn't already been checked if self._evaluate_is_cached(node, pref): return conanfile = node.conanfile if node.recipe == RECIPE_EDITABLE: node.binary = BINARY_EDITABLE # TODO: PREV? return if pref.id == PACKAGE_ID_INVALID: # annotate pattern, so unused patterns in --build are not displayed as errors build_mode.forced(node.conanfile, node.ref) node.binary = BINARY_INVALID return if self._evaluate_build(node, build_mode): return package_layout = self._cache.package_layout( pref.ref, short_paths=conanfile.short_paths) metadata = self._evaluate_clean_pkg_folder_dirty( node, package_layout, pref) remote = remotes.selected if not remote: # If the remote_name is not given, follow the binary remote, or the recipe remote # If it is defined it won't iterate (might change in conan2.0) metadata = metadata or package_layout.load_metadata() remote_name = metadata.packages[ pref.id].remote or metadata.recipe.remote remote = remotes.get(remote_name) if package_layout.package_id_exists( pref.id): # Binary already in cache, check for updates self._evaluate_cache_pkg(node, package_layout, pref, metadata, remote, remotes, update) recipe_hash = None else: # Binary does NOT exist locally # Returned remote might be different than the passed one if iterating remotes recipe_hash, remote = self._evaluate_remote_pkg( node, pref, remote, remotes) if build_mode.outdated: if node.binary in (BINARY_CACHE, BINARY_DOWNLOAD, BINARY_UPDATE): if node.binary == BINARY_UPDATE: info, pref = self._get_package_info(node, pref, remote) recipe_hash = info.recipe_hash elif node.binary == BINARY_CACHE: package_folder = package_layout.package(pref) recipe_hash = ConanInfo.load_from_package( package_folder).recipe_hash local_recipe_hash = package_layout.recipe_manifest( ).summary_hash if local_recipe_hash != recipe_hash: conanfile.output.info("Outdated package!") node.binary = BINARY_BUILD node.prev = None else: conanfile.output.info("Package is up to date") node.binary_remote = remote
def test_conaninfo_filtered(self): client = TestClient() # Try injecting some package level ENV in the install, but without priority self._export(client, "A", [], {}, { "VAR1": "900", "VAR2": "23", "VAR3": "-23" }) self._export(client, "B", ["A"], {}, {"VAR1": "800", "VAR2": "24"}) self._export(client, "B2", ["A"], {}, { "VAR1": "800_2", "VAR2": "24_2" }) self._export(client, "C", ["B", "B2"], {"VAR3": "bestvalue"}, {"VAR1": "700"}) def load_conaninfo(lib): # Read the LIB_A conaninfo packages_path = client.cache.package_layout( ConanFileReference.loads("LIB_%s/1.0@lasote/stable" % lib)).packages() package_path = os.path.join(packages_path, os.listdir(packages_path)[0]) info = ConanInfo.loads(load(os.path.join(package_path, CONANINFO))) return info # Test "A" conaninfo, should filter the FAKE_LIB client.save({"conanfile.py": reuse}) client.run("install . --build missing -e LIB_A:VAR3=override " "-e GLOBAL=99 -e FAKE_LIB:VAR1=-90 -e LIB_B:VAR2=222 " "-e LIB_B2:NEWVAR=VALUE -e VAR3=[newappend]") info = load_conaninfo("A") self.assertEqual(info.env_values.env_dicts("LIB_A"), ({ "VAR3": "override", "GLOBAL": "99" }, {})) self.assertEqual(info.env_values.env_dicts(""), ({ 'GLOBAL': '99' }, { 'VAR3': ['newappend'] })) info = load_conaninfo("B") self.assertEqual(info.env_values.env_dicts("LIB_A"), ({ 'GLOBAL': '99', 'VAR3': "override" }, {})) self.assertEqual(info.env_values.env_dicts("LIB_B"), ({ 'GLOBAL': '99', "VAR2": "222" }, { 'VAR3': ['newappend'] })) info = load_conaninfo("B2") self.assertEqual(info.env_values.env_dicts("LIB_A"), ({ 'GLOBAL': '99', 'VAR3': 'override' }, {})) self.assertEqual(info.env_values.env_dicts("LIB_B2"), ({ 'GLOBAL': '99', 'NEWVAR': "VALUE" }, { 'VAR3': ['newappend'] })) info = load_conaninfo("C") self.assertEqual(info.env_values.env_dicts("LIB_B2"), ({ 'GLOBAL': '99', 'NEWVAR': "VALUE" }, { 'VAR3': ['newappend'] })) self.assertEqual(info.env_values.env_dicts("LIB_C"), ({ 'GLOBAL': '99' }, { 'VAR3': ['newappend'] })) # Now check the info for the project info = ConanInfo.loads(client.load(CONANINFO)) self.assertEqual(info.env_values.env_dicts("PROJECT"), ({ 'GLOBAL': '99' }, { 'VAR3': ['newappend'] })) _, _, buildinfo = TXTGenerator.loads(client.load(BUILD_INFO)) self.assertEqual(buildinfo["LIB_A"].VAR1, ["900"])
def get_package_info(self, pref): url = self.router.package_info(pref) cache = (pref.revision != DEFAULT_REVISION_V1) content = self._get_remote_file_contents(url, use_cache=cache) return ConanInfo.loads(decode_text(content))
def test_reuse(self): self._export_upload("Hello0", "0.1") self._export_upload("Hello1", "0.1", deps=[("Hello0/0.1@lasote/stable", "private")], static=False) client = TestClient(servers=self.servers, users={"default": [("lasote", "mypass")]}) files3 = cpp_hello_conan_files("Hello3", "0.1", ["Hello1/0.1@lasote/stable"]) client.save(files3) client.run('install . --build missing') client.run('build .') # assert Hello3 only depends on Hello2, and Hello1 build_info_cmake = client.load(BUILD_INFO_CMAKE) # Ensure it does not depend on Hello0 to build, as private in dlls self.assertNotIn("Hello0", repr(build_info_cmake)) command = os.sep.join([".", "bin", "say_hello"]) client.run_command(command) self.assertEqual(['Hello Hello3', 'Hello Hello1', 'Hello Hello0'], str(client.out).splitlines()[-3:]) conan_info = ConanInfo.loads(client.load(CONANINFO)) self.assertEqual("language=0\nstatic=True", conan_info.options.dumps()) # Try to upload and reuse the binaries client.run("upload Hello1/0.1@lasote/stable --all") self.assertEqual(str(client.out).count("Uploading package"), 1) client2 = TestClient(servers=self.servers, users={"default": [("lasote", "mypass")]}) client2.save(files3) client2.run("install .") self.assertNotIn("Package installed in Hello0/0.1", client2.out) self.assertNotIn("Building", client2.out) client2.run("build .") self.assertNotIn("libhello0.a", client2.out) self.assertNotIn("libhello1.a", client2.out) self.assertNotIn("libhello3.a", client2.out) client2.run_command(command) self.assertEqual(['Hello Hello3', 'Hello Hello1', 'Hello Hello0'], str(client2.out).splitlines()[-3:]) # Issue 79, fixing private deps from current project files3 = cpp_hello_conan_files( "Hello3", "0.2", [ "Hello1/0.1@lasote/stable", ("Hello0/0.1@lasote/stable", "private") ], language=1) client2.save(files3, clean_first=True) client2.run('install . -o language=1 --build missing') client2.run('build .') self.assertNotIn("libhello0.a", client2.out) self.assertNotIn("libhello1.a", client2.out) self.assertNotIn("libhello3.a", client2.out) client2.run_command(command) self.assertEqual( ['Hola Hello3', 'Hola Hello1', 'Hola Hello0', 'Hola Hello0'], str(client2.out).splitlines()[-4:])
def get_package_info(self, pref): url = self.router.package_info(pref) content = self._get_remote_file_contents(url) return ConanInfo.loads(decode_text(content))
def reuse_test(self): self._export_upload("Hello0", "0.1") self._export_upload("Hello00", "0.2", msg="#") self._export_upload("Hello1", "0.1", deps=[("Hello0/0.1@lasote/stable", "private")], static=False) self._export_upload("Hello2", "0.1", deps=[("Hello00/0.2@lasote/stable", "private")], static=False) client = TestClient(servers=self.servers, users={"default": [("lasote", "mypass")]}) files3 = cpp_hello_conan_files( "Hello3", "0.1", ["Hello1/0.1@lasote/stable", "Hello2/0.1@lasote/stable"]) # WE need to copy the DLLs and dylib client.save(files3) client.run('install --build missing') client.run('build') # assert Hello3 only depends on Hello2, and Hello1 info_path = os.path.join(client.current_folder, BUILD_INFO_CMAKE) build_info_cmake = load(info_path) # Ensure it does not depend on Hello0 to build, as private in dlls self.assertNotIn("Hello0", repr(build_info_cmake)) command = os.sep.join([".", "bin", "say_hello"]) client.runner(command, cwd=client.current_folder) self.assertEqual([ 'Hello Hello3', 'Hello Hello1', 'Hello Hello0', 'Hello Hello2', 'Hello #' ], str(client.user_io.out).splitlines()[-5:]) # assert Hello3 only depends on Hello2, and Hello1 info_path = os.path.join(client.current_folder, CONANINFO) conan_info = ConanInfo.loads(load(info_path)) self.assertEqual("language=0\nstatic=True", conan_info.options.dumps()) # Try to upload and reuse the binaries client.run("upload Hello1/0.1@lasote/stable --all") self.assertEqual(str(client.user_io.out).count("Uploading package"), 1) client.run("upload Hello2/0.1@lasote/stable --all") self.assertEqual(str(client.user_io.out).count("Uploading package"), 1) client2 = TestClient(servers=self.servers, users={"default": [("lasote", "mypass")]}) files2 = cpp_hello_conan_files( "Hello3", "0.1", ["Hello1/0.1@lasote/stable", "Hello2/0.1@lasote/stable"]) # WE need to copy the DLLs client2.save(files2) client2.run("install . --build missing") self.assertNotIn("Package installed in Hello0/0.1", client2.user_io.out) self.assertNotIn("Building", client2.user_io.out) client2.run("build .") self.assertNotIn("libhello0.a", client2.user_io.out) self.assertNotIn("libhello00.a", client2.user_io.out) self.assertNotIn("libhello1.a", client2.user_io.out) self.assertNotIn("libhello2.a", client2.user_io.out) self.assertNotIn("libhello3.a", client2.user_io.out) client2.runner(command, cwd=client2.current_folder) self.assertEqual([ 'Hello Hello3', 'Hello Hello1', 'Hello Hello0', 'Hello Hello2', 'Hello #' ], str(client2.user_io.out).splitlines()[-5:]) files3 = cpp_hello_conan_files( "Hello3", "0.2", ["Hello1/0.1@lasote/stable", "Hello2/0.1@lasote/stable"], language=1) client2.save(files3) client2.run('install -o language=1 --build missing') client2.run('build') self.assertNotIn("libhello0.a", client2.user_io.out) self.assertNotIn("libhello00.a", client2.user_io.out) self.assertNotIn("libhello1.a", client2.user_io.out) self.assertNotIn("libhello2.a", client2.user_io.out) self.assertNotIn("libhello3.a", client2.user_io.out) client2.runner(command, cwd=client2.current_folder) self.assertEqual([ 'Hola Hello3', 'Hola Hello1', 'Hola Hello0', 'Hola Hello2', 'Hola #' ], str(client2.user_io.out).splitlines()[-5:]) # Issue 79, fixing private deps from current project files3 = cpp_hello_conan_files( "Hello3", "0.2", [ "Hello1/0.1@lasote/stable", "Hello2/0.1@lasote/stable", ("Hello0/0.1@lasote/stable", "private"), ("Hello00/0.2@lasote/stable", "private") ], language=1) client2.save(files3, clean_first=True) client2.run('install -o language=1 --build missing') client2.run('build') self.assertNotIn("libhello0.a", client2.user_io.out) self.assertNotIn("libhello00.a", client2.user_io.out) self.assertNotIn("libhello1.a", client2.user_io.out) self.assertNotIn("libhello2.a", client2.user_io.out) self.assertNotIn("libhello3.a", client2.user_io.out) client2.runner(command, cwd=client2.current_folder) self.assertEqual([ 'Hola Hello3', 'Hola Hello1', 'Hola Hello0', 'Hola Hello2', 'Hola #', 'Hola Hello0', 'Hola #' ], str(client2.user_io.out).splitlines()[-7:])
def test_modes(self): info_text = '''[settings] arch=x86_64 build_type=Debug compiler=gcc compiler.libcxx=libstdc++11 compiler.version=5.2 os=Linux [full_requires] bzip2/1.2.3-alpha1+build123@lasote/testing:sha1 zlib/0.3@lasote/testing:sha2 poco/2.3.4+build123@lasote/stable:sha3 [options] fPIC=True header_only=False shared=False ''' info = ConanInfo.loads(info_text) info.header_only() self.assertEqual(info.settings.dumps(), "") self.assertEqual(info.options.dumps(), "") self.assertEqual(info.requires.dumps(), "") info = ConanInfo.loads(info_text) info.requires.unrelated_mode() self.assertEqual(info.requires.dumps(), "") info = ConanInfo.loads(info_text) info.requires.semver_mode() self.assertEqual(info.requires.dumps(), "bzip2/1.Y.Z\npoco/2.Y.Z\nzlib/0.3") info = ConanInfo.loads(info_text) info.requires.patch_mode() self.assertEqual(info.requires.dumps(), "bzip2/1.2.3\npoco/2.3.4\nzlib/0.3.0") info = ConanInfo.loads(info_text) info.requires.minor_mode() self.assertEqual(info.requires.dumps(), "bzip2/1.2.Z\npoco/2.3.Z\nzlib/0.3.Z") info = ConanInfo.loads(info_text) info.requires.major_mode() self.assertEqual(info.requires.dumps(), "bzip2/1.Y.Z\npoco/2.Y.Z\nzlib/0.Y.Z") info = ConanInfo.loads(info_text) info.requires.base_mode() self.assertEqual(info.requires.dumps(), "bzip2/1.2.3-alpha1\npoco/2.3.4\nzlib/0.3") info = ConanInfo.loads(info_text) info.requires.full_version_mode() self.assertEqual(info.requires.dumps(), "bzip2/1.2.3-alpha1+build123\n" "poco/2.3.4+build123\n" "zlib/0.3") info = ConanInfo.loads(info_text) info.requires.full_recipe_mode() self.assertEqual(info.requires.dumps(), "bzip2/1.2.3-alpha1+build123@lasote/testing\n" "poco/2.3.4+build123@lasote/stable\n" "zlib/0.3@lasote/testing") info = ConanInfo.loads(info_text) info.requires.full_package_mode() self.assertEqual(info.requires.dumps(), "bzip2/1.2.3-alpha1+build123@lasote/testing:sha1\n" "poco/2.3.4+build123@lasote/stable:sha3\n" "zlib/0.3@lasote/testing:sha2") info2 = info_text.replace("zlib/0.3@lasote/testing", "zlib/0.3@lasote/testing#RREV1") info = ConanInfo.loads(info2) info.requires.recipe_revision_mode() self.assertEqual(info.requires.dumps(), "bzip2/1.2.3-alpha1+build123@lasote/testing:sha1\n" "poco/2.3.4+build123@lasote/stable:sha3\n" "zlib/0.3@lasote/testing#RREV1:sha2") info2 = "[full_requires]\nzlib/0.3@lasote/testing#RREV1:sha2#PREV1" info = ConanInfo.loads(info2) info.requires.package_revision_mode() self.assertEqual(info.requires.dumps(), "zlib/0.3@lasote/testing#RREV1:sha2#PREV1")
def pythonpath_env_injection_test(self): # Save some custom python code in custom dir external_py = ''' def external_baz(): print("External baz") ''' external_dir = temp_folder() save(os.path.join(external_dir, "external.py"), external_py) conanfile = """ import os from conans import ConanFile, tools class ConanToolPackage(ConanFile): name = "conantool" version = "1.0" exports = "*" build_policy = "missing" def build(self): with tools.pythonpath(self): import external external.external_baz() def package(self): self.copy("*") def package_info(self): self.env_info.PYTHONPATH.append(self.package_folder) """ client = TestClient() client.save({ CONANFILE: conanfile, "__init__.py": "", "mytest.py": test }) client.run("export . lasote/stable") # We can't build the package without our PYTHONPATH self.assertRaises( Exception, client.run, "install conantool/1.0@lasote/stable --build missing") # But we can inject the PYTHONPATH client.run("install conantool/1.0@lasote/stable -e PYTHONPATH=['%s']" % external_dir) # Now we want to reuse the package and access both external stuff and mytest.py stuff reuse = """from conans import ConanFile, tools class ToolsTest(ConanFile): name = "Consumer" version = "0.1" requires = "conantool/1.0@lasote/stable" def build(self): with tools.pythonpath(self): import mytest mytest.foo(self.output) import external external.external_baz() """ client.save({CONANFILE: reuse}) client.run("install . --build -e PYTHONPATH=['%s']" % external_dir) client.run("build .") info = ConanInfo.loads( load(os.path.join(client.current_folder, "conaninfo.txt"))) pythonpath = info.env_values.env_dicts(None)[1]["PYTHONPATH"] self.assertEqual(os.path.normpath(pythonpath[0]), os.path.normpath(external_dir)) self.assertTrue(len(pythonpath), 2)
def _evaluate_node(self, node, build_mode, update, evaluated_references, remote_name): assert node.binary is None conan_ref, conanfile = node.conan_ref, node.conanfile revisions_enabled = get_env("CONAN_CLIENT_REVISIONS_ENABLED", False) package_id = conanfile.info.package_id() package_ref = PackageReference(conan_ref, package_id) # Check that this same reference hasn't already been checked previous_node = evaluated_references.get(package_ref) if previous_node: node.binary = previous_node.binary node.binary_remote = previous_node.binary_remote return evaluated_references[package_ref] = node output = ScopedOutput(str(conan_ref), self._out) if build_mode.forced(conanfile, conan_ref): output.warn('Forced build from source') node.binary = BINARY_BUILD return package_folder = self._client_cache.package( package_ref, short_paths=conanfile.short_paths) # Check if dirty, to remove it local_project = self._workspace[conan_ref] if self._workspace else None if local_project: node.binary = BINARY_WORKSPACE return with self._client_cache.package_lock(package_ref): if is_dirty(package_folder): output.warn("Package is corrupted, removing folder: %s" % package_folder) rmdir(package_folder) if remote_name: remote = self._registry.remotes.get(remote_name) else: # If the remote_name is not given, follow the binary remote, or # the recipe remote # If it is defined it won't iterate (might change in conan2.0) remote = self._registry.prefs.get( package_ref) or self._registry.refs.get(conan_ref) remotes = self._registry.remotes.list if os.path.exists(package_folder): if update: if remote: if self._check_update(package_folder, package_ref, remote, output, node): node.binary = BINARY_UPDATE if build_mode.outdated: package_hash = self._get_package_info( package_ref, remote).recipe_hash elif remotes: pass else: output.warn("Can't update, no remote defined") if not node.binary: node.binary = BINARY_CACHE package_hash = ConanInfo.load_from_package( package_folder).recipe_hash else: # Binary does NOT exist locally if not revisions_enabled and not node.revision_pinned: # Do not search for packages for the specific resolved recipe revision but all package_ref = package_ref.copy_clear_rev() remote_info = None if remote: remote_info = self._get_package_info(package_ref, remote) # If the "remote" came from the registry but the user didn't specified the -r, with # revisions iterate all remotes if not remote or (not remote_info and revisions_enabled and not remote_name): for r in remotes: remote_info = self._get_package_info(package_ref, r) if remote_info: remote = r break if remote_info: node.binary = BINARY_DOWNLOAD package_hash = remote_info.recipe_hash else: if build_mode.allowed(conanfile, conan_ref): node.binary = BINARY_BUILD else: node.binary = BINARY_MISSING if build_mode.outdated: if node.binary in (BINARY_CACHE, BINARY_DOWNLOAD, BINARY_UPDATE): local_recipe_hash = self._client_cache.load_manifest( package_ref.conan).summary_hash if local_recipe_hash != package_hash: output.info("Outdated package!") node.binary = BINARY_BUILD else: output.info("Package is up to date") node.binary_remote = remote