Beispiel #1
0
    def test_simple_dependency(self):
        # Given
        mkl = self.package_factory(u"mkl 10.3-1")
        libgfortran = self.package_factory(u"libgfortran 3.0.0-2")
        numpy = self.package_factory(
            u"numpy 1.9.2-1; depends (mkl == 10.3-1, libgfortran ^= 3.0.0)"
        )

        r_operations = [
            InstallOperation(mkl),
            InstallOperation(libgfortran),
            InstallOperation(numpy),
        ]

        self.repository.add_package(mkl)
        self.repository.add_package(libgfortran)
        self.repository.add_package(numpy)

        request = Request()
        request.install(R("numpy"))

        # When
        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
Beispiel #2
0
    def test_upgrade_fail(self):
        # Given
        mkl_11_3_1 = P(u"mkl 11.3.1-1")
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        mkl_2017_0_1_2 = P(u"mkl 2017.0.1-2")

        numpy_1_10_4 = P(u"numpy 1.10.4-1; depends (mkl ^= 11.3.1)")

        scipy_0_17_1 = P(u"scipy 0.17.1-1; depends (mkl ^= 11.3.1, numpy ^= 1.10.4)")

        self.repository.update([
            mkl_11_3_1, mkl_2017_0_1_1, mkl_2017_0_1_2, numpy_1_10_4,
            scipy_0_17_1
        ])
        self.installed_repository.update([mkl_11_3_1, numpy_1_10_4, scipy_0_17_1])

        r_hint_pretty_string = textwrap.dedent(u"""\
            The following jobs are conflicting:
                install mkl == 2017.0.1-2
                install numpy == 1.10.4-1"""
        )

        # When/Then
        request = Request()
        request.upgrade()

        with self.assertRaises(SatisfiabilityErrorWithHint) as ctx:
            self.resolve_with_hint(request)

        self.assertMultiLineEqual(
            ctx.exception.hint_pretty_string, r_hint_pretty_string)
Beispiel #3
0
    def test_upgrade_simple(self):
        # Given
        mkl_11_3_1 = P(u"mkl 11.3.1-1")
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        mkl_2017_0_1_2 = P(u"mkl 2017.0.1-2")

        numpy_1_10_4 = P(u"numpy 1.10.4-1; depends (mkl ^= 11.3.1)")
        numpy_1_11_3 = P(u"numpy 1.11.3-1; depends (mkl ^= 2017.0.1)")

        scipy_0_17_1 = P(u"scipy 0.17.1-1; depends (mkl ^= 11.3.1, numpy ^= 1.10.4)")
        scipy_0_18_1 = P(u"scipy 0.18.1-1; depends (mkl ^= 2017.0.1, numpy ^= 1.11.3)")

        self.repository.update([
            mkl_11_3_1, mkl_2017_0_1_1, mkl_2017_0_1_2, numpy_1_10_4,
            numpy_1_11_3, scipy_0_17_1, scipy_0_18_1
        ])
        self.installed_repository.update([mkl_11_3_1, numpy_1_10_4, scipy_0_17_1])

        r_operations = [
            RemoveOperation(scipy_0_17_1),
            RemoveOperation(numpy_1_10_4),
            RemoveOperation(mkl_11_3_1),
            InstallOperation(mkl_2017_0_1_2),
            InstallOperation(numpy_1_11_3),
            InstallOperation(scipy_0_18_1),
        ]

        # When
        request = Request()
        request.upgrade()

        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
Beispiel #4
0
    def test_upgrade_no_candidate(self):
        # Given
        mkl_11_3_1 = P(u"mkl 11.3.1-1")
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        mkl_2017_0_1_2 = P(u"mkl 2017.0.1-2")

        numpy_1_10_4 = P(u"numpy 1.10.4-1; depends (mkl ^= 11.3.1)")

        scipy_0_17_1 = P(
            u"scipy 0.17.1-1; depends (mkl ^= 11.3.1, numpy ^= 1.10.4)")

        gnureadline_6_3 = P(u"gnureadline 6.3-1")

        # gnureadline is not available in the remote repository
        self.repository.update([
            mkl_11_3_1, mkl_2017_0_1_1, mkl_2017_0_1_2, numpy_1_10_4,
            scipy_0_17_1
        ])
        self.installed_repository.update(
            [mkl_11_3_1, numpy_1_10_4, scipy_0_17_1])
        self.installed_repository.update([gnureadline_6_3])

        # When/Then
        request = Request()
        request.upgrade()

        with self.assertRaises(SatisfiabilityError):
            self.resolve(request)
