Skip to content

dependencies

Full name: tenets.viz.dependencies

dependencies

Dependencies visualization module.

This module provides visualization capabilities for dependency analysis, including dependency graphs, circular dependencies, and package structure.

Classes

DependencyVisualizer

Python
DependencyVisualizer(chart_config: Optional[ChartConfig] = None, display_config: Optional[DisplayConfig] = None)

Bases: BaseVisualizer

Visualizer for dependency metrics.

Creates visualizations for dependency analysis including dependency trees, circular dependency detection, and package relationships.

Initialize dependency visualizer.

PARAMETERDESCRIPTION
chart_config

Chart configuration

TYPE:Optional[ChartConfig]DEFAULT:None

display_config

Display configuration

TYPE:Optional[DisplayConfig]DEFAULT:None

Source code in tenets/viz/dependencies.py
Python
def __init__(
    self,
    chart_config: Optional[ChartConfig] = None,
    display_config: Optional[DisplayConfig] = None,
):
    """Initialize dependency visualizer.

    Args:
        chart_config: Chart configuration
        display_config: Display configuration
    """
    super().__init__(chart_config, display_config)
    self.terminal_display = TerminalDisplay(display_config)
Functions
create_dependency_graph
Python
create_dependency_graph(dependencies: Dict[str, List[str]], highlight_circular: bool = True, max_nodes: int = 100) -> Dict[str, Any]

Create dependency graph visualization.

PARAMETERDESCRIPTION
dependencies

Dictionary of module -> [dependencies]

TYPE:Dict[str, List[str]]

highlight_circular

Whether to highlight circular dependencies

TYPE:boolDEFAULT:True

max_nodes

Maximum nodes to display

TYPE:intDEFAULT:100

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Network graph configuration

Source code in tenets/viz/dependencies.py
Python
def create_dependency_graph(
    self,
    dependencies: Dict[str, List[str]],
    highlight_circular: bool = True,
    max_nodes: int = 100,
) -> Dict[str, Any]:
    """Create dependency graph visualization.

    Args:
        dependencies: Dictionary of module -> [dependencies]
        highlight_circular: Whether to highlight circular dependencies
        max_nodes: Maximum nodes to display

    Returns:
        Dict[str, Any]: Network graph configuration
    """
    # Build nodes and edges
    nodes_set = set()
    edges = []

    # Track circular dependencies
    circular_pairs = set()
    if highlight_circular:
        circular_pairs = self._find_circular_dependencies(dependencies)

    for module, deps in dependencies.items():
        nodes_set.add(module)
        for dep in deps:
            nodes_set.add(dep)

            # Check if this is a circular dependency
            is_circular = (module, dep) in circular_pairs or (dep, module) in circular_pairs

            edges.append(
                {
                    "source": module,
                    "target": dep,
                    "color": ColorPalette.SEVERITY["critical"] if is_circular else None,
                    "style": "dashed" if is_circular else "solid",
                }
            )

    # Limit nodes if necessary
    if len(nodes_set) > max_nodes:
        # Keep nodes with most connections
        node_connections = {}
        for module, deps in dependencies.items():
            node_connections[module] = node_connections.get(module, 0) + len(deps)
            for dep in deps:
                node_connections[dep] = node_connections.get(dep, 0) + 1

        sorted_nodes = sorted(
            nodes_set, key=lambda n: node_connections.get(n, 0), reverse=True
        )[:max_nodes]
        nodes_set = set(sorted_nodes)

        # Filter edges
        edges = [e for e in edges if e["source"] in nodes_set and e["target"] in nodes_set]

    # Create node list
    nodes = []
    for node_id in nodes_set:
        # Determine node type and color
        is_external = self._is_external_dependency(node_id)
        has_circular = any(node_id in pair for pair in circular_pairs)

        if has_circular:
            color = ColorPalette.SEVERITY["critical"]
        elif is_external:
            color = ColorPalette.DEFAULT[2]  # Green for external
        else:
            color = ColorPalette.DEFAULT[0]  # Blue for internal

        nodes.append(
            {
                "id": node_id,
                "label": self._truncate_package_name(node_id),
                "color": color,
                "shape": "box" if is_external else "circle",
            }
        )

    config = ChartConfig(type=ChartType.NETWORK, title="Dependency Graph")

    return self.create_chart(
        ChartType.NETWORK, {"nodes": nodes, "edges": edges, "layout": "hierarchical"}, config
    )
create_dependency_tree
Python
create_dependency_tree(tree_data: Dict[str, Any], max_depth: int = 5) -> Dict[str, Any]

Create dependency tree visualization.

PARAMETERDESCRIPTION
tree_data

Hierarchical dependency data

TYPE:Dict[str, Any]

max_depth

Maximum tree depth to display

TYPE:intDEFAULT:5

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Treemap configuration

