Example #1
0
def get_latest_package(name, range_=None, paths=None, error=False):
    """Get the latest package for a given package name.

    Args:
        name (str): Package name.
        range_ (`VersionRange`): Version range to search within.
        paths (list of str, optional): paths to search for package families,
            defaults to `config.packages_path`.
        error (bool): If True, raise an error if no package is found.

    Returns:
        `Package` object, or None if no package is found.
    """
    it = iter_packages(name, range_=range_, paths=paths)
    try:
        return max(it, key=lambda x: x.version)
    except ValueError:  # empty sequence
        if error:
            raise PackageFamilyNotFoundError("No such package family %r" % name)
        return None
Example #2
0
def get_reverse_dependency_tree(package_name,
                                depth=None,
                                paths=None,
                                build_requires=False,
                                private_build_requires=False):
    """Find packages that depend on the given package.

    This is a reverse dependency lookup. A tree is constructed, showing what
    packages depend on the given package, with an optional depth limit. A
    resolve does not occur. Only the latest version of each package is used,
    and requirements from all variants of that package are used.

    Args:
        package_name (str): Name of the package depended on.
        depth (int): Tree depth limit, unlimited if None.
        paths (list of str): paths to search for packages, defaults to
            `config.packages_path`.
        build_requires (bool): If True, includes packages' build_requires.
        private_build_requires (bool): If True, include `package_name`'s
            private_build_requires.

    Returns:
        A 2-tuple:
        - (list of list of str): Lists of package names, where each list is a
          single depth in the tree. The first list is always [`package_name`].
        - `pygraph.digraph` object, where nodes are package names, and
          `package_name` is always the leaf node.
    """
    pkgs_list = [[package_name]]
    g = digraph()
    g.add_node(package_name)

    # build reverse lookup
    it = iter_package_families(paths)
    package_names = set(x.name for x in it)
    if package_name not in package_names:
        raise PackageFamilyNotFoundError("No such package family %r" %
                                         package_name)

    if depth == 0:
        return pkgs_list, g

    bar = ProgressBar("Searching", len(package_names))
    lookup = defaultdict(set)

    for i, package_name_ in enumerate(package_names):
        it = iter_packages(name=package_name_, paths=paths)
        packages = list(it)
        if not packages:
            continue

        pkg = max(packages, key=lambda x: x.version)
        requires = []

        for variant in pkg.iter_variants():
            pbr = (private_build_requires and pkg.name == package_name)

            requires += variant.get_requires(build_requires=build_requires,
                                             private_build_requires=pbr)

        for req in requires:
            if not req.conflict:
                lookup[req.name].add(package_name_)

        bar.next()

    bar.finish()

    # perform traversal
    n = 0
    consumed = set([package_name])
    working_set = set([package_name])

    node_color = "#F6F6F6"
    node_fontsize = 10
    node_attrs = [("fillcolor", node_color), ("style", "filled"),
                  ("fontsize", node_fontsize)]

    while working_set and (depth is None or n < depth):
        working_set_ = set()

        for child in working_set:
            parents = lookup[child] - consumed
            working_set_.update(parents)
            consumed.update(parents)

            for parent in parents:
                g.add_node(parent, attrs=node_attrs)
                g.add_edge((parent, child))

        if working_set_:
            pkgs_list.append(sorted(list(working_set_)))

        working_set = working_set_
        n += 1

    return pkgs_list, g