Beispiel #5
0
    def test_upgrade_fail(self):
        # Given
        mkl_11_3_1 = P(u"mkl 11.3.1-1")
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        mkl_2017_0_1_2 = P(u"mkl 2017.0.1-2")

        numpy_1_10_4 = P(u"numpy 1.10.4-1; depends (mkl ^= 11.3.1)")

        scipy_0_17_1 = P(
            u"scipy 0.17.1-1; depends (mkl ^= 11.3.1, numpy ^= 1.10.4)")

        self.repository.update([
            mkl_11_3_1, mkl_2017_0_1_1, mkl_2017_0_1_2, numpy_1_10_4,
            scipy_0_17_1
        ])
        self.installed_repository.update(
            [mkl_11_3_1, numpy_1_10_4, scipy_0_17_1])

        r_hint_pretty_string = textwrap.dedent(u"""\
            The following jobs are conflicting:
                install mkl == 2017.0.1-2
                install numpy == 1.10.4-1""")

        # When/Then
        request = Request()
        request.upgrade()

        with self.assertRaises(SatisfiabilityErrorWithHint) as ctx:
            self.resolve_with_hint(request)

        self.assertMultiLineEqual(ctx.exception.hint_pretty_string,
                                  r_hint_pretty_string)
def requirements_are_satisfiable(packages, requirements, modifiers=None):
    """ Determine if the `requirements` can be satisfied together.

    Parameters
    ----------
    packages : iterable of PackageMetadata
        The packages available to draw from when satisfying requirements.
    requirements : list of Requirement
        The requirements used to identify relevent packages.
    modifiers : ConstraintModifiers, optional
        If not None, modify requirements before resolving packages.

    Returns
    -------
    bool
        Return True if the `requirements` can be satisfied by the `packages`.
    """
    modifiers = modifiers or ConstraintModifiers()
    Result = collections.namedtuple("Result", "is_satisfiable message")

    request = Request(modifiers=modifiers)
    for requirement in requirements:
        request.install(requirement)
    repositories = (Repository(packages),)
    pool = Pool(repositories, modifiers=modifiers)

    try:
        DependencySolver(pool, repositories, []).solve(request)
        return Result(is_satisfiable=True, message="")
    except SatisfiabilityError as e:
        return Result(
            is_satisfiable=False, message=e.unsat.to_string(pool=pool)
        )
Beispiel #7
0
    def test_simple_dependency(self):
        # Given
        mkl = self.package_factory(u"mkl 10.3-1")
        libgfortran = self.package_factory(u"libgfortran 3.0.0-2")
        numpy = self.package_factory(
            u"numpy 1.9.2-1; depends (mkl == 10.3-1, libgfortran ^= 3.0.0)")

        r_operations = [
            # libgfortran sorts before mkl
            InstallOperation(libgfortran),
            InstallOperation(mkl),
            InstallOperation(numpy),
        ]

        self.repository.add_package(mkl)
        self.repository.add_package(libgfortran)
        self.repository.add_package(numpy)

        request = Request()
        request.install(R("numpy"))

        # When
        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
Beispiel #8
0
    def test_up_to_date_package_choices(self):
        # Given
        packages = u"""
            envisage 4.7.2-1; depends (apptools ^= 4.4.0, traits ^= 5.1.1)
            apptools 4.4.0-12; depends (traitsui ^= 6.0.0)
            apptools 4.4.0-14; depends (traitsui ^= 6.1.1)
            traitsui 6.0.0-3; depends (traits ^= 5.1.0)
            traitsui 6.0.0-4; depends (traits ^= 5.1.1)
            traitsui 6.1.1-1; depends (traits ^= 5.1.1)
            traits 5.1.0-1
            traits 5.1.1-1
        """
        for package in packages.strip().splitlines():
            self.repository.add_package(P(package.strip()))

        # When
        request = Request()
        request.install(R("envisage"))
        transaction = self.resolve(request)
        packages = {
            operation.package.name: str(operation.package.version)
            for operation in transaction.operations
        }

        # Then
        expected_packages = {
            "traits": "5.1.1-1",
            "traitsui": "6.1.1-1",
            "apptools": "4.4.0-14",
            "envisage": "4.7.2-1",
        }
        self.assertEqual(packages, expected_packages)