Source code in tenets/viz/dependencies.py
Python
def create_dependency_tree(
    self, tree_data: Dict[str, Any], max_depth: int = 5
) -> Dict[str, Any]:
    """Create dependency tree visualization.

    Args:
        tree_data: Hierarchical dependency data
        max_depth: Maximum tree depth to display

    Returns:
        Dict[str, Any]: Treemap configuration
    """
    # Flatten tree to specified depth
    flat_data = self._flatten_tree(tree_data, max_depth)

    config = ChartConfig(type=ChartType.TREEMAP, title="Dependency Tree")

    return self.create_chart(ChartType.TREEMAP, {"tree": flat_data}, config)
create_package_sunburst
Python
create_package_sunburst(package_data: Dict[str, Any]) -> Dict[str, Any]

Create package structure sunburst chart.

PARAMETERDESCRIPTION
package_data

Hierarchical package data

TYPE:Dict[str, Any]

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Sunburst/treemap configuration

Source code in tenets/viz/dependencies.py
Python
def create_package_sunburst(self, package_data: Dict[str, Any]) -> Dict[str, Any]:
    """Create package structure sunburst chart.

    Args:
        package_data: Hierarchical package data

    Returns:
        Dict[str, Any]: Sunburst/treemap configuration
    """
    flat_data = self._flatten_tree(package_data)

    # Color by depth level
    for i, item in enumerate(flat_data):
        depth = item.get("depth", 0)
        item["color"] = ColorPalette.DEFAULT[depth % len(ColorPalette.DEFAULT)]

    config = ChartConfig(type=ChartType.TREEMAP, title="Package Structure")

    return self.create_chart(ChartType.TREEMAP, {"tree": flat_data}, config)
create_circular_dependencies_chart
Python
create_circular_dependencies_chart(circular_deps: List[List[str]]) -> Dict[str, Any]

Create circular dependencies visualization.

PARAMETERDESCRIPTION
circular_deps

List of circular dependency chains

TYPE:List[List[str]]

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Network graph configuration

Source code in tenets/viz/dependencies.py
Python
def create_circular_dependencies_chart(self, circular_deps: List[List[str]]) -> Dict[str, Any]:
    """Create circular dependencies visualization.

    Args:
        circular_deps: List of circular dependency chains

    Returns:
        Dict[str, Any]: Network graph configuration
    """
    # Build graph from circular chains
    nodes_set = set()
    edges = []

    for chain in circular_deps:
        for i, module in enumerate(chain):
            nodes_set.add(module)
            if i < len(chain) - 1:
                edges.append(
                    {
                        "source": module,
                        "target": chain[i + 1],
                        "color": ColorPalette.SEVERITY["critical"],
                        "style": "solid",
                        "arrows": "to",
                    }
                )

    # Create nodes with critical coloring
    nodes = [
        {
            "id": node,
            "label": self._truncate_package_name(node),
            "color": ColorPalette.SEVERITY["critical"],
            "shape": "circle",
        }
        for node in nodes_set
    ]

    config = ChartConfig(type=ChartType.NETWORK, title="Circular Dependencies")

    return self.create_chart(
        ChartType.NETWORK, {"nodes": nodes, "edges": edges, "layout": "circular"}, config
    )
create_dependency_matrix
Python
create_dependency_matrix(modules: List[str], dependency_matrix: List[List[bool]]) -> Dict[str, Any]

Create dependency matrix visualization.

PARAMETERDESCRIPTION
modules

List of module names

TYPE:List[str]

dependency_matrix

Boolean matrix of dependencies

TYPE:List[List[bool]]

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Heatmap configuration

Source code in tenets/viz/dependencies.py
Python
def create_dependency_matrix(
    self, modules: List[str], dependency_matrix: List[List[bool]]
) -> Dict[str, Any]:
    """Create dependency matrix visualization.

    Args:
        modules: List of module names
        dependency_matrix: Boolean matrix of dependencies

    Returns:
        Dict[str, Any]: Heatmap configuration
    """
    # Convert boolean to numeric
    numeric_matrix = [[1 if dep else 0 for dep in row] for row in dependency_matrix]

    labels = [self._truncate_package_name(m) for m in modules]

    config = ChartConfig(type=ChartType.HEATMAP, title="Dependency Matrix")

    return self.create_chart(
        ChartType.HEATMAP,
        {"matrix": numeric_matrix, "x_labels": labels, "y_labels": labels},
        config,
    )
create_layer_violations_chart
Python
create_layer_violations_chart(violations: List[Dict[str, Any]]) -> Dict[str, Any]

Create layer violation visualization.

PARAMETERDESCRIPTION
violations

List of layer violations

TYPE:List[Dict[str, Any]]

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Chart configuration

Source code in tenets/viz/dependencies.py
Python
def create_layer_violations_chart(self, violations: List[Dict[str, Any]]) -> Dict[str, Any]:
    """Create layer violation visualization.

    Args:
        violations: List of layer violations

    Returns:
        Dict[str, Any]: Chart configuration
    """
    # Group violations by type
    violation_types = {}
    for violation in violations:
        vtype = violation.get("type", "Unknown")
        violation_types[vtype] = violation_types.get(vtype, 0) + 1

    labels = list(violation_types.keys())
    values = list(violation_types.values())

    # Color based on severity
    colors = []
    for label in labels:
        if "critical" in label.lower():
            colors.append(ColorPalette.SEVERITY["critical"])
        elif "high" in label.lower():
            colors.append(ColorPalette.SEVERITY["high"])
        else:
            colors.append(ColorPalette.SEVERITY["medium"])

    config = ChartConfig(
        type=ChartType.BAR, title="Architecture Layer Violations", colors=colors
    )

    return self.create_chart(ChartType.BAR, {"labels": labels, "values": values}, config)
