class ConanRequirementsTest(unittest.TestCase): def setUp(self): self.output = TestBufferConanOutput() self.loader = ConanFileLoader(None, Settings.loads(""), OptionsValues.loads("")) self.retriever = Retriever(self.loader, self.output) self.builder = DepsBuilder(self.retriever, self.output, self.loader) def test_diamond_no_conflict(self): self.retriever.conan("ZLib") self.retriever.conan("BZip2") self.retriever.conan("SDL2", ["ZLib"]) self.retriever.conan("LibPNG", ["ZLib"]) self.retriever.conan("freeType", ["BZip2", "LibPNG"]) self.retriever.conan("SDL2_ttf", ["freeType", "SDL2"]) root = self.retriever.root("MyProject", ["SDL2_ttf"]) deps_graph = self.builder.load(None, root) init_cpp_info(deps_graph, self.retriever) bylevel = deps_graph.propagate_buildinfo() E = bylevel[-1][0] self.assertEqual(E.conanfile.deps_cpp_info.libs, ['SDL2_ttf', 'SDL2', 'rt', 'pthread', 'dl', 'freeType', 'BZip2', 'LibPNG', 'm', 'ZLib'])
def _get_graph(self, reference, current_path, remote, options, settings, filename, update, check_updates, manifest_manager, scopes, package_settings, env, package_env): loader = self._loader(current_path, settings, package_settings, options, scopes, env, package_env) # Not check for updates for info command, it'll be checked when dep graph is built remote_proxy = ConanProxy(self._client_cache, self._user_io, self._remote_manager, remote, update=update, check_updates=check_updates, manifest_manager=manifest_manager) if isinstance(reference, ConanFileReference): project_reference = None conanfile = loader.load_virtual(reference, current_path) is_txt = True else: conanfile_path = reference project_reference = "PROJECT" output = ScopedOutput(project_reference, self._user_io.out) try: if filename and filename.endswith(".txt"): raise NotFoundException("") conan_file_path = os.path.join(conanfile_path, filename or CONANFILE) conanfile = loader.load_conan(conan_file_path, output, consumer=True) is_txt = False if conanfile.name is not None and conanfile.version is not None: project_reference = "%s/%s@" % (conanfile.name, conanfile.version) project_reference += "PROJECT" except NotFoundException: # Load requirements.txt conan_path = os.path.join(conanfile_path, filename or CONANFILE_TXT) conanfile = loader.load_conan_txt(conan_path, output) is_txt = True # build deps graph and install it local_search = None if update else self._search_manager resolver = RequireResolver(self._user_io.out, local_search, remote_proxy) builder = DepsBuilder(remote_proxy, self._user_io.out, loader, resolver) deps_graph = builder.load(None, conanfile) # These lines are so the conaninfo stores the correct complete info if is_txt: conanfile.info.settings = loader._settings.values conanfile.info.full_settings = loader._settings.values conanfile.info.scope = self._current_scopes conanfile.cpp_info = CppInfo(current_path) conanfile.env_info = EnvInfo(current_path) registry = RemoteRegistry(self._client_cache.registry, self._user_io.out) return (builder, deps_graph, project_reference, registry, conanfile, remote_proxy, loader)
def install(self, reference, current_path, remote=None, options=None, settings=None, build_mode=False, info=None): """ Fetch and build all dependencies for the given reference param reference: ConanFileReference or path to user space conanfile param current_path: where the output files will be saved param remote: install only from that remote param options: written in JSON, e.g. {"compiler": "Visual Studio 12", ...} """ if not isinstance(reference, ConanFileReference): conanfile_path = reference reference = None loader = self._loader(current_path, settings, options) installer = ConanInstaller(self._paths, self._user_io, loader, self.remote_manager, remote) if reference: conanfile = installer.retrieve_conanfile(reference, consumer=True) else: try: conan_file_path = os.path.join(conanfile_path, CONANFILE) conanfile = loader.load_conan(conan_file_path, consumer=True) is_txt = False except NotFoundException: # Load requirements.txt conan_path = os.path.join(conanfile_path, CONANFILE_TXT) conanfile = loader.load_conan_txt(conan_path) is_txt = True # build deps graph and install it builder = DepsBuilder(installer, self._user_io.out) deps_graph = builder.load(reference, conanfile) if info: Printer(self._user_io.out).print_info(deps_graph, info) return Printer(self._user_io.out).print_graph(deps_graph) installer.install(deps_graph, build_mode) if not reference: if is_txt: conanfile.info.settings = loader._settings.values conanfile.info.full_settings = loader._settings.values save(os.path.join(current_path, CONANINFO), conanfile.info.dumps()) self._user_io.out.info("Generated %s" % CONANINFO) write_generators(conanfile, current_path, self._user_io.out) local_installer = FileImporter(deps_graph, self._paths, current_path) conanfile.copy = local_installer conanfile.imports() local_installer.execute()
def install(self, reference, current_path, remote=None, options=None, settings=None, build_mode=False, info=None, filename=None, update=False): """ Fetch and build all dependencies for the given reference @param reference: ConanFileReference or path to user space conanfile @param current_path: where the output files will be saved @param remote: install only from that remote @param options: list of tuples: [(optionname, optionvalue), (optionname, optionvalue)...] @param settings: list of tuples: [(settingname, settingvalue), (settingname, value)...] """ reference_given = True if not isinstance(reference, ConanFileReference): conanfile_path = reference reference_given = False reference = None loader = self._loader(current_path, settings, options) # Not check for updates for info command, it'll be checked when dep graph is built check_updates = not info remote_proxy = ConanProxy(self._paths, self._user_io, self._remote_manager, remote, update, check_updates) if reference_given: project_reference = None conanfile_path = remote_proxy.get_conanfile(reference) output = ScopedOutput(str(reference), self._user_io.out) conanfile = loader.load_conan(conanfile_path, output, consumer=True) else: project_reference = "PROJECT" output = ScopedOutput(project_reference, self._user_io.out) try: if filename and filename.endswith(".txt"): raise NotFoundException("") conan_file_path = os.path.join(conanfile_path, filename or CONANFILE) conanfile = loader.load_conan(conan_file_path, output, consumer=True) is_txt = False if conanfile.name is not None and conanfile.version is not None: project_reference = "%s/%s@" % (conanfile.name, conanfile.version) project_reference += "PROJECT" except NotFoundException: # Load requirements.txt conan_path = os.path.join(conanfile_path, filename or CONANFILE_TXT) conanfile = loader.load_conan_txt(conan_path, output) is_txt = True # build deps graph and install it builder = DepsBuilder(remote_proxy, self._user_io.out, loader) deps_graph = builder.load(reference, conanfile) registry = RemoteRegistry(self._paths.registry, self._user_io.out) if info: graph_updates_info = builder.get_graph_updates_info(deps_graph) Printer(self._user_io.out).print_info(deps_graph, project_reference, info, registry, graph_updates_info, remote) return Printer(self._user_io.out).print_graph(deps_graph, registry) installer = ConanInstaller(self._paths, self._user_io, remote_proxy) installer.install(deps_graph, build_mode) if not reference_given: if is_txt: conanfile.info.settings = loader._settings.values # Just in case the current package is header only, we still store the full settings # for reference and compiler checks conanfile.info.full_settings = loader._settings.values content = normalize(conanfile.info.dumps()) save(os.path.join(current_path, CONANINFO), content) output.info("Generated %s" % CONANINFO) write_generators(conanfile, current_path, output) local_installer = FileImporter(deps_graph, self._paths, current_path) conanfile.copy = local_installer conanfile.imports() copied_files = local_installer.execute() import_output = ScopedOutput("%s imports()" % output.scope, output) report_copied_files(copied_files, import_output)
def install(self, reference, current_path, remote=None, options=None, settings=None, build_mode=False, info=None, filename=None, update=False): """ Fetch and build all dependencies for the given reference @param reference: ConanFileReference or path to user space conanfile @param current_path: where the output files will be saved @param remote: install only from that remote @param options: list of tuples: [(optionname, optionvalue), (optionname, optionvalue)...] @param settings: list of tuples: [(settingname, settingvalue), (settingname, settingvalue)...] """ reference_given = True if not isinstance(reference, ConanFileReference): conanfile_path = reference reference_given = False reference = None loader = self._loader(current_path, settings, options) # Not check for updates for info command, it'll be checked when dep graph is built check_updates = not info remote_proxy = ConanProxy(self._paths, self._user_io, self._remote_manager, remote, update, check_updates) if reference_given: project_reference = None conanfile_path = remote_proxy.get_conanfile(reference) output = ScopedOutput(str(reference), self._user_io.out) conanfile = loader.load_conan(conanfile_path, output, consumer=True) else: project_reference = "PROJECT" output = ScopedOutput(project_reference, self._user_io.out) try: if filename and filename.endswith(".txt"): raise NotFoundException() conan_file_path = os.path.join(conanfile_path, filename or CONANFILE) conanfile = loader.load_conan(conan_file_path, output, consumer=True) is_txt = False if conanfile.name is not None and conanfile.version is not None: project_reference = "%s/%s@" % (conanfile.name, conanfile.version) project_reference += "PROJECT" except NotFoundException: # Load requirements.txt conan_path = os.path.join(conanfile_path, filename or CONANFILE_TXT) conanfile = loader.load_conan_txt(conan_path, output) is_txt = True # build deps graph and install it builder = DepsBuilder(remote_proxy, self._user_io.out, loader) deps_graph = builder.load(reference, conanfile) registry = RemoteRegistry(self._paths.registry, self._user_io.out) if info: graph_updates_info = builder.get_graph_updates_info(deps_graph) Printer(self._user_io.out).print_info(deps_graph, project_reference, info, registry, graph_updates_info, remote) return Printer(self._user_io.out).print_graph(deps_graph, registry) installer = ConanInstaller(self._paths, self._user_io, remote_proxy) installer.install(deps_graph, build_mode) if not reference_given: if is_txt: conanfile.info.settings = loader._settings.values # Just in case the current package is header only, we still store the full settings # for reference and compiler checks conanfile.info.full_settings = loader._settings.values content = normalize(conanfile.info.dumps()) save(os.path.join(current_path, CONANINFO), content) output.info("Generated %s" % CONANINFO) write_generators(conanfile, current_path, output) local_installer = FileImporter(deps_graph, self._paths, current_path) conanfile.copy = local_installer conanfile.imports() local_installer.execute()
def install(self, reference, current_path, remote=None, options=None, settings=None, build_mode=False, info=None, filename=None, update=False, check_updates=False, integrity=False, scopes=None): """ Fetch and build all dependencies for the given reference @param reference: ConanFileReference or path to user space conanfile @param current_path: where the output files will be saved @param remote: install only from that remote @param options: list of tuples: [(optionname, optionvalue), (optionname, optionvalue)...] @param settings: list of tuples: [(settingname, settingvalue), (settingname, value)...] """ reference_given = True if not isinstance(reference, ConanFileReference): conanfile_path = reference reference_given = False reference = None loader = self._loader(current_path, settings, options, scopes) # Not check for updates for info command, it'll be checked when dep graph is built remote_proxy = ConanProxy(self._paths, self._user_io, self._remote_manager, remote, update=update, check_updates=check_updates, check_integrity=integrity) if reference_given: project_reference = None conanfile_path = remote_proxy.get_conanfile(reference) output = ScopedOutput(str(reference), self._user_io.out) conanfile = loader.load_conan(conanfile_path, output, consumer=True) else: project_reference = "PROJECT" output = ScopedOutput(project_reference, self._user_io.out) try: if filename and filename.endswith(".txt"): raise NotFoundException("") conan_file_path = os.path.join(conanfile_path, filename or CONANFILE) conanfile = loader.load_conan(conan_file_path, output, consumer=True) is_txt = False if conanfile.name is not None and conanfile.version is not None: project_reference = "%s/%s@" % (conanfile.name, conanfile.version) project_reference += "PROJECT" except NotFoundException: # Load requirements.txt conan_path = os.path.join(conanfile_path, filename or CONANFILE_TXT) conanfile = loader.load_conan_txt(conan_path, output) is_txt = True # build deps graph and install it builder = DepsBuilder(remote_proxy, self._user_io.out, loader) deps_graph = builder.load(reference, conanfile) registry = RemoteRegistry(self._paths.registry, self._user_io.out) if info: if check_updates: graph_updates_info = builder.get_graph_updates_info(deps_graph) else: graph_updates_info = {} Printer(self._user_io.out).print_info(deps_graph, project_reference, info, registry, graph_updates_info, remote) return Printer(self._user_io.out).print_graph(deps_graph, registry) # Warn if os doesn't match try: if detected_os() != conanfile.settings.os: message = '''You are building this package with settings.os='%s' on a '%s' system. If this is your intention, you can ignore this message. If not: - Check the passed settings (-s) - Check your global settings in ~/.conan/conan.conf - Remove conaninfo.txt to avoid bad cached settings ''' % (conanfile.settings.os, detected_os()) self._user_io.out.warn(message) except ConanException: # Setting os doesn't exist pass installer = ConanInstaller(self._paths, self._user_io, remote_proxy) installer.install(deps_graph, build_mode) if not reference_given: if is_txt: conanfile.info.settings = loader._settings.values # Just in case the current package is header only, we still store the full settings # for reference and compiler checks conanfile.info.full_settings = loader._settings.values conanfile.info.scope = self._current_scopes content = normalize(conanfile.info.dumps()) save(os.path.join(current_path, CONANINFO), content) output.info("Generated %s" % CONANINFO) write_generators(conanfile, current_path, output) local_installer = FileImporter(deps_graph, self._paths, current_path) conanfile.copy = local_installer conanfile.imports() copied_files = local_installer.execute() import_output = ScopedOutput("%s imports()" % output.scope, output) report_copied_files(copied_files, import_output)
class VersionRangesTest(unittest.TestCase): 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 root(self, content): root_conan = self.retriever.root(content) deps_graph = self.builder.load(None, root_conan) return deps_graph def test_local_basic(self): for expr, solution in [(">0.0", "2.2.1"), (">0.1,<1", "0.3"), (">0.1,<1||2.1", "2.1"), ("", "2.2.1"), ("~0", "0.3"), ("~=1", "1.2.1"), ("~1.1", "1.1.2"), ("~=2", "2.2.1"), ("~=2.1", "2.1"), ]: deps_graph = self.root(hello_content % expr) self.assertEqual(2, len(deps_graph.nodes)) hello = _get_nodes(deps_graph, "Hello")[0] say = _get_nodes(deps_graph, "Say")[0] self.assertEqual(_get_edges(deps_graph), {Edge(hello, say)}) self.assertEqual(hello.conan_ref, None) conanfile = hello.conanfile self.assertEqual(conanfile.version, "1.2") self.assertEqual(conanfile.name, "Hello") say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % solution) self.assertEqual(conanfile.requires, Requirements(str(say_ref))) def test_remote_basic(self): self.resolver._local_search = None remote_packages = [] for v in ["0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"]: say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % v) remote_packages.append(say_ref) self.remote_search.packages = remote_packages self.test_local_basic() @parameterized.expand([("", "0.3", None, None), ('"Say/1.1@memsharded/testing"', "1.1", False, False), ('"Say/0.2@memsharded/testing"', "0.2", False, True), ('("Say/1.1@memsharded/testing", "override")', "1.1", True, False), ('("Say/0.2@memsharded/testing", "override")', "0.2", True, True), # ranges ('"Say/[<=1.2]@memsharded/testing"', "1.1.2", False, False), ('"Say/[>=0.2,<=1.0]@memsharded/testing"', "0.3", False, True), ('("Say/[<=1.2]@memsharded/testing", "override")', "1.1.2", True, False), ('("Say/[>=0.2,<=1.0]@memsharded/testing", "override")', "0.3", True, True), ]) def transitive_test(self, version_range, solution, override, valid): hello_text = hello_content % ">0.1, <1" hello_ref = ConanFileReference.loads("Hello/1.0@memsharded/testing") self.retriever.conan(hello_ref, hello_text) chat_content = """ from conans import ConanFile class ChatConan(ConanFile): name = "Chat" version = "2.3" requires = "Hello/1.0@memsharded/testing", %s """ deps_graph = self.root(chat_content % version_range) hello = _get_nodes(deps_graph, "Hello")[0] say = _get_nodes(deps_graph, "Say")[0] chat = _get_nodes(deps_graph, "Chat")[0] edges = {Edge(hello, say), Edge(chat, hello)} if override is not None: self.assertIn("override", self.output) else: self.assertNotIn("override", self.output) if override is False: edges = {Edge(hello, say), Edge(chat, say), Edge(chat, hello)} if valid is True: self.assertIn(" valid", self.output) elif valid is False: self.assertIn("not valid", self.output) self.assertEqual(3, len(deps_graph.nodes)) self.assertEqual(_get_edges(deps_graph), edges) self.assertEqual(hello.conan_ref, hello_ref) conanfile = hello.conanfile self.assertEqual(conanfile.version, "1.2") self.assertEqual(conanfile.name, "Hello") say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % solution) self.assertEqual(conanfile.requires, Requirements(str(say_ref)))
class VersionRangesTest(unittest.TestCase): 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 root(self, content): root_conan = self.retriever.root(content) deps_graph = self.builder.load(None, root_conan) return deps_graph def test_local_basic(self): for expr, solution in [(">0.0", "2.2.1"), (">0.1, <1", "0.3"), (">0.1, <1 || 2.1", "2.1"), ("", "2.2.1"), ("~0", "0.3"), ("~=1", "1.2.1"), ("~1.1", "1.1.2"), ("~=2", "2.2.1"), ("~=2.1", "2.1"), ]: deps_graph = self.root(hello_content % expr) self.assertEqual(2, len(deps_graph.nodes)) hello = _get_nodes(deps_graph, "Hello")[0] say = _get_nodes(deps_graph, "Say")[0] self.assertEqual(_get_edges(deps_graph), {Edge(hello, say)}) self.assertEqual(hello.conan_ref, None) conanfile = hello.conanfile self.assertEqual(conanfile.version, "1.2") self.assertEqual(conanfile.name, "Hello") say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % solution) self.assertEqual(conanfile.requires, Requirements(str(say_ref))) def test_remote_basic(self): self.resolver._local_search = None remote_packages = [] for v in ["0.1", "0.2", "0.3", "1.1", "1.1.2", "1.2.1", "2.1", "2.2.1"]: say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % v) remote_packages.append(say_ref) self.remote_search.packages = remote_packages self.test_local_basic() @parameterized.expand([("", "0.3", None, None), ('"Say/1.1@memsharded/testing"', "1.1", False, False), ('"Say/0.2@memsharded/testing"', "0.2", False, True), ('("Say/1.1@memsharded/testing", "override")', "1.1", True, False), ('("Say/0.2@memsharded/testing", "override")', "0.2", True, True), # ranges ('"Say/[<=1.2]@memsharded/testing"', "1.1.2", False, False), ('"Say/[>=0.2,<=1.1]@memsharded/testing"', "0.3", False, True), ('("Say/[<=1.2]@memsharded/testing", "override")', "1.1.2", True, False), ('("Say/[>=0.2,<=1.1]@memsharded/testing", "override")', "0.3", True, True), ]) def transitive_test(self, version_range, solution, override, valid): hello_text = hello_content % ">0.1, <1" hello_ref = ConanFileReference.loads("Hello/1.0@memsharded/testing") self.retriever.conan(hello_ref, hello_text) chat_content = """ from conans import ConanFile class ChatConan(ConanFile): name = "Chat" version = "2.3" requires = "Hello/1.0@memsharded/testing", %s """ deps_graph = self.root(chat_content % version_range) hello = _get_nodes(deps_graph, "Hello")[0] say = _get_nodes(deps_graph, "Say")[0] chat = _get_nodes(deps_graph, "Chat")[0] edges = {Edge(hello, say), Edge(chat, hello)} if override is not None: self.assertIn("override", self.output) else: self.assertNotIn("override", self.output) if override is False: edges = {Edge(hello, say), Edge(chat, say), Edge(chat, hello)} if valid is True: self.assertIn(" valid", self.output) elif valid is False: self.assertIn("not valid", self.output) self.assertEqual(3, len(deps_graph.nodes)) self.assertEqual(_get_edges(deps_graph), edges) self.assertEqual(hello.conan_ref, hello_ref) conanfile = hello.conanfile self.assertEqual(conanfile.version, "1.2") self.assertEqual(conanfile.name, "Hello") say_ref = ConanFileReference.loads("Say/%s@memsharded/testing" % solution) self.assertEqual(conanfile.requires, Requirements(str(say_ref)))
def install(self, reference, current_path, remote=None, options=None, settings=None, build_mode=False, info=None, filename=None): """ Fetch and build all dependencies for the given reference @param reference: ConanFileReference or path to user space conanfile @param current_path: where the output files will be saved @param remote: install only from that remote @param options: written in JSON, e.g. {"compiler": "Visual Studio 12", ...} """ reference_given = True if not isinstance(reference, ConanFileReference): conanfile_path = reference reference_given = False reference = None loader = self._loader(current_path, settings, options) installer = ConanInstaller(self._paths, self._user_io, loader, self.remote_manager, remote) if reference_given: project_reference = None conanfile = installer.retrieve_conanfile(reference, consumer=True) else: project_reference = "PROJECT" output = ScopedOutput(project_reference, self._user_io.out) try: if filename and filename.endswith(".txt"): raise NotFoundException() conan_file_path = os.path.join(conanfile_path, filename or CONANFILE) conanfile = loader.load_conan(conan_file_path, output, consumer=True) is_txt = False if conanfile.name is not None and conanfile.version is not None: project_reference = "%s/%s@" % (conanfile.name, conanfile.version) # Calculate a placeholder conan file reference for the project current_user = self._localdb.get_username() if current_user: project_reference += "%s/" % current_user project_reference += "PROJECT" except NotFoundException: # Load requirements.txt conan_path = os.path.join(conanfile_path, filename or CONANFILE_TXT) conanfile = loader.load_conan_txt(conan_path, output) is_txt = True # build deps graph and install it builder = DepsBuilder(installer, self._user_io.out) deps_graph = builder.load(reference, conanfile) if info: Printer(self._user_io.out).print_info(deps_graph, project_reference, info) return Printer(self._user_io.out).print_graph(deps_graph) installer.install(deps_graph, build_mode) if not reference_given: if is_txt: conanfile.info.settings = loader._settings.values # Just in case the current package is header only, we still store the full settings # for reference and compiler checks conanfile.info.full_settings = loader._settings.values content = normalize(conanfile.info.dumps()) save(os.path.join(current_path, CONANINFO), content) self._user_io.out.writeln("") output.info("Generated %s" % CONANINFO) write_generators(conanfile, current_path, output) local_installer = FileImporter(deps_graph, self._paths, current_path) conanfile.copy = local_installer conanfile.imports() local_installer.execute()