Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
    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
Beispiel #5
0
 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
Beispiel #6
0
 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
Beispiel #7
0
    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)
Beispiel #8
0
    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
Beispiel #9
0
 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
Beispiel #10
0
    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
Beispiel #11
0
    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)