Beispiel #9
0
    def test_direct_dependency_conflict(self):
        # Given
        mkl_11_3_1 = P(u"mkl 11.3.1-1")
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        numpy_1_11_3 = P(u"numpy 1.11.3-1; depends (mkl ^= 2017.0.1)")
        scipy_0_18_1 = P(u"scipy 0.18.1-1; depends (mkl ^= 2017.0.1, numpy ^= 1.11.3)")

        self.repository.update([
            mkl_11_3_1, mkl_2017_0_1_1, numpy_1_11_3, scipy_0_18_1,
        ])

        request = Request()
        request.install(R(u"scipy >= 0.18.0"))
        request.install(R(u"numpy >= 1.10.0"))
        request.install(R(u"mkl < 12"))  # MKL < 12 conflicts with scipy >= 0.18.0

        r_hint_pretty_string = textwrap.dedent(u"""\
            The following jobs are conflicting:
                install numpy >= 1.10.0-0
                install mkl < 12-0"""
        )


        # When/Then
        with self.assertRaises(SatisfiabilityErrorWithHint) as ctx:
            self.resolve_with_hint(request)

        self.assertMultiLineEqual(
            ctx.exception.hint_pretty_string, r_hint_pretty_string)
Beispiel #10
0
    def test_upgrade_no_candidate(self):
        # Given
        mkl_11_3_1 = P(u"mkl 11.3.1-1")
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        mkl_2017_0_1_2 = P(u"mkl 2017.0.1-2")

        numpy_1_10_4 = P(u"numpy 1.10.4-1; depends (mkl ^= 11.3.1)")

        scipy_0_17_1 = P(u"scipy 0.17.1-1; depends (mkl ^= 11.3.1, numpy ^= 1.10.4)")

        gnureadline_6_3 = P(u"gnureadline 6.3-1")

        # gnureadline is not available in the remote repository
        self.repository.update([
            mkl_11_3_1, mkl_2017_0_1_1, mkl_2017_0_1_2, numpy_1_10_4,
            scipy_0_17_1
        ])
        self.installed_repository.update([mkl_11_3_1, numpy_1_10_4, scipy_0_17_1])
        self.installed_repository.update([gnureadline_6_3])

        # When/Then
        request = Request()
        request.upgrade()

        with self.assertRaises(SatisfiabilityError):
            self.resolve(request)
Beispiel #11
0
    def _solve(self, top_core, flags={}, only_matching_vlnv=False):
        def eq_vln(this, that):
            return \
                this.vendor  == that.vendor and \
                this.library == that.library and \
                this.name    == that.name

        repo = Repository()
        _flags = flags.copy()
        cores = [x['core'] for x in self._cores.values()]
        for core in cores:
            if only_matching_vlnv:
                if not eq_vln(core.name, top_core):
                    continue

            package_str = "{} {}-{}".format(self._package_name(core.name),
                                            core.name.version,
                                            core.name.revision)
            if not only_matching_vlnv:
                _flags['is_toplevel'] = (core.name == top_core)
                _depends = core.get_depends(_flags)
                if _depends:
                    _s = "; depends ( {} )"
                    package_str += _s.format(self._parse_depend(_depends))
            parser = PrettyPackageStringParser(EnpkgVersion.from_string)

            package = parser.parse_to_package(package_str)
            package.core = core

            repo.add_package(package)

        request = Request()
        _top_dep = "{} {} {}".format(self._package_name(top_core),
                                     top_core.relation,
                                     self._package_version(top_core))
        requirement = Requirement._from_string(_top_dep)
        request.install(requirement)
        installed_repository = Repository()
        pool = Pool([repo])
        pool.add_repository(installed_repository)
        solver = DependencySolver(pool, [repo], installed_repository)

        try:
            transaction = solver.solve(request)
        except SatisfiabilityError as e:
            raise DependencyError(top_core.name,
                                  msg=e.unsat.to_string(pool))
        except NoPackageFound as e:
            raise DependencyError(top_core.name)

        return [op.package.core for op in transaction.operations]
Beispiel #12
0
    def test_missing_direct_dependency_fails(self):
        # Given
        numpy192 = self.package_factory(u"numpy 1.9.2-1")
        numpy200 = self.package_factory(u"numpy 2.0.0-1; depends (missing)")

        self.repository.add_package(numpy192)
        self.repository.add_package(numpy200)

        # When
        request = Request()
        request.install(R("numpy >= 2.0"))

        # Then
        with self.assertRaises(SatisfiabilityError):
            self.resolve(request)
