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)
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 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)
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)
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) )
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)
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)
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)
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)
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]
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)
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)
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
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)
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)
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]
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
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)
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)
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
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)
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)
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
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
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)
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 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)
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)
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)
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)
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