Beispiel #1
0
    def test_environment_marker_evaluation_called(self):
        """
        If one package foo requires bar without any extras,
        markers should pass for bar without extras.
        """
        parent_req, = parse_requirements("foo")
        req, = parse_requirements("bar;python_version>='2'")
        req_extras = pkg_resources._ReqExtras({req: parent_req.extras})
        assert req_extras.markers_pass(req)

        parent_req, = parse_requirements("foo[]")
        req, = parse_requirements("bar;python_version>='2'")
        req_extras = pkg_resources._ReqExtras({req: parent_req.extras})
        assert req_extras.markers_pass(req)
Beispiel #2
0
    def test_environment_marker_evaluation_called(self):
        """
        If one package foo requires bar without any extras,
        markers should pass for bar without extras.
        """
        parent_req, = parse_requirements("foo")
        req, = parse_requirements("bar;python_version>='2'")
        req_extras = pkg_resources._ReqExtras({req: parent_req.extras})
        assert req_extras.markers_pass(req)

        parent_req, = parse_requirements("foo[]")
        req, = parse_requirements("bar;python_version>='2'")
        req_extras = pkg_resources._ReqExtras({req: parent_req.extras})
        assert req_extras.markers_pass(req)
Beispiel #3
0
    def test_environment_marker_evaluation_called(self):
        """
        If one package foo requires bar without any extras,
        markers should pass for bar.
        """
        parent_req, = parse_requirements("foo")
        req, = parse_requirements("bar;python_version>='2'")
        req_extras = pkg_resources._ReqExtras({req: parent_req.extras})
        assert req_extras.markers_pass(req)

        parent_req, = parse_requirements("foo[]")
        req, = parse_requirements("bar;python_version>='2'")
        req_extras = pkg_resources._ReqExtras({req: parent_req.extras})
        assert req_extras.markers_pass(req)

        # extra should not be present in the marker namespace if
        # no markers were supplied
        parent_req, = parse_requirements("foo")
        req, = parse_requirements("bar;extra==''")
        req_extras = pkg_resources._ReqExtras({req: parent_req.extras})
        with pytest.raises(packaging.markers.UndefinedEnvironmentName):
            req_extras.markers_pass(req)
Beispiel #4
0
    def resolve(
        self,
        requirements: Sequence[Requirement],
        env: Optional[Environment] = None,
        installer: Optional[Callable[[str], Distribution]] = None,
        replace_conflicting: Optional[bool] = False,
        extras: List[str] = None,
    ) -> List[Distribution]:
        """List all distributions needed to (recursively) meet `requirements`
        `requirements` must be a sequence of ``Requirement`` objects.  `env`,
        if supplied, should be an ``Environment`` instance.  If
        not supplied, it defaults to all distributions available within any
        entry or distribution in the working set.  `installer`, if supplied,
        will be invoked with each requirement that cannot be met by an
        already-installed distribution; it should return a ``Distribution`` or
        ``None``.
        Unless `replace_conflicting=True`, raises a VersionConflict exception
        if
        any requirements are found on the path that have the correct name but
        the wrong version.  Otherwise, if an `installer` is supplied it will be
        invoked to obtain the correct version of the requirement and activate
        it.
        `extras` is a list of the extras to be used with these requirements.
        This is important because extra requirements may look like `my_req;
        extra = "my_extra"`, which would otherwise be interpreted as a purely
        optional requirement.  Instead, we want to be able to assert that these
        requirements are truly required.
        """

        # set up the stack
        requirements = list(requirements)[::-1]
        # set of processed requirements
        processed = {}
        # key -> dist
        best = {}
        resolved = []

        requirement_extras = _ReqExtras()

        # Mapping of requirement to set of distributions that required it;
        # useful for reporting info about conflicts.
        required_by = defaultdict(set)

        while requirements:
            # process dependencies breadth-first
            requirement = requirements.pop(0)
            if requirement in processed:
                # Ignore cyclic or redundant dependencies
                continue

            if not requirement_extras.markers_pass(requirement, extras):
                continue

            dist = best.get(requirement.key)
            if dist is None:
                # Find the best distribution and add it to the map
                dist = self.by_key.get(requirement.key)
                if dist is None or (dist not in requirement and replace_conflicting):
                    ws = self
                    if env is None:
                        if dist is None:
                            env = Environment(self.entries)
                        else:
                            # Use an empty environment and workingset to avoid
                            # any further conflicts with the conflicting
                            # distribution
                            env = Environment([])
                            ws = WorkingSet([])
                    dist = best[requirement.key] = env.best_match(
                        requirement,
                        ws,
                        installer,
                        replace_conflicting=replace_conflicting,
                    )
                    if dist is None:
                        requirers = required_by.get(requirement, None)
                        raise DistributionNotFound(requirement, requirers)
                resolved.append(dist)

            if dist not in requirement:
                # Oops, the "best" so far conflicts with a dependency
                dependent_requirement = required_by[requirement]
                raise VersionConflict(dist, requirement).with_context(
                    dependent_requirement
                )

            # push the new requirements onto the stack
            new_requirements = [
                requirement
                for requirement in dist.requires(requirement.extras)[::-1]
                if requirement.key not in self.excludes
            ]
            requirements.extend(new_requirements)

            # Register the new requirements needed by requirement
            for new_requirement in new_requirements:
                required_by[new_requirement].add(requirement.project_name)
                requirement_extras[new_requirement] = requirement.extras

            processed[requirement] = True

        # return list of distros to activate
        return resolved