Beispiel #13
0
    def test_simple_install(self):
        # Given
        mkl = self.package_factory(u"mkl 10.3-1")
        self.repository.add_package(mkl)

        r_operations = [InstallOperation(mkl)]

        request = Request()
        request.install(R("mkl"))

        # When
        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
Beispiel #14
0
    def test_simple_install(self):
        # Given
        mkl = self.package_factory(u"mkl 10.3-1")
        self.repository.add_package(mkl)

        r_operations = [InstallOperation(mkl)]

        request = Request()
        request.install(R("mkl"))

        # When
        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
Beispiel #15
0
    def test_missing_direct_dependency_fails(self):
        # Given
        numpy192 = self.package_factory(u"numpy 1.9.2-1")
        numpy200 = self.package_factory(u"numpy 2.0.0-1; depends (missing)")

        self.repository.add_package(numpy192)
        self.repository.add_package(numpy200)

        # When
        request = Request()
        request.install(R("numpy >= 2.0"))

        # Then
        with self.assertRaises(SatisfiabilityError):
            self.resolve(request)
Beispiel #16
0
    def from_yaml(cls, file_or_filename):
        if isinstance(file_or_filename, six.string_types):
            with open(file_or_filename) as fp:
                data = yaml.load(fp, Loader=_UnicodeLoader)
        else:
            data = yaml.load(file_or_filename, Loader=_UnicodeLoader)

        scenario_requests = data.get("request", [])

        marked = list(data.get("marked", []))

        request = Request()

        for kind, values in data.get("modifiers", {}).items():
            for value in values:
                getattr(request, kind)(value)

        update_all = False

        for s_request in scenario_requests:
            kind = s_request["operation"]
            if kind == 'update_all':
                update_all = True
                continue
            requirement = Requirement._from_string(s_request["requirement"])
            try:
                marked.remove(requirement.name)
            except ValueError:
                pass
            getattr(request, kind)(requirement)

        if update_all:
            request_job = request.hard_update
        else:
            request_job = request.install

        for package_str in marked:
            request_job(Requirement._from_string(package_str))

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

        operations = cls._operations_from_transaction_list(
            data.get("transaction", []))

        pretty_operations = cls._operations_from_transaction_list(
            data.get("pretty_transaction", []))

        failure = data.get('failure')

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

        return cls(packages, [remote_repository(data, packages)],
                   installed_repository(data, packages),
                   request,
                   decisions,
                   operations,
                   pretty_operations,
                   failure=failure)
 def callback(jobs):
     callback_request = Request(modifiers=request.modifiers)
     for job in jobs:
         callback_request.jobs.append(job)
     try:
         self.solve(callback_request)
         return True
     except SatisfiabilityError:
         return False
Beispiel #18
0
    def test_strange_key_error_bug_on_failure(self):
        # Given
        mkl = self.package_factory(u'MKL 10.3-1')
        libgfortran = self.package_factory(u'libgfortran 3.0.0-2')
        numpy192 = self.package_factory(
            u"numpy 1.9.2-1; depends (libgfortran ^= 3.0.0, MKL == 10.3-1)")
        numpy200 = self.package_factory(
            u"numpy 2.0.0-1; depends (nonexistent)")
        request = Request()

        # When
        for pkg in (mkl, libgfortran, numpy192, numpy200):
            self.repository.add_package(pkg)
        request.install(R("numpy >= 2.0"))

        # Then
        with self.assertRaises(SatisfiabilityError):
            self.resolve(request)
Beispiel #19
0
    def test_missing_dependency_strict(self):
        # Given
        mkl = self.package_factory(u'MKL 10.3-1')
        libgfortran = self.package_factory(u'libgfortran 3.0.0-2')
        numpy192 = self.package_factory(
            u"numpy 1.9.2-1; depends (libgfortran ^= 3.0.0, MKL == 10.3-1)")
        numpy200 = self.package_factory(
            u"numpy 2.0.0-1; depends (nonexistent)")
        request = Request()

        # When
        for pkg in (mkl, libgfortran, numpy192, numpy200):
            self.repository.add_package(pkg)
        request.install(R("numpy == 2.0.0-1"))

        # Then
        with self.assertRaises(MissingInstallRequires):
            self.resolve(request, strict=True)
