def _add_package_rules(self, package):
        """
        Create all the rules required to satisfy installing the given package.
        """
        work_queue = collections.deque()
        work_queue.append(package)

        while len(work_queue) > 0:
            p = work_queue.popleft()

            p_id = self._pool.package_id(p)
            if p_id not in self.added_package_ids:
                self.added_package_ids.add(p_id)

                self._add_dependencies_rules(p, work_queue)

                requirement = Requirement.from_legacy_requirement_string(p.name)
                obsolete_providers = self._pool.what_provides(requirement)
                for provider in obsolete_providers:
                    if provider != p:
                        if provider.name == p.name:
                            reason = RuleType.package_same_name
                        else:
                            reason = RuleType.package_implicit_obsoletes
                        rule = self._create_conflicts_rule(p, provider,
                                                           reason, str(p))
                        self._add_rule(rule, "package")
    def _add_package_rules(self, package):
        """
        Create all the rules required to satisfy installing the given package.
        """
        work_queue = collections.deque()
        work_queue.append(package)

        while len(work_queue) > 0:
            p = work_queue.popleft()

            p_id = self._pool.package_id(p)
            if p_id not in self.added_package_ids:
                self.added_package_ids.add(p_id)

                self._add_dependencies_rules(p, work_queue)

                requirement = Requirement.from_legacy_requirement_string(
                    p.name)
                obsolete_providers = self._pool.what_provides(requirement)
                for provider in obsolete_providers:
                    if provider != p:
                        if provider.name == p.name:
                            reason = RuleType.package_same_name
                        else:
                            reason = RuleType.package_implicit_obsoletes
                        rule = self._create_conflicts_rule(
                            p, provider, reason, str(p))
                        self._add_rule(rule, "package")
    def _from_string(cls, rule_string, pool):
        """
        Creates a PackageRule from a rule string, e.g. '-numpy-1.6.0 | numpy-1.7.0'

        Because package full name -> id is not 1-to-1 mapping, this may fail
        when a package has multiple ids. This is mostly used for testing, to
        write reference rules a bit more easily.
        """
        packages_string = (s.strip() for s in rule_string.split("|"))
        package_literals = []
        for package_string in packages_string:
            if package_string.startswith("-"):
                positive = False
                package_string = package_string[1:]
            else:
                positive = True

            requirement = Requirement.from_package_string(package_string)
            package_candidates = pool.what_provides(requirement)
            if len(package_candidates) == 0:
                msg = "No candidate for package {0!r}".format(package_string)
                raise EnstallerException(msg)
            elif len(package_candidates) > 1:
                msg = "> 1 candidate for package {0!r} requirement, cannot " \
                      "create rule from it" % package_string
                raise EnstallerException(msg)
            else:
                _id = pool.package_id(package_candidates[0])
                if positive:
                    package_literals.append(_id)
                else:
                    package_literals.append(-_id)
        return cls(package_literals)
    def _from_string(cls, rule_string, pool):
        """
        Creates a PackageRule from a rule string, e.g. '-numpy-1.6.0 | numpy-1.7.0'

        Because package full name -> id is not 1-to-1 mapping, this may fail
        when a package has multiple ids. This is mostly used for testing, to
        write reference rules a bit more easily.
        """
        packages_string = (s.strip() for s in rule_string.split("|"))
        package_literals = []
        for package_string in packages_string:
            if package_string.startswith("-"):
                positive = False
                package_string = package_string[1:]
            else:
                positive = True

            requirement = Requirement.from_package_string(package_string)
            package_candidates = pool.what_provides(requirement)
            if len(package_candidates) == 0:
                msg = "No candidate for package {0!r}".format(package_string)
                raise EnstallerException(msg)
            elif len(package_candidates) > 1:
                msg = "> 1 candidate for package {0!r} requirement, cannot " \
                      "create rule from it" % package_string
                raise EnstallerException(msg)
            else:
                _id = pool.package_id(package_candidates[0])
                if positive:
                    package_literals.append(_id)
                else:
                    package_literals.append(-_id)
        return cls(package_literals)
