Coverage for src/renaissance/integrations/python/ast/extractor.py: 84%
32 statements
« prev ^ index » next coverage.py v7.16.1, created at 2026-10-02 13:12 +0000
« prev ^ index » next coverage.py v7.16.1, created at 2026-10-02 13:12 +0000
1"""AI: Extractor that builds a codebase graph of Python modules and their contained statements."""
3from pathlib import Path
5import networkx as nx
7from renaissance.integrations.python.ast.rst_node import PythonRstNode
8from renaissance.syntax_tree.semantic_kind import SemanticKind
11class PythonExtractor:
12 """AI: Extractor that builds a codebase graph of Python modules and their contained statements."""
14 graph = nx.DiGraph()
15 codebase: dict = {}
17 def process(self, file: Path):
18 """AI: Parse file and merge its module/import/function/class nodes into the codebase graph."""
19 root = PythonRstNode.load(file)
20 module_name = root.filename.replace("/", ".").replace(".py", "")
21 folder = str(Path(file).parent)
22 self.graph.add_node(folder, type="folder")
23 self.graph.add_edge(folder, module_name, type="contains")
25 for stmt in root:
26 match stmt.semantic_kind:
27 case SemanticKind.IMPORT:
28 self.graph.add_edge(module_name, stmt.name, type="include")
29 case _ if stmt.parser_kind == "ImportFrom":
30 for alias in stmt.node.names:
31 self.graph.add_edge(module_name, f"{stmt.node.module}.{alias.name}", type="include")
32 case SemanticKind.FUNCTION:
33 self.graph.add_edge(module_name, f"{module_name}.{stmt.name}", type="definition")
34 self.graph.add_node(f"{module_name}.{stmt.name}", properties="function")
35 # TODO: convert #, stmt.properties) to graphml
36 case SemanticKind.CLASS:
37 self.graph.add_edge(module_name, f"{module_name}.{stmt.name}", type="definition")
38 self.graph.add_node(f"{module_name}.{stmt.name}") # convert to args, stmt.properties)
39 case _:
40 pass
42 self.codebase[file] = root
43 # # reconstruct dependencies inside module
44 # tu.lazy_create_refers(root)
45 # self.nodes |= tu._nodes
46 # self.edges |=tu._references
47 # self.edges |= tu._referenced_by
49 def save_graph(self, filename: str):
50 """AI: Write the extracted codebase graph to a GraphML file named filename."""
51 nx.write_graphml(self.graph, filename)
52 print(f"Graph saved to: {filename}")