Skip to content

Public Interface

All names that can be imported from this module are considered public, stable, and intended for general use.

The byecycle.run function returns a dictionary containing all the necessary information, as well as a networkx.DiGraph with essentially the same information but a different interface, and the name of the importable distribution, which is useful if you want to create artifacts with good names.

For analysis, the dictionary is probably all you need:

from byecycle import run

imports, _, _ = run("byecycle")
print(imports["byecycle"]["byecycle.cli"]["cycle"])  # prints: 'complicated'

Functions

run(project, *, dynamic=severity['dynamic'], conditional=severity['conditional'], typing=severity['typing'], parent=severity['parent'], vanilla=severity['vanilla'])

Programmatic equivalent of running this package through the CLI.

Parameters:

  • project (str) –

    Either the path to a project source, or the name of an installed package.

  • dynamic (EdgeKind) –

    Severity of dynamic import cycles.

  • conditional (EdgeKind) –

    Severity of conditional import cycles.

  • typing (EdgeKind) –

    Severity of typing-only import cycles.

  • parent (EdgeKind) –

    Severity of parent-package-resolution related import cycles.

  • vanilla (EdgeKind) –

    Severity of vanilla import cycles.

Returns:

  • GraphDict

    A dictionary-representation of the import graph.

  • nx.DiGraph

    The actual import graph.

  • str

    The name of the package.

Source code in src/byecycle/cli.py
def _run(
    project: str,
    *,
    dynamic: EdgeKind = severity["dynamic"],
    conditional: EdgeKind = severity["conditional"],
    typing: EdgeKind = severity["typing"],
    parent: EdgeKind = severity["parent"],
    vanilla: EdgeKind = severity["vanilla"],
) -> tuple[GraphDict, nx.DiGraph, str]:
    """Programmatic equivalent of running this package through the CLI.

    Args:
        project: Either the path to a project source, or the name of an installed package.
        dynamic: Severity of dynamic import cycles.
        conditional: Severity of conditional import cycles.
        typing: Severity of typing-only import cycles.
        parent: Severity of parent-package-resolution related import cycles.
        vanilla: Severity of vanilla import cycles.

    Returns:
        A dictionary-representation of the import graph.
        The actual import graph.
        The name of the package.
    """
    if os.path.isdir(project):
        project_path = Path(project)
    else:
        try:
            spec = importlib.util.find_spec(project)
        except ImportError:
            spec = None
        if spec is None or spec.origin is None:
            raise RuntimeError(
                f"Failed trying to resolve {project=} as a package, please pass the "
                f"source code location as proper path."
            )
        project_path = Path(spec.origin).parent.resolve()

    root = Module.parse(project_path)
    graph = build_digraph(
        root,
        dynamic=dynamic,
        conditional=conditional,
        typing=typing,
        parent=parent,
        vanilla=vanilla,
    )
    return {key: {**graph[key]} for key in graph}, graph, project_path.name