Exemple #5
0
    def from_yaml(cls, filename):
        with open(filename) as fp:
            data = yaml.load(fp)

        packages = collections.OrderedDict(
            parse_package_list(data.get("packages", [])))
        operations = data.get("request", [])

        request = Request()

        for operation in operations:
            kind = operation["operation"]
            requirement = Requirement._from_string(operation["requirement"])
            getattr(request, kind)(requirement)

        decisions = data.get("decisions", {})

        operations = []
        for operation in data.get("transaction", []):
            if operation["kind"] == "install":
                operations.append(InstallOperation(operation["package"]))
            elif operation["kind"] == "update":
                operations.append(
                    UpdateOperation(operation["from"], operation["to"]))
            elif operation["kind"] == "remove":
                operations.append(RemoveOperation(operation["package"]))
            else:
                msg = "invalid operation kind {!r}".format(operation["kind"])
                raise ValueError(msg)

        return cls(packages, [remote_repository(data, packages)],
                   installed_repository(data, packages), request, decisions,
                   operations)
Exemple #6
0
    def from_yaml(cls, filename):
        with open(filename) as fp:
            data = yaml.load(fp)

        packages = collections.OrderedDict(
            parse_package_list(data.get("packages", []))
        )
        operations = data.get("request", [])

        request = Request()

        for operation in operations:
            kind = operation["operation"]
            requirement = Requirement._from_string(operation["requirement"])
            getattr(request, kind)(requirement)

        decisions = data.get("decisions", {})

        operations = []
        for operation in data.get("transaction", []):
            if operation["kind"] == "install":
                operations.append(InstallOperation(operation["package"]))
            elif operation["kind"] == "update":
                operations.append(UpdateOperation(operation["from"],
                                                  operation["to"]))
            elif operation["kind"] == "remove":
                operations.append(RemoveOperation(operation["package"]))
            else:
                msg = "invalid operation kind {!r}".format(operation["kind"])
                raise ValueError(msg)

        return cls(packages, [remote_repository(data, packages)],
                   installed_repository(data, packages), request,
                   decisions, operations)
def dependency_to_string(dependency):
    req = Requirement.from_legacy_requirement_string(dependency)
    constraints = list(req._constraints._constraints)
    assert len(constraints) == 1
    assert isinstance(constraints[0], (EnpkgUpstreamMatch, Any, Equal))
    constraint = constraints[0]
    if isinstance(constraint, Any):
        return req.name
    elif isinstance(constraint, Equal):
        return "{0} == {1}".format(req.name, str(constraint.version))
    else:  # EnpkgUpstreamMatch
        assert isinstance(constraint.version, EnpkgVersion)
        return "{0} ~= {1}".format(req.name, str(constraint.version.upstream))
def dependency_to_string(dependency):
    req = Requirement.from_legacy_requirement_string(dependency)
    constraints = list(req._constraints._constraints)
    assert len(constraints) == 1
    assert isinstance(constraints[0],
                      (EnpkgUpstreamMatch, Any, Equal))
    constraint = constraints[0]
    if isinstance(constraint, Any):
        return req.name
    elif isinstance(constraint, Equal):
        return "{0} == {1}".format(req.name, str(constraint.version))
    else:  # EnpkgUpstreamMatch
        assert isinstance(constraint.version, EnpkgVersion)
        return "{0} ~= {1}".format(req.name, str(constraint.version.upstream))
    def _add_dependencies_rules(self, package, work_queue):
        for dependency in package.dependencies:
            requirement = Requirement.from_legacy_requirement_string(dependency)
            dependency_candidates = self._pool.what_provides(requirement)

            assert len(dependency_candidates) > 0, \
                ("No candidates found for requirement {0!r}, needed for "
                 "dependency {1!r}".format(requirement.name, package))

            rule = self._create_dependency_rule(package, dependency_candidates,
                                                RuleType.package_requires,
                                                str(dependency))
            self._add_rule(rule, "package")

            for candidate in dependency_candidates:
                work_queue.append(candidate)
    def _add_dependencies_rules(self, package, work_queue):
        for dependency in package.dependencies:
            requirement = Requirement.from_legacy_requirement_string(
                dependency)
            dependency_candidates = self._pool.what_provides(requirement)

            assert len(dependency_candidates) > 0, \
                ("No candidates found for requirement {0!r}, needed for "
                 "dependency {1!r}".format(requirement.name, package))

            rule = self._create_dependency_rule(package, dependency_candidates,
                                                RuleType.package_requires,
                                                str(dependency))
            self._add_rule(rule, "package")

            for candidate in dependency_candidates:
                work_queue.append(candidate)
