def extend_build_requires(self, graph, node, build_requires_refs, check_updates, update, remotes, profile_host, profile_build, graph_lock): # The options that will be defined in the node will be the real options values that have # been already propagated downstream from the dependency graph. This will override any # other possible option in the build_requires dependency graph. This means that in theory # an option conflict while expanding the build_requires is impossible node.conanfile.build_requires_options.clear_unscoped_options() new_options = node.conanfile.build_requires_options._reqs_options new_reqs = Requirements() conanfile = node.conanfile scope = conanfile.display_name build_requires = [] for ref, context in build_requires_refs: r = Requirement(ref) r.build_require = True r.build_require_context = context r.force_host_context = getattr(ref, "force_host_context", False) build_requires.append(r) if graph_lock: graph_lock.pre_lock_node(node) # TODO: Add info about context? graph_lock.lock_node(node, build_requires, build_requires=True) for require in build_requires: self._resolve_alias(node, require, graph, update, update, remotes) self._resolve_ranges(graph, build_requires, scope, update, remotes) for br in build_requires: context_switch = bool(br.build_require_context == CONTEXT_BUILD) populate_settings_target = context_switch # Avoid 'settings_target' for BR-host self._expand_require( br, node, graph, check_updates, update, remotes, profile_host, profile_build, new_reqs, new_options, graph_lock, context_switch=context_switch, populate_settings_target=populate_settings_target) new_nodes = set(n for n in graph.nodes if n.package_id is None) # This is to make sure that build_requires have precedence over the normal requires node.public_closure.sort(key_fn=lambda x: x not in new_nodes) return new_nodes
def _look_for_require(self, require): try: python_require = self._cached_requires[require] except KeyError: ref = ConanFileReference.loads(require) requirement = Requirement(ref) self._range_resolver.resolve(requirement, "python_require", update=False, remote_name=None) ref = requirement.ref result = self._proxy.get_recipe(ref, self._check_updates, self._update, remote_name=self._remote_name, recorder=ActionRecorder()) path, _, _, new_ref = result module, conanfile = parse_conanfile(conanfile_path=path, python_requires=self) # Check for alias if getattr(conanfile, "alias", None): # Will register also the aliased python_require = self._look_for_require(conanfile.alias) else: python_require = PythonRequire(new_ref, module, conanfile) self._cached_requires[require] = python_require return python_require
def extend_build_requires(self, graph, node, build_requires_refs, check_updates, update, remotes, profile_host, graph_lock): # The options that will be defined in the node will be the real options values that have # been already propagated downstream from the dependency graph. This will override any # other possible option in the build_requires dependency graph. This means that in theory # an option conflict while expanding the build_requires is impossible node.conanfile.build_requires_options.clear_unscoped_options() new_options = node.conanfile.build_requires_options._reqs_options new_reqs = Requirements() conanfile = node.conanfile scope = conanfile.display_name requires = [Requirement(ref) for ref in build_requires_refs] for r in requires: r.build_require = True if graph_lock: graph_lock.pre_lock_node(node) graph_lock.lock_node(node, requires, build_requires=True) self._resolve_ranges(graph, requires, scope, update, remotes) for require in requires: self._expand_require(require, node, graph, check_updates, update, remotes, profile_host, new_reqs, new_options, graph_lock) new_nodes = set(n for n in graph.nodes if n.package_id is None) # This is to make sure that build_requires have precedence over the normal requires ordered_closure = list(node.public_closure.items()) ordered_closure.sort(key=lambda x: x[1] not in new_nodes) node.public_closure = OrderedDict(ordered_closure) return new_nodes
def _look_for_require(self, reference): ref = ConanFileReference.loads(reference) ref = self.locked_versions[ref.name] if self.locked_versions is not None else ref try: python_require = self._cached_requires[ref] except KeyError: requirement = Requirement(ref) self._range_resolver.resolve(requirement, "python_require", update=self._update, remotes=self._remotes) ref = requirement.ref result = self._proxy.get_recipe(ref, self._check_updates, self._update, remotes=self._remotes, recorder=ActionRecorder()) path, _, _, new_ref = result module, conanfile = parse_conanfile(conanfile_path=path, python_requires=self) # Check for alias if getattr(conanfile, "alias", None): # Will register also the aliased python_require = self._look_for_require(conanfile.alias) else: package_layout = self._proxy._cache.package_layout(new_ref, conanfile.short_paths) exports_sources_folder = package_layout.export_sources() exports_folder = package_layout.export() python_require = PythonRequire(new_ref, module, conanfile, exports_folder, exports_sources_folder) self._cached_requires[ref] = python_require return python_require
def __call__(self, require): try: m, reference = self._modules[require] self._references.append(reference) return m except KeyError: r = ConanFileReference.loads(require) requirement = Requirement(r) self._range_resolver.resolve(requirement, "python_require", update=False, remote_name=None) r = requirement.conan_reference result = self._proxy.get_recipe(r, False, False, remote_name=None, recorder=ActionRecorder()) path, _, _, reference = result self._references.append(reference) try: sys.path.append(os.path.dirname(path)) module = imp.load_source("python_require", path) finally: sys.path.pop() self._modules[require] = module, reference return module
def _resolve_ref(self, py_requires_ref, lock_python_requires): ref = ConanFileReference.loads(py_requires_ref) if lock_python_requires: locked = {r.name: r for r in lock_python_requires}[ref.name] ref = locked else: requirement = Requirement(ref) self._range_resolver.resolve(requirement, "py_require", update=self._update, remotes=self._remotes) ref = requirement.ref return ref
def _load_pyreq_conanfile(self, loader, lock_python_requires, ref): recipe = self._proxy.get_recipe(ref, self._check_updates, self._update, remotes=self._remotes, recorder=ActionRecorder()) path, _, _, new_ref = recipe conanfile, module = loader.load_basic_module(path, lock_python_requires, user=new_ref.user, channel=new_ref.channel) conanfile.name = new_ref.name # FIXME Conan 2.0 version should be a string, not a Version object conanfile.version = new_ref.version if getattr(conanfile, "alias", None): ref = ConanFileReference.loads(conanfile.alias) requirement = Requirement(ref) alias = requirement.alias if alias is not None: ref = alias conanfile, module, new_ref, path = self._load_pyreq_conanfile(loader, lock_python_requires, ref) return conanfile, module, new_ref, os.path.dirname(path)
def _resolve_alias(self, node, require, graph, check_updates, update, remotes): alias = require.alias if alias is None: return # First try cached cached = graph.new_aliased.get(alias) if cached is not None: while True: new_cached = graph.new_aliased.get(cached) if new_cached is None: break else: cached = new_cached require.ref = cached return while alias is not None: # if not cached, then resolve try: result = self._proxy.get_recipe(alias, check_updates, update, remotes, self._recorder) conanfile_path, recipe_status, remote, new_ref = result except ConanException as e: raise e dep_conanfile = self._loader.load_basic(conanfile_path) try: pointed_ref = ConanFileReference.loads(dep_conanfile.alias) except Exception as e: raise ConanException("Alias definition error in {}: {}".format( alias, str(e))) # UPDATE THE REQUIREMENT! require.ref = require.range_ref = pointed_ref graph.new_aliased[alias] = pointed_ref # Caching the alias new_req = Requirement( pointed_ref) # FIXME: Ugly temp creation just for alias check alias = new_req.alias
def __call__(self, require): try: python_require = self._cached_requires[require] except KeyError: r = ConanFileReference.loads(require) requirement = Requirement(r) self._range_resolver.resolve(requirement, "python_require", update=False, remote_name=None) r = requirement.conan_reference result = self._proxy.get_recipe(r, False, False, remote_name=None, recorder=ActionRecorder()) path, _, _, reference = result module, _ = parse_conanfile(path) python_require = PythonRequire(reference, module) self._cached_requires[require] = python_require self._requires.append(python_require) return python_require.module
def extend_build_requires(self, graph, node, build_requires_refs, check_updates, update, remotes, processed_profile): # The options that will be defined in the node will be the real options values that have # been already propagated downstream from the dependency graph. This will override any # other possible option in the build_requires dependency graph. This means that in theory # an option conflict while expanding the build_requires is impossible node.conanfile.build_requires_options.clear_unscoped_options() new_options = node.conanfile.build_requires_options._reqs_options new_reqs = Requirements() conanfile = node.conanfile scope = conanfile.display_name requires = [Requirement(ref) for ref in build_requires_refs] self._resolve_ranges(graph, requires, scope, update, remotes) for require in requires: name = require.ref.name require.build_require = True self._handle_require(name, node, require, graph, check_updates, update, remotes, processed_profile, new_reqs, new_options) new_nodes = set([n for n in graph.nodes if n.package_id is None]) # This is to make sure that build_requires have precedence over the normal requires ordered_closure = list(node.public_closure.items()) ordered_closure.sort(key=lambda x: x[1] not in new_nodes) node.public_closure = OrderedDict(ordered_closure) subgraph = DepsGraph() subgraph.aliased = graph.aliased subgraph.evaluated = graph.evaluated subgraph.nodes = new_nodes for n in subgraph.nodes: n.build_require = True return subgraph
def unit_test_get_reference_to_test(self): obj = PackageTester(None, None) # No requires in the test_package/conanfile.py, specified parameters requires = {} ref = obj._get_reference_to_test(requires, "lib", "1.0", "user", "channel") self.assertEquals(ref, ConanFileReference.loads("lib/1.0@user/channel")) # One require, with same info that we are passing requires = { "lib": Requirement(ConanFileReference.loads("lib/1.0@user/channel")) } ref = obj._get_reference_to_test(requires, "lib", "1.0", "user", "channel") self.assertEquals(ref, ConanFileReference.loads("lib/1.0@user/channel")) # One require, with same info (Except user and channel) requires = { "lib": Requirement(ConanFileReference.loads("lib/1.0@user2/channel2")) } ref = obj._get_reference_to_test(requires, "lib", "1.0", "user", "channel") self.assertEquals(ref, ConanFileReference.loads("lib/1.0@user/channel")) # One require, for a different library requires = { "lib2": Requirement(ConanFileReference.loads("lib2/1.0@user2/channel2")) } ref = obj._get_reference_to_test(requires, "lib", "1.0", "user", "channel") self.assertEquals(ref, ConanFileReference.loads("lib/1.0@user/channel")) # Two requires, for different libraries requires = { "lib2": Requirement(ConanFileReference.loads("lib2/1.0@user2/channel2")), "lib2": Requirement(ConanFileReference.loads("lib2/1.0@user2/channel2")) } ref = obj._get_reference_to_test(requires, "lib", "1.0", "user", "channel") self.assertEquals(ref, ConanFileReference.loads("lib/1.0@user/channel")) # Two requires, one matching requires = { "lib2": Requirement(ConanFileReference.loads("lib2/1.0@user2/channel2")), "lib": Requirement(ConanFileReference.loads("lib/1.0@user2/channel2")) } ref = obj._get_reference_to_test(requires, "lib", "1.0", "user", "channel") self.assertEquals(ref, ConanFileReference.loads("lib/1.0@user/channel")) # Two requires, one matching, no specifing user/channel requires = { "lib2": Requirement(ConanFileReference.loads("lib2/1.0@user2/channel2")), "lib": Requirement(ConanFileReference.loads("lib/1.0@user2/channel2")) } ref = obj._get_reference_to_test(requires, "lib", "1.0", None, None) self.assertEquals(ref, ConanFileReference.loads("lib/1.0@user2/channel2")) # Two requires, one matching, no specifing lib requires = { "lib2": Requirement(ConanFileReference.loads("lib2/1.0@user2/channel2")), "lib": Requirement(ConanFileReference.loads("lib/1.0@user2/channel2")) } with self.assertRaisesRegexp( ConanException, "Cannot deduce the reference to be tested"): obj._get_reference_to_test(requires, None, None, None, None) # Library missmatching version requires = { "lib2": Requirement(ConanFileReference.loads("lib2/1.0@user2/channel2")), "lib": Requirement(ConanFileReference.loads("lib/1.0@user2/channel2")) } with self.assertRaisesRegexp(ConanException, "he specified version doesn't match"): obj._get_reference_to_test(requires, "lib", "1.2", None, None)