File size: 1,937 Bytes
cf05092
 
 
 
 
 
 
899a7c7
 
cf05092
 
 
 
 
 
 
 
 
 
 
899a7c7
cf05092
 
899a7c7
 
 
 
 
 
cf05092
 
 
899a7c7
cf05092
 
899a7c7
 
cf05092
 
899a7c7
 
 
 
 
cf05092
899a7c7
 
 
cf05092
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

import networkx as nx

from db.seed import seed_project
from graph.graph_manager import GraphManager


@dataclass
class GraphLoadResult:
    graph: nx.DiGraph
    loaded_from_cache: bool


class DependencyGraph:
    def __init__(self, target_dir: str | Path, db_path: str | Path | None = None) -> None:
        self.target_dir = Path(target_dir).resolve()
        self.graph_manager = GraphManager(source_root=self.target_dir, db_path=db_path)

    def load_or_build(self, force_reparse: bool = False) -> GraphLoadResult:
        result = seed_project(
            self.target_dir,
            db_path=str(self.graph_manager.store.config.db_path),
            force=force_reparse,
        )
        loaded_from_cache = bool(result.get("loaded_from_cache", False))
        return GraphLoadResult(graph=self._build_graph(), loaded_from_cache=loaded_from_cache)

    def _build_graph(self) -> nx.DiGraph:
        return self.graph_manager.load_graph()

    def traversal_order(self, graph: nx.DiGraph | None = None) -> list[str]:
        if graph is None:
            return self.graph_manager.traversal_order()
        if graph.number_of_nodes() == 0:
            return []
        centrality = nx.betweenness_centrality(graph, normalized=True)
        return sorted(
            graph.nodes(),
            key=lambda node: (
                int(graph.out_degree(node)),
                float(centrality.get(node, 0.0)),
                str(node),
            ),
        )


if __name__ == "__main__":
    manager = DependencyGraph(target_dir="sample_codebase")
    result = manager.load_or_build()
    print(
        f"Loaded graph with {result.graph.number_of_nodes()} nodes and "
        f"{result.graph.number_of_edges()} edges (cache={result.loaded_from_cache})"
    )
    print("Traversal order:", manager.traversal_order(result.graph))