Beispiel #20
0
    def test_strange_key_error_bug_on_failure(self):
        # Given
        mkl = self.package_factory(u'MKL 10.3-1')
        libgfortran = self.package_factory(u'libgfortran 3.0.0-2')
        numpy192 = self.package_factory(
            u"numpy 1.9.2-1; depends (libgfortran ^= 3.0.0, MKL == 10.3-1)")
        numpy200 = self.package_factory(
            u"numpy 2.0.0-1; depends (nonexistent)")
        request = Request()

        # When
        for pkg in (mkl, libgfortran, numpy192, numpy200):
            self.repository.add_package(pkg)
        request.install(R("numpy >= 2.0"))

        # Then
        with self.assertRaises(SatisfiabilityError):
            self.resolve(request)
Beispiel #21
0
    def test_missing_dependency_strict(self):
        # Given
        mkl = self.package_factory(u'MKL 10.3-1')
        libgfortran = self.package_factory(u'libgfortran 3.0.0-2')
        numpy192 = self.package_factory(
            u"numpy 1.9.2-1; depends (libgfortran ^= 3.0.0, MKL == 10.3-1)")
        numpy200 = self.package_factory(
            u"numpy 2.0.0-1; depends (nonexistent)")
        request = Request()

        # When
        for pkg in (mkl, libgfortran, numpy192, numpy200):
            self.repository.add_package(pkg)
        request.install(R("numpy == 2.0.0-1"))

        # Then
        with self.assertRaises(MissingInstallRequires):
            self.resolve(request, strict=True)
Beispiel #22
0
    def solve(self, top_core, tool):
        repo = Repository()
        for core in self._cores.values():
            package_str = "{} {}-{}".format(self._package_name(core.name),
                                            core.name.version,
                                            core.name.revision)
            _depends = core.depend
            try:
                _depends += getattr(core, tool).depend
            except (AttributeError, KeyError):
                pass

            if _depends:
                _s = "; depends ( {} )"
                package_str += _s.format(self._parse_depend(_depends))
            parser = PrettyPackageStringParser(EnpkgVersion.from_string)

            package = parser.parse_to_package(package_str)
            package.core = core

            repo.add_package(package)

        request = Request()
        _top_dep = "{} {} {}".format(self._package_name(top_core),
                                     top_core.relation,
                                     self._package_version(top_core))
        requirement = Requirement._from_string(_top_dep)
        request.install(requirement)
        installed_repository = Repository()
        pool = Pool([repo])
        pool.add_repository(installed_repository)
        solver = DependencySolver(pool, repo, installed_repository)

        try:
            transaction = solver.solve(request)
        except SatisfiabilityError as e:
            msg = "UNSATISFIABLE: {}"
            raise RuntimeError(msg.format(e.unsat.to_string(pool)))
        except NoPackageFound as e:
            raise DependencyError(top_core.name)

        return [op.package.core for op in transaction.operations]
Beispiel #23
0
def generate_rules_for_requirement(pool, requirement, installed_map=None):
    """Generate CNF rules for a requirement.

    Parameters
    ----------
    pool: Pool
        Package constraints.
    requirement: Requirement
        Package to be installed.

    Returns
    -------
    rules: list
        Package rules describing the given scenario.
    """
    request = Request()
    request.install(requirement)

    rules_generator = RulesGenerator(pool, request, installed_map)
    rules = list(rules_generator.iter_rules())
    return rules
Beispiel #24
0
    def test_direct_dependency_conflict(self):
        # Given
        mkl_11_3_1 = P(u"mkl 11.3.1-1")
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        numpy_1_11_3 = P(u"numpy 1.11.3-1; depends (mkl ^= 2017.0.1)")
        scipy_0_18_1 = P(
            u"scipy 0.18.1-1; depends (mkl ^= 2017.0.1, numpy ^= 1.11.3)")

        self.repository.update([
            mkl_11_3_1,
            mkl_2017_0_1_1,
            numpy_1_11_3,
            scipy_0_18_1,
        ])

        request = Request()
        request.install(R(u"scipy >= 0.18.0"))
        request.install(R(u"numpy >= 1.10.0"))
        request.install(
            R(u"mkl < 12"))  # MKL < 12 conflicts with scipy >= 0.18.0

        r_hint_pretty_string = textwrap.dedent(u"""\
            The following jobs are conflicting:
                install numpy >= 1.10.0-0
                install mkl < 12-0""")

        # When/Then
        with self.assertRaises(SatisfiabilityErrorWithHint) as ctx:
            self.resolve_with_hint(request)

        self.assertMultiLineEqual(ctx.exception.hint_pretty_string,
                                  r_hint_pretty_string)
