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¶
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.
PARAMETER | DESCRIPTION |
---|---|
chart_config | Chart configuration TYPE: |
display_config | Display configuration TYPE: |
Source code in tenets/viz/dependencies.py
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¶
create_dependency_graph(dependencies: Dict[str, List[str]], highlight_circular: bool = True, max_nodes: int = 100) -> Dict[str, Any]
Create dependency graph visualization.
PARAMETER | DESCRIPTION |
---|---|
dependencies | Dictionary of module -> [dependencies] |
highlight_circular | Whether to highlight circular dependencies TYPE: |
max_nodes | Maximum nodes to display TYPE: |
RETURNS | DESCRIPTION |
---|---|
Dict[str, Any] | Dict[str, Any]: Network graph configuration |
Source code in tenets/viz/dependencies.py
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¶
Create dependency tree visualization.
PARAMETER | DESCRIPTION |
---|---|
tree_data | Hierarchical dependency data |
max_depth | Maximum tree depth to display TYPE: |
RETURNS | DESCRIPTION |
---|---|
Dict[str, Any] | Dict[str, Any]: Treemap configuration |
Source code in tenets/viz/dependencies.py
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¶
Create package structure sunburst chart.
PARAMETER | DESCRIPTION |
---|---|
package_data | Hierarchical package data |
RETURNS | DESCRIPTION |
---|---|
Dict[str, Any] | Dict[str, Any]: Sunburst/treemap configuration |
Source code in tenets/viz/dependencies.py
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¶
Create circular dependencies visualization.
PARAMETER | DESCRIPTION |
---|---|
circular_deps | List of circular dependency chains |
RETURNS | DESCRIPTION |
---|---|
Dict[str, Any] | Dict[str, Any]: Network graph configuration |
Source code in tenets/viz/dependencies.py
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¶
create_dependency_matrix(modules: List[str], dependency_matrix: List[List[bool]]) -> Dict[str, Any]
Create dependency matrix visualization.
PARAMETER | DESCRIPTION |
---|---|
modules | List of module names |
dependency_matrix | Boolean matrix of dependencies |
RETURNS | DESCRIPTION |
---|---|
Dict[str, Any] | Dict[str, Any]: Heatmap configuration |
Source code in tenets/viz/dependencies.py
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¶
Create layer violation visualization.
PARAMETER | DESCRIPTION |
---|---|
violations | List of layer violations |
RETURNS | DESCRIPTION |
---|---|
Dict[str, Any] | Dict[str, Any]: Chart configuration |
Source code in tenets/viz/dependencies.py
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¶
Display dependency analysis in terminal.
PARAMETER | DESCRIPTION |
---|---|
dependency_data | Dependency analysis data |
show_details | Whether to show detailed breakdown TYPE: |
Source code in tenets/viz/dependencies.py
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¶
Create dependency trend chart over time.
PARAMETER | DESCRIPTION |
---|---|
trend_data | List of data points with date and metrics |
RETURNS | DESCRIPTION |
---|---|
Dict[str, Any] | Dict[str, Any]: Line chart configuration |
Source code in tenets/viz/dependencies.py
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