Skip to content

graph_generator

Full name: tenets.viz.graph_generator

graph_generator

Graph generation for dependency visualization.

Pure-Python backends (pip-installable) are preferred: - Plotly + Kaleido for static/interactive graphs - NetworkX + Matplotlib as a fallback - Graphviz only if available (requires system binaries) - DOT/HTML text fallback otherwise

Classes

GraphGenerator

Python
GraphGenerator()

Generates various graph visualizations for dependencies.

Source code in tenets/viz/graph_generator.py
Python
def __init__(self) -> None:
    self.logger = get_logger(__name__)
    # Capability flags
    self._networkx_available = False
    self._matplotlib_available = False
    self._graphviz_available = False
    self._plotly_available = False
    self._kaleido_available = False

    # Optional imports (best-effort)
    try:
        import networkx as nx  # type: ignore

        self.nx = nx
        self._networkx_available = True
    except Exception:
        self.logger.debug("NetworkX not available - pip install networkx")

    try:
        import matplotlib  # type: ignore

        matplotlib.use("Agg")
        import matplotlib.pyplot as plt  # type: ignore

        self.plt = plt
        self._matplotlib_available = True
    except Exception:
        self.logger.debug("Matplotlib not available - pip install matplotlib")

    try:
        import graphviz  # type: ignore

        self.graphviz = graphviz
        self._graphviz_available = True
    except Exception:
        self.logger.debug(
            "Graphviz not available - pip install graphviz (and install system Graphviz)"
        )

    try:
        import plotly.graph_objects as go  # type: ignore

        self.go = go
        self._plotly_available = True
    except Exception:
        self.logger.debug("Plotly not available - pip install plotly")

    try:
        import kaleido  # noqa: F401  # type: ignore

        self._kaleido_available = True
    except Exception:
        self._kaleido_available = False
Functions
generate_graph
Python
generate_graph(dependency_graph: Dict[str, List[str]], output_path: Optional[Path] = None, format: str = 'svg', layout: str = 'hierarchical', cluster_by: Optional[str] = None, max_nodes: Optional[int] = None, project_info: Optional[Dict[str, Any]] = None) -> str

Generate a dependency graph visualization.

PARAMETERDESCRIPTION
dependency_graph

node -> list of dependencies

TYPE:Dict[str, List[str]]

output_path

where to save; if None, return string content

TYPE:Optional[Path]DEFAULT:None

format

svg, png, pdf, html, json, dot

TYPE:strDEFAULT:'svg'

layout

layout hint (hierarchical, circular, shell, kamada)

TYPE:strDEFAULT:'hierarchical'

cluster_by

module, directory, package

TYPE:Optional[str]DEFAULT:None

max_nodes

optional cap on number of nodes

TYPE:Optional[int]DEFAULT:None

project_info

optional project metadata

TYPE:Optional[Dict[str, Any]]DEFAULT:None

Source code in tenets/viz/graph_generator.py
Python
def generate_graph(
    self,
    dependency_graph: Dict[str, List[str]],
    output_path: Optional[Path] = None,
    format: str = "svg",
    layout: str = "hierarchical",
    cluster_by: Optional[str] = None,
    max_nodes: Optional[int] = None,
    project_info: Optional[Dict[str, Any]] = None,
) -> str:
    """Generate a dependency graph visualization.

    Args:
        dependency_graph: node -> list of dependencies
        output_path: where to save; if None, return string content
        format: svg, png, pdf, html, json, dot
        layout: layout hint (hierarchical, circular, shell, kamada)
        cluster_by: module, directory, package
        max_nodes: optional cap on number of nodes
        project_info: optional project metadata
    """
    processed = self._process_graph(
        dependency_graph,
        cluster_by=cluster_by,
        max_nodes=max_nodes,
        project_info=project_info,
    )

    if format == "json":
        return self._generate_json(processed, output_path)
    if format == "dot":
        return self._generate_dot(processed, output_path)
    if format == "html":
        return self._generate_html(processed, output_path, layout)
    if format in ("svg", "png", "pdf"):
        return self._generate_image(processed, output_path, format, layout)
    raise ValueError(f"Unsupported format: {format}")

Functions