Beispiel #25
0
    def test_already_installed(self):
        # Given
        mkl1 = self.package_factory(u"mkl 10.3-1")
        mkl2 = self.package_factory(u"mkl 10.3-2")

        r_operations = []

        self.repository.add_package(mkl1)
        self.repository.add_package(mkl2)
        self.installed_repository.add_package(mkl1)

        # When
        request = Request()
        request.install(R("mkl"))

        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)

        # Given
        r_operations = [
            UpdateOperation(mkl2, mkl1),
        ]

        # When
        request = Request()
        request.install(R("mkl > 10.3-1"))

        # When
        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
Beispiel #26
0
    def test_upgrade_fail(self):
        # Given
        mkl_11_3_1 = P(u"mkl 11.3.1-1")
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        mkl_2017_0_1_2 = P(u"mkl 2017.0.1-2")

        numpy_1_10_4 = P(u"numpy 1.10.4-1; depends (mkl ^= 11.3.1)")

        scipy_0_17_1 = P(u"scipy 0.17.1-1; depends (mkl ^= 11.3.1, numpy ^= 1.10.4)")

        self.repository.update([
            mkl_11_3_1, mkl_2017_0_1_1, mkl_2017_0_1_2, numpy_1_10_4,
            scipy_0_17_1
        ])
        self.installed_repository.update([mkl_11_3_1, numpy_1_10_4, scipy_0_17_1])

        # When/Then
        request = Request()
        request.upgrade()

        with self.assertRaises(SatisfiabilityError):
            self.resolve(request)
def satisfy_requirements(packages, requirements, modifiers=None):
    """ Find a collection of packages that satisfy the requirements.

    Parameters
    ----------
    packages : iterable of PackageMetadata
        The packages available to draw from when satisfying requirements.
    requirements : list of Requirement
        The requirements used to identify relevent packages.
    modifiers : ConstraintModifiers, optional
        If not None, modify requirements before resolving packages.

    Returns
    -------
    tuple of PackageMetadata
        Return a tuple of packages that together satisfy all of the
        `requirements`. The packages are in topological order.

    Raises
    ------
    SatisfiabilityError
        If the `requirements` cannot be satisfied using the `packages`.
    """
    request = Request(modifiers=modifiers)
    for requirement in requirements:
        request.install(requirement)
    repositories = (Repository(packages),)
    pool = Pool(repositories, modifiers=modifiers)
    transaction = DependencySolver(pool, repositories, []).solve(request)
    msg = ("""
        Unexpected operation in the transaction. This should never occur.
        Something in simplesat is broken.
        {!r}""")
    for op in transaction.operations:
        # Our installed repository was empty so everything should be an install
        # operation
        assert isinstance(op, InstallOperation), msg.format(op)
    packages = tuple(op.package for op in transaction.operations)
    return packages
Beispiel #28
0
    def test_multiple_installs(self):
        # Given
        mkl = self.package_factory(u"mkl 10.3-1")
        libgfortran = self.package_factory(u"libgfortran 3.0.0-2")

        r_operations = [
            InstallOperation(mkl),
            InstallOperation(libgfortran),
        ]

        self.repository.add_package(mkl)
        self.repository.add_package(libgfortran)

        request = Request()
        request.install(R("mkl"))
        request.install(R("libgfortran"))

        # When
        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
Beispiel #29
0
    def test_upgrade_simple(self):
        # Given
        mkl_11_3_1 = P(u"mkl 11.3.1-1")
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        mkl_2017_0_1_2 = P(u"mkl 2017.0.1-2")

        numpy_1_10_4 = P(u"numpy 1.10.4-1; depends (mkl ^= 11.3.1)")
        numpy_1_11_3 = P(u"numpy 1.11.3-1; depends (mkl ^= 2017.0.1)")

        scipy_0_17_1 = P(
            u"scipy 0.17.1-1; depends (mkl ^= 11.3.1, numpy ^= 1.10.4)")
        scipy_0_18_1 = P(
            u"scipy 0.18.1-1; depends (mkl ^= 2017.0.1, numpy ^= 1.11.3)")

        self.repository.update([
            mkl_11_3_1, mkl_2017_0_1_1, mkl_2017_0_1_2, numpy_1_10_4,
            numpy_1_11_3, scipy_0_17_1, scipy_0_18_1
        ])
        self.installed_repository.update(
            [mkl_11_3_1, numpy_1_10_4, scipy_0_17_1])

        r_operations = [
            RemoveOperation(scipy_0_17_1),
            RemoveOperation(numpy_1_10_4),
            RemoveOperation(mkl_11_3_1),
            InstallOperation(mkl_2017_0_1_2),
            InstallOperation(numpy_1_11_3),
            InstallOperation(scipy_0_18_1),
        ]

        # When
        request = Request()
        request.upgrade()

        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
