예제 #1
0
 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_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)))
예제 #4
0
    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)))
예제 #5
0
    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))
        )
예제 #6
0
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
예제 #7
0
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