display_terminal
Python
display_terminal(dependency_data: Dict[str, Any], show_details: bool = True) -> None

Display dependency analysis in terminal.

PARAMETERDESCRIPTION
dependency_data

Dependency analysis data

TYPE:Dict[str, Any]

show_details

Whether to show detailed breakdown

TYPE:boolDEFAULT:True

Source code in tenets/viz/dependencies.py
Python
def display_terminal(self, dependency_data: Dict[str, Any], show_details: bool = True) -> None:
    """Display dependency analysis in terminal.

    Args:
        dependency_data: Dependency analysis data
        show_details: Whether to show detailed breakdown
    """
    # Display header
    self.terminal_display.display_header("Dependency Analysis", style="double")

    # Display summary metrics
    summary_data = {
        "Total Modules": dependency_data.get("total_modules", 0),
        "Total Dependencies": dependency_data.get("total_dependencies", 0),
        "External Dependencies": dependency_data.get("external_dependencies", 0),
        "Circular Dependencies": dependency_data.get("circular_count", 0),
    }

    self.terminal_display.display_metrics(summary_data, title="Summary")

    # Display circular dependencies warning
    if dependency_data.get("circular_count", 0) > 0:
        self.terminal_display.display_warning(
            f"⚠️  Found {dependency_data['circular_count']} circular dependencies!"
        )

        if show_details and "circular_chains" in dependency_data:
            for i, chain in enumerate(dependency_data["circular_chains"][:5], 1):
                chain_str = " → ".join(chain[:5])
                if len(chain) > 5:
                    chain_str += f" → ... ({len(chain) - 5} more)"
                print(f"  {i}. {chain_str}")

    # Display most dependent modules
    if show_details and "most_dependent" in dependency_data:
        headers = ["Module", "Dependencies", "Dependents", "Coupling"]
        rows = []

        for module in dependency_data["most_dependent"][:10]:
            coupling = module.get("dependencies", 0) + module.get("dependents", 0)
            rows.append(
                [
                    self._truncate_package_name(module.get("name", "")),
                    str(module.get("dependencies", 0)),
                    str(module.get("dependents", 0)),
                    str(coupling),
                ]
            )

        self.terminal_display.display_table(headers, rows, title="Most Dependent Modules")

    # Display external dependencies
    if "external" in dependency_data:
        self._display_external_dependencies(dependency_data["external"])

    # Display recommendations
    if "recommendations" in dependency_data:
        self.terminal_display.display_list(
            dependency_data["recommendations"], title="Recommendations", style="numbered"
        )
create_dependency_trend
Python
create_dependency_trend(trend_data: List[Dict[str, Any]]) -> Dict[str, Any]

Create dependency trend chart over time.

PARAMETERDESCRIPTION
trend_data

List of data points with date and metrics

TYPE:List[Dict[str, Any]]

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Line chart configuration

Source code in tenets/viz/dependencies.py
Python
def create_dependency_trend(self, trend_data: List[Dict[str, Any]]) -> Dict[str, Any]:
    """Create dependency trend chart over time.

    Args:
        trend_data: List of data points with date and metrics

    Returns:
        Dict[str, Any]: Line chart configuration
    """
    labels = []
    total_deps = []
    external_deps = []
    circular_deps = []

    for point in trend_data:
        labels.append(point.get("date", ""))
        total_deps.append(point.get("total_dependencies", 0))
        external_deps.append(point.get("external_dependencies", 0))
        circular_deps.append(point.get("circular_dependencies", 0))

    datasets = [
        {
            "label": "Total Dependencies",
            "data": total_deps,
            "borderColor": ColorPalette.DEFAULT[0],
            "fill": False,
        },
        {
            "label": "External Dependencies",
            "data": external_deps,
            "borderColor": ColorPalette.DEFAULT[1],
            "fill": False,
        },
        {
            "label": "Circular Dependencies",
            "data": circular_deps,
            "borderColor": ColorPalette.SEVERITY["critical"],
            "fill": False,
            "yAxisID": "y1",
        },
    ]

    config = ChartConfig(type=ChartType.LINE, title="Dependency Trends")

    chart_config = self.create_chart(
        ChartType.LINE, {"labels": labels, "datasets": datasets}, config
    )

    # Add dual y-axis
    chart_config["options"]["scales"] = {
        "y": {"type": "linear", "display": True, "position": "left"},
        "y1": {
            "type": "linear",
            "display": True,
            "position": "right",
            "grid": {"drawOnChartArea": False},
        },
    }

    return chart_config