def test_find_with_specified_version(self): index = Index() p1 = gen_package(idx=1, version=1) p2 = gen_package(idx=1, version=2) index.add(p1) index.add(p2) self.assertItemsEqual([p1], index.find_all(p1.name, objects.VersionRange("=", p1.version))) self.assertItemsEqual([p2], index.find_all(p2.name, objects.VersionRange("=", p2.version)))
def test_add(self): index = Index() package1 = gen_package(version=1) index.add(package1) self.assertIn(package1.name, index.packages) self.assertEqual([(1, package1)], list(index.packages[package1.name].items())) package2 = gen_package(version=2) index.add(package2) self.assertEqual(1, len(index.packages)) self.assertEqual([(1, package1), (2, package2)], list(index.packages[package1.name].items()))
def test_find_obsolete(self): index = Index() p1 = gen_package(version=1) index.add(p1) self.assertIs( p1, index.find("obsoletes1", objects.VersionRange("le", 2)) ) self.assertIsNone( index.find("obsoletes1", objects.VersionRange("gt", 2)) )
def test_find_provides(self): index = Index() p1 = gen_package(version=1) p2 = gen_package(version=2) index.add(p1) index.add(p2) self.assertIs( p2, index.find("provides1", objects.VersionRange("ge", 2)) ) self.assertIsNone( index.find("provides1", objects.VersionRange("gt", 2)) )
def test_find_accurate(self): index = Index() p1 = gen_package(version=1) p2 = gen_package(version=2) index.add(p1) index.add(p2) self.assertIs( p1, index.find("package1", objects.VersionRange("eq", 1)) ) self.assertIsNone( index.find("package1", objects.VersionRange("eq", 3)) )
def test_add(self): index = Index() index.add(gen_package(version=1)) self.assertIn("package1", index.packages) self.assertIn(1, index.packages["package1"]) self.assertIn("obsoletes1", index.obsoletes) self.assertIn("provides1", index.provides) index.add(gen_package(version=2)) self.assertEqual(1, len(index.packages)) self.assertIn(1, index.packages["package1"]) self.assertIn(2, index.packages["package1"]) self.assertEqual(1, len(index.obsoletes)) self.assertEqual(1, len(index.provides))
def test_find_newest_package(self): index = Index() p1 = gen_package(idx=1, version=2) p2 = gen_package(idx=2, version=2) p2.obsoletes.append( gen_relation(p1.name, ["lt", p1.version]) ) index.add(p1) index.add(p2) self.assertIs( p1, index.find(p1.name, objects.VersionRange("eq", p1.version)) ) self.assertIs( p2, index.find(p1.name, objects.VersionRange("eq", 1)) )
def test_len(self): index = Index() for i in six.moves.range(3): index.add(gen_package(idx=i + 1)) self.assertEqual(3, len(index)) for i in six.moves.range(3): index.add(gen_package(idx=i + 1, version=2)) self.assertEqual(6, len(index)) self.assertEqual(3, len(index.packages)) for i in six.moves.range(3): index.add(gen_package(idx=i + 1, version=2)) self.assertEqual(6, len(index)) self.assertEqual(3, len(index.packages))
def test_find_down_up(self): index = Index() p1 = gen_package(version=1) p2 = gen_package(version=2) index.add(p1) index.add(p2) self.assertEqual([p2], index.find_all(p1.name, objects.VersionRange(">=", 2))) self.assertEqual([p2], index.find_all(p1.name, objects.VersionRange(">", 1))) self.assertEqual([], index.find_all(p1.name, objects.VersionRange(">", 2)))
def test_find_with_specified_version(self): index = Index() p1 = gen_package(idx=1, version=1) p2 = gen_package(idx=1, version=2) index.add(p1) index.add(p2) self.assertItemsEqual([p1], index.find_all( p1.name, objects.VersionRange("=", p1.version))) self.assertItemsEqual([p2], index.find_all( p2.name, objects.VersionRange("=", p2.version)))
def test_find_all(self): index = Index() p11 = gen_package(idx=1, version=1) p12 = gen_package(idx=1, version=2) p21 = gen_package(idx=2, version=1) p22 = gen_package(idx=2, version=2) index.add(p11) index.add(p12) index.add(p21) index.add(p22) self.assertItemsEqual( [p11, p12], index.find_all("package1", objects.VersionRange()) ) self.assertItemsEqual( [p21, p22], index.find_all("package2", objects.VersionRange("le", 2)) )
def test_find_top_down(self): index = Index() p1 = gen_package(version=1) p2 = gen_package(version=2) index.add(p1) index.add(p2) self.assertIs( p2, index.find("package1", objects.VersionRange("le", 2)) ) self.assertIs( p1, index.find("package1", objects.VersionRange("lt", 2)) ) self.assertIsNone( index.find("package1", objects.VersionRange("lt", 1)) )
def __init__(self): super(PackagesTree, self).__init__() self.mandatory_packages = [] self.packages = Index() self.provides = defaultdict(dict) self.obsoletes = defaultdict(dict)
class PackagesTree(object): """Helper class to deal with dependency graph.""" def __init__(self): super(PackagesTree, self).__init__() self.mandatory_packages = [] self.packages = Index() self.provides = defaultdict(dict) self.obsoletes = defaultdict(dict) def add(self, package): # store all mandatory packages in separated list for quick access if package.mandatory: self.mandatory_packages.append(package) self.packages.add(package) key = package.name, package.version for obsolete in package.obsoletes: self.obsoletes[obsolete.name][key] = obsolete for provide in package.provides: self.provides[provide.name][key] = provide def find(self, name, version_range): """Finds the package by name and range of versions. :param name: the package`s name. :param version_range: the range of versions. :return: the package if it is found, otherwise None """ candidates = self.find_all(name, version_range) if len(candidates) > 0: return candidates[-1] return None def find_all(self, name, version_range): """Finds the packages by name and range of versions. :param name: the package`s name. :param version_range: the range of versions. :return: the list of suitable packages """ if name in self.packages: candidates = self.packages.find_all(name, version_range) if len(candidates) > 0: return candidates if name in self.obsoletes: return self._resolve_relation(self.obsoletes[name], version_range) if name in self.provides: return self._resolve_relation(self.provides[name], version_range) return [] def get_unresolved_dependencies(self): """Gets the set of unresolved dependencies. :return: the set of unresolved depends. """ unresolved = set() for pkg in self.packages: for required in pkg.requires: for rel in required: if rel not in unresolved: if self.find(rel.name, rel.version) is not None: break else: unresolved.add(required) return unresolved def _resolve_relation(self, relations, version_range): """Resolve relation according to relations index. :param relations: the index of relations :param version_range: the range of versions :return: package if found, otherwise None """ result = [] for key, candidate in six.iteritems(relations): if version_range.has_intersection(candidate.version): result.extend( self.packages.find_all(key[0], VersionRange('=', key[1]))) result.sort(key=lambda x: x.version) return result
class PackagesTree(object): """Helper class to deal with dependency graph.""" def __init__(self): super(PackagesTree, self).__init__() self.mandatory_packages = [] self.packages = Index() self.provides = defaultdict(dict) self.obsoletes = defaultdict(dict) def add(self, package): # store all mandatory packages in separated list for quick access if package.mandatory: self.mandatory_packages.append(package) self.packages.add(package) key = package.name, package.version for obsolete in package.obsoletes: self.obsoletes[obsolete.name][key] = obsolete for provide in package.provides: self.provides[provide.name][key] = provide def find(self, name, version_range): """Finds the package by name and range of versions. :param name: the package`s name. :param version_range: the range of versions. :return: the package if it is found, otherwise None """ candidates = self.find_all(name, version_range) if len(candidates) > 0: # we return candidates in sorted order, so let's take the highest return candidates[-1] return None def find_all(self, name, version_range): """Finds the packages by name and range of versions. :param name: the package`s name. :param version_range: the range of versions. :return: the list of suitable packages """ candidates = set() # find package by name if name in self.packages: candidates.update(self.packages.find_all(name, version_range)) # find package by provides # in case of rpm: # set(candidates) >= set(provides) if name in self.provides: candidates.update(self._resolve_relation( self.provides[name], version_range) ) if name in self.obsoletes: candidates.update(self._resolve_relation( self.obsoletes[name], version_range) ) return sorted(candidates, key=lambda x: x.version) def get_unresolved_dependencies(self): """Gets the set of unresolved dependencies. :return: the set of unresolved depends. """ unresolved = set() for pkg in self.packages: for required in pkg.requires: for rel in required: if rel not in unresolved: if self.find(rel.name, rel.version) is not None: break else: unresolved.add(required) return unresolved def _resolve_relation(self, relations, version_range): """Resolve relation according to relations index. :param relations: the index of relations :param version_range: the range of versions :return: package if found, otherwise None """ result = [] for key, candidate in six.iteritems(relations): if version_range.has_intersection(candidate.version): result.extend( self.packages.find_all(key[0], VersionRange('=', key[1])) ) # sort related packages ASC result.sort(key=lambda x: x.version) return result