Ejemplo n.º 1
0
def format_dependency_graph(graph: DirectedGraph) -> str:
    """Format dependency graph for output."""
    content = []
    for package in graph.iter_children(None):
        content.append(format_package(graph, package, prefix="",
                                      visited=set()))
    return "".join(content).strip()
Ejemplo n.º 2
0
def format_package(
    graph: DirectedGraph,
    package: Package,
    required: str = "",
    prefix: str = "",
    visited=None,
) -> str:
    """Format one package.

    :param graph: the dependency graph
    :param package: the package instance
    :param required: the version required by its parent
    :param prefix: prefix text for children
    :param visited: the visited package collection
    """
    if visited is None:
        visited = set()
    result = []
    version = (
        stream.red("[ not installed ]")
        if not package.version
        else stream.red(package.version)
        if required
        and required != "Any"
        and not SpecifierSet(required).contains(package.version)
        else stream.yellow(package.version)
    )
    if package.name in visited:
        version = stream.red("[circular]")
    required = f"[ required: {required} ]" if required else ""
    result.append(f"{stream.green(package.name, bold=True)} {version} {required}\n")
    if package.name in visited:
        return "".join(result)
    visited.add(package.name)
    try:
        *children, last = sorted(graph.iter_children(package), key=lambda p: p.name)
    except ValueError:  # No children nodes
        pass
    else:
        for child in children:
            required = str(package.requirements[child.name].specifier or "Any")
            result.append(
                prefix
                + NON_LAST_CHILD
                + format_package(
                    graph, child, required, prefix + NON_LAST_PREFIX, visited.copy()
                )
            )
        required = str(package.requirements[last.name].specifier or "Any")
        result.append(
            prefix
            + LAST_CHILD
            + format_package(
                graph, last, required, prefix + LAST_PREFIX, visited.copy()
            )
        )
    return "".join(result)
Ejemplo n.º 3
0
def format_reverse_dependency_graph(project: Project, graph: DirectedGraph) -> str:
    """Format reverse dependency graph for output."""
    leaf_nodes = sorted(
        (node for node in graph._vertices if not list(graph.iter_children(node))),
        key=lambda p: p.name,
    )
    content = []
    for node in leaf_nodes:
        content.append(format_reverse_package(graph, node, prefix="", visited=set()))
    return "".join(content).strip()
Ejemplo n.º 4
0
def build_dependency_graph(working_set: WorkingSet) -> DirectedGraph:
    """Build a dependency graph from locked result."""
    graph = DirectedGraph()
    graph.add(None)  # sentinel parent of top nodes.
    node_with_extras = set()

    def add_package(key, dist):
        name, extras = strip_extras(key)
        extras = extras or ()
        reqs = {}
        if dist:
            requirements = [
                Requirement.from_pkg_requirement(r)
                for r in dist.requires(extras)
            ]
            for req in requirements:
                reqs[req.identify()] = req
            version = dist.version
        else:
            version = None

        node = Package(key, version, reqs)
        if node not in graph:
            if extras:
                node_with_extras.add(name)
            graph.add(node)

            for k in reqs:
                child = add_package(k, working_set.get(strip_extras(k)[0]))
                graph.connect(node, child)

        return node

    for k, dist in working_set.items():
        add_package(k, dist)
    for node in graph._vertices.copy():
        if node is not None and not list(graph.iter_parents(node)):
            # Top requirements
            if node.name in node_with_extras:
                # Already included in package[extra], no need to keep the top level
                # non-extra package.
                graph.remove(node)
            else:
                graph.connect(None, node)
    return graph
Ejemplo n.º 5
0
def build_dependency_graph(
        working_set: WorkingSet,
        marker_env: dict[str, str] | None = None) -> DirectedGraph:
    """Build a dependency graph from locked result."""
    graph: DirectedGraph[Package | None] = DirectedGraph()
    graph.add(None)  # sentinel parent of top nodes.
    node_with_extras: set[str] = set()

    def add_package(key: str, dist: Distribution | None) -> Package:
        name, extras = strip_extras(key)
        extras = extras or ()
        reqs: dict[str, Requirement] = {}
        if dist:
            requirements = (parse_requirement(r)
                            for r in filter_requirements_with_extras(
                                cast(str, dist.metadata["Name"]),
                                dist.requires or [],
                                extras,
                                include_default=True,
                            ))
            for req in requirements:
                if not req.marker or req.marker.evaluate(marker_env):
                    reqs[req.identify()] = req
            version: str | None = dist.version
        else:
            version = None

        node = Package(key, version, reqs)
        if node not in graph:
            if extras:
                node_with_extras.add(name)
            graph.add(node)

            for k in reqs:
                child = add_package(k, working_set.get(strip_extras(k)[0]))
                graph.connect(node, child)

        return node

    for k, dist in working_set.items():
        add_package(k, dist)
    for node in list(graph):
        if node is not None and not list(graph.iter_parents(node)):
            # Top requirements
            if node.name in node_with_extras:
                # Already included in package[extra], no need to keep the top level
                # non-extra package.
                graph.remove(node)
            else:
                graph.connect(None, node)
    return graph