Beispiel #30
0
def generate_rules_for_requirement(pool, requirement, installed_map=None):
    """Generate CNF rules for a requirement.

    Parameters
    ----------
    pool : Pool
        A Pool of Repositories to use when fulfilling the requirement.
    requirement : Requirement
        The description of the package to be installed.

    Returns
    -------
    rules : list
        Package rules describing the given scenario.

    """
    request = Request()
    request.install(requirement)

    rules_generator = RulesGenerator(
        pool, request, installed_map=installed_map)
    rules = list(rules_generator.iter_rules())
    return rules
Beispiel #31
0
def generate_rules_for_requirement(pool, requirement, installed_map=None):
    """Generate CNF rules for a requirement.

    Parameters
    ----------
    pool : Pool
        A Pool of Repositories to use when fulfilling the requirement.
    requirement : Requirement
        The description of the package to be installed.

    Returns
    -------
    rules : list
        Package rules describing the given scenario.

    """
    request = Request()
    request.install(requirement)

    rules_generator = RulesGenerator(pool,
                                     request,
                                     installed_map=installed_map)
    rules = list(rules_generator.iter_rules())
    return rules
Beispiel #32
0
    def test_no_conflict(self):
        # Given
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        numpy_1_11_3 = P(u"numpy 1.11.3-1; depends (mkl ^= 2017.0.1)")
        scipy_0_18_1 = P(
            u"scipy 0.18.1-1; depends (mkl ^= 2017.0.1, numpy ^= 1.11.3)")

        r_operations = [
            InstallOperation(mkl_2017_0_1_1),
            InstallOperation(numpy_1_11_3),
            InstallOperation(scipy_0_18_1),
        ]

        self.repository.update([mkl_2017_0_1_1, numpy_1_11_3, scipy_0_18_1])

        request = Request()
        request.install(R(u"scipy >= 0.18.0"))
        request.install(R(u"numpy >= 1.10.0"))

        # When
        transaction = self.resolve_with_hint(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
Beispiel #33
0
    def test_upgrade_fail(self):
        # Given
        mkl_11_3_1 = P(u"mkl 11.3.1-1")
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        mkl_2017_0_1_2 = P(u"mkl 2017.0.1-2")

        numpy_1_10_4 = P(u"numpy 1.10.4-1; depends (mkl ^= 11.3.1)")

        scipy_0_17_1 = P(
            u"scipy 0.17.1-1; depends (mkl ^= 11.3.1, numpy ^= 1.10.4)")

        self.repository.update([
            mkl_11_3_1, mkl_2017_0_1_1, mkl_2017_0_1_2, numpy_1_10_4,
            scipy_0_17_1
        ])
        self.installed_repository.update(
            [mkl_11_3_1, numpy_1_10_4, scipy_0_17_1])

        # When/Then
        request = Request()
        request.upgrade()

        with self.assertRaises(SatisfiabilityError):
            self.resolve(request)
Beispiel #34
0
    def test_no_conflict(self):
        # Given
        mkl_2017_0_1_1 = P(u"mkl 2017.0.1-1")
        numpy_1_11_3 = P(u"numpy 1.11.3-1; depends (mkl ^= 2017.0.1)")
        scipy_0_18_1 = P(u"scipy 0.18.1-1; depends (mkl ^= 2017.0.1, numpy ^= 1.11.3)")

        r_operations = [
            InstallOperation(mkl_2017_0_1_1),
            InstallOperation(numpy_1_11_3),
            InstallOperation(scipy_0_18_1),
        ]

        self.repository.update([mkl_2017_0_1_1, numpy_1_11_3, scipy_0_18_1])

        request = Request()
        request.install(R(u"scipy >= 0.18.0"))
        request.install(R(u"numpy >= 1.10.0"))


        # When
        transaction = self.resolve_with_hint(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
Beispiel #35
0
    def test_modification_what_provides(self):
        # Given
        repository = Repository(self.packages_from_definition(
            "numpy 1.8.1-1; depends (MKL == 10.3-1)"))
        request = Request()
        request.modifiers.allow_newer.add('numpy')

        # When
        pool = Pool([repository], modifiers=request.modifiers)
        requirement = InstallRequirement._from_string('numpy ^= 1.7')
        numpy_181 = list(repository)[0]
        result = pool.what_provides(requirement)
        expected = [numpy_181]

        # Then
        self.assertEqual(result, expected)
Beispiel #36
0
    def test_already_installed(self):
        # Given
        mkl1 = self.package_factory(u"mkl 10.3-1")
        mkl2 = self.package_factory(u"mkl 10.3-2")

        r_operations = []

        self.repository.add_package(mkl1)
        self.repository.add_package(mkl2)
        self.installed_repository.add_package(mkl1)

        # When
        request = Request()
        request.install(R("mkl"))

        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)

        # Given
        r_operations = [
            RemoveOperation(mkl1),
            InstallOperation(mkl2),
        ]
        r_pretty_operations = [
            UpdateOperation(mkl2, mkl1),
        ]

        # When
        request = Request()
        request.install(R("mkl > 10.3-1"))

        # When
        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
        self.assertEqualOperations(transaction.pretty_operations,
                                   r_pretty_operations)
Beispiel #37
0
    def test_multiple_installs(self):
        # Given
        mkl = self.package_factory(u"mkl 10.3-1")
        libgfortran = self.package_factory(u"libgfortran 3.0.0-2")

        r_operations = [
            InstallOperation(libgfortran),
            InstallOperation(mkl),
        ]

        self.repository.add_package(mkl)
        self.repository.add_package(libgfortran)

        request = Request()
        request.install(R("mkl"))
        request.install(R("libgfortran"))

        # When
        transaction = self.resolve(request)

        # Then
        self.assertEqualOperations(transaction.operations, r_operations)
Beispiel #38
0
    def _solve(self, top_core, flags={}, only_matching_vlnv=False):
        def eq_vln(this, that):
            return (
                this.vendor == that.vendor
                and this.library == that.library
                and this.name == that.name
            )

        # Try to return a cached result
        solver_cache_key = (top_core, self._hash_flags_dict(flags), only_matching_vlnv)
        cached_solution = self._solver_cache_lookup(solver_cache_key)
        if cached_solution:
            return cached_solution

        repo = Repository()
        _flags = flags.copy()
        cores = [x["core"] for x in self._cores.values()]
        for core in cores:
            if only_matching_vlnv:
                if not eq_vln(core.name, top_core):
                    continue

            package_str = "{} {}-{}".format(
                self._package_name(core.name), core.name.version, core.name.revision
            )
            if not only_matching_vlnv:
                _flags["is_toplevel"] = core.name == top_core
                _depends = core.get_depends(_flags)
                if _depends:
                    _s = "; depends ( {} )"
                    package_str += _s.format(self._parse_depend(_depends))
            parser = PrettyPackageStringParser(EnpkgVersion.from_string)

            package = parser.parse_to_package(package_str)
            package.core = core

            repo.add_package(package)

        request = Request()
        simplevlnvs = top_core.simpleVLNVs()
        for sv in simplevlnvs:
            _top_dep = "{} {} {}".format(
                self._package_name(top_core),
                top_core.relation,
                self._package_version(top_core),
            )
            request.install(Requirement._from_string(_top_dep))

        installed_repository = Repository()
        pool = Pool([repo])
        pool.add_repository(installed_repository)
        solver = DependencySolver(pool, [repo], installed_repository)

        try:
            transaction = solver.solve(request)
        except SatisfiabilityError as e:
            raise DependencyError(top_core.name, msg=e.unsat.to_string(pool))
        except NoPackageFound as e:
            raise DependencyError(top_core.name)

        objdict = {}
        depdict = {}
        if len(transaction.operations) > 1:
            for op in transaction.operations:
                objdict[op.package._name] = str(op.package.core.name)
                depdict[str(op.package.core.name)] = [
                    objdict[n[0]] for n in op.package.install_requires
                ]
                op.package.core.direct_deps = [
                    objdict[n[0]] for n in op.package.install_requires
                ]
        result = [op.package.core for op in transaction.operations]

        # Cache the solution for further lookups
        self._solver_cache_store(solver_cache_key, result)

        return result