Exemple #11
0
def optimize_at_level(pool, parent_package, rules, solution):
    new_rules = rules[:]

    # Step 1: optimize each dependency independently
    best_dependencies = []

    for dependency in parent_package.dependencies:
        requirement = Requirement.from_legacy_requirement_string(dependency)
        best_candidate = find_best_candidate(pool, requirement, new_rules)

        new_rules.append(PackageRule((best_candidate.id,)))
        best_dependencies.append(best_candidate)

    solution.extend(best_dependencies)

    # Step 2: recurse
    for dependency in best_dependencies:
        solution = optimize_at_level(pool, dependency, new_rules, solution)

    return solution
Exemple #12
0
def legacy_dependencies_to_pretty_string(dependencies):
    """ Convert a sequence of legacy dependency strings to a pretty constraint
    string.

    Parameters
    ----------
    dependencies : seq
        Sequence of legacy dependency string (e.g. 'MKL 10.3')
    """
    constraints_mapping = []

    for dependency in dependencies:
        req = Requirement.from_legacy_requirement_string(dependency)
        constraints = req._constraints._constraints
        assert len(constraints) == 1
        constraint = next(iter(constraints))
        assert isinstance(constraint,
                          (EnpkgUpstreamMatch, Any, Equal))
        constraints_mapping.append((req.name, frozenset((constraint,))))

    return constraints_to_pretty_string(constraints_mapping)
Exemple #13
0
    # Step 2: recurse
    for dependency in best_dependencies:
        solution = optimize_at_level(pool, dependency, new_rules, solution)

    return solution


def optimize(pool, requirement, rules):
    best_package = find_best_candidate(pool, requirement, rules)
    solution = [best_package]
    return optimize_at_level(pool, best_package, rules, solution)


if __name__ == '__main__':
    repository = repository_from_index("full_index.json")
    pool = Pool([repository])

    requirement_str = "scikit_learn < 0.14"
    requirement = Requirement._from_string(requirement_str)

    request = Request()
    request.install(requirement)

    rules_generator = RulesGenerator(pool, request)
    rules = list(rules_generator.iter_rules())

    solution = optimize(pool, requirement, rules)
    for decision in solution:
        print(decision.name, str(decision.version))
Exemple #14
0
    # Step 2: recurse
    for dependency in best_dependencies:
        solution = optimize_at_level(pool, dependency, new_rules, solution)

    return solution


def optimize(pool, requirement, rules):
    best_package = find_best_candidate(pool, requirement, rules)
    solution = [best_package]
    return optimize_at_level(pool, best_package, rules, solution)


if __name__ == '__main__':
    repository = repository_from_index("full_index.json")
    pool = Pool([repository])

    requirement_str = "scikit_learn < 0.14"
    requirement = Requirement._from_string(requirement_str)

    request = Request()
    request.install(requirement)

    rules_generator = RulesGenerator(pool, request)
    rules = list(rules_generator.iter_rules())

    solution = optimize(pool, requirement, rules)
    for decision in solution:
        print(decision.name, str(decision.version))