Ejemplo n.º 6
0
def format_dependency_graph(project: Project, graph: DirectedGraph) -> str:
    """Format dependency graph for output."""
    content = []
    all_dependencies = ChainMap(*project.all_dependencies.values())
    for package in sorted(graph.iter_children(None), key=lambda p: p.name):
        if package.name in all_dependencies:
            required = str(all_dependencies[package.name].specifier or "Any")
        elif (not project.environment.is_global
              and package.name == project.meta.project_name.lower()):
            required = "This project"
        else:
            required = ""
        content.append(format_package(graph, package, required, "", set()))
    return "".join(content).strip()
Ejemplo n.º 7
0
def format_package(
    graph: DirectedGraph,
    package: Package,
    required: str = "",
    prefix: str = "",
    visited: Optional[Set[str]] = None,
) -> str:
    """Format one package.

    :param graph: the dependency graph
    :param package: the package instance
    :param required: the version required by its parent
    :param prefix: prefix text for children
    :param visited: the visited package collection
    """
    if visited is None:
        visited = set()
    result = []
    version = (
        termui.red("[ not installed ]")
        if not package.version
        else termui.red(package.version)
        if required
        and required not in ("Any", "This project")
        and not SpecifierSet(required).contains(package.version)
        else termui.yellow(package.version)
    )
    if package.name in visited:
        version = termui.red("[circular]")
    required = f"[ required: {required} ]" if required else "[ Not required ]"
    result.append(f"{termui.green(package.name, bold=True)} {version} {required}\n")
    if package.name in visited:
        return "".join(result)
    visited.add(package.name)
    children = sorted(graph.iter_children(package), key=lambda p: p.name)
    for i, child in enumerate(children):
        is_last = i == len(children) - 1
        head = LAST_CHILD if is_last else NON_LAST_CHILD
        cur_prefix = LAST_PREFIX if is_last else NON_LAST_PREFIX
        required = str(package.requirements[child.name].specifier or "Any")
        result.append(
            prefix
            + head
            + format_package(
                graph, child, required, prefix + cur_prefix, visited.copy()
            )
        )
    return "".join(result)
Ejemplo n.º 8
0
def format_reverse_package(
    graph: DirectedGraph,
    package: Package,
    child: Optional[Package] = None,
    requires: str = "",
    prefix: str = "",
    visited: Optional[Set[str]] = None,
):
    """Format one package for output reverse dependency graph."""
    if visited is None:
        visited = set()
    result = []
    version = (
        termui.red("[ not installed ]")
        if not package.version
        else termui.yellow(package.version)
    )
    if package.name in visited:
        version = termui.red("[circular]")
    requires = (
        f"[ requires: {termui.red(requires)} ]"
        if requires not in ("Any", "")
        and child
        and child.version
        and not SpecifierSet(requires).contains(child.version)
        else ""
        if not requires
        else f"[ requires: {requires} ]"
    )
    result.append(f"{termui.green(package.name, bold=True)} {version} {requires}\n")
    if package.name in visited:
        return "".join(result)
    visited.add(package.name)
    parents = sorted(filter(None, graph.iter_parents(package)), key=lambda p: p.name)
    for i, parent in enumerate(parents):
        is_last = i == len(parents) - 1
        head = LAST_CHILD if is_last else NON_LAST_CHILD
        cur_prefix = LAST_PREFIX if is_last else NON_LAST_PREFIX
        requires = str(parent.requirements[package.name].specifier or "Any")
        result.append(
            prefix
            + head
            + format_reverse_package(
                graph, parent, package, requires, prefix + cur_prefix, visited.copy()
            )
        )
    return "".join(result)
Ejemplo n.º 9
0
Archivo: utils.py Proyecto: pawamoy/pdm
def _format_forward_dependency_graph(project: Project,
                                     graph: DirectedGraph) -> str:
    """Format dependency graph for output."""
    content = []
    all_dependencies = ChainMap(*project.all_dependencies.values())
    top_level_dependencies = sorted(graph.iter_children(None),
                                    key=lambda p: p.name)
    for package in top_level_dependencies:
        if package.name in all_dependencies:
            required = specifier_from_requirement(
                all_dependencies[package.name])
        elif package_is_project(package, project):
            required = "This project"
        else:
            required = ""
        content.append(format_package(graph, package, required, ""))
    return "".join(content).strip()
Ejemplo n.º 10
0
def graph():
    return DirectedGraph()