codegraph-cli-ai 0.1.6__tar.gz → 0.1.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. codegraph_cli_ai-0.1.8/MANIFEST.in +1 -0
  2. codegraph_cli_ai-0.1.8/PKG-INFO +225 -0
  3. codegraph_cli_ai-0.1.8/README.md +207 -0
  4. {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph/cli.py +121 -11
  5. codegraph_cli_ai-0.1.8/codegraph/graph/builder.py +190 -0
  6. codegraph_cli_ai-0.1.8/codegraph/parsers/database_parser.py +25 -0
  7. codegraph_cli_ai-0.1.8/codegraph/parsers/image_parser.py +39 -0
  8. codegraph_cli_ai-0.1.8/codegraph/parsers/multimodal_parser.py +86 -0
  9. codegraph_cli_ai-0.1.8/codegraph/parsers/pdf_parser.py +43 -0
  10. {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph/parsers/python_parser.py +13 -1
  11. codegraph_cli_ai-0.1.8/codegraph_cli_ai.egg-info/PKG-INFO +225 -0
  12. {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph_cli_ai.egg-info/SOURCES.txt +5 -0
  13. {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/pyproject.toml +1 -1
  14. codegraph_cli_ai-0.1.6/MANIFEST.in +0 -1
  15. codegraph_cli_ai-0.1.6/PKG-INFO +0 -17
  16. codegraph_cli_ai-0.1.6/codegraph/graph/builder.py +0 -110
  17. codegraph_cli_ai-0.1.6/codegraph_cli_ai.egg-info/PKG-INFO +0 -17
  18. {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph_cli_ai.egg-info/dependency_links.txt +0 -0
  19. {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph_cli_ai.egg-info/entry_points.txt +0 -0
  20. {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph_cli_ai.egg-info/requires.txt +0 -0
  21. {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph_cli_ai.egg-info/top_level.txt +0 -0
  22. {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/setup.cfg +0 -0
@@ -0,0 +1 @@
1
+ include README.md
@@ -0,0 +1,225 @@
1
+ Metadata-Version: 2.4
2
+ Name: codegraph-cli-ai
3
+ Version: 0.1.8
4
+ Summary: CLI tool to analyze codebases and visualize knowledge graphs using AST
5
+ Author: Aditya Jogdand
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/AdityaJogdand/codegraph-ai
8
+ Keywords: code-analysis,ast,graph,cli,developer-tools
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: typer>=0.9.0
16
+ Requires-Dist: networkx>=3.0
17
+ Requires-Dist: pyvis>=0.3.2
18
+
19
+ # CodeGraph AI
20
+
21
+ **CodeGraph AI** is a CLI tool that analyzes your Python codebase and visualizes it as an interactive knowledge graph.
22
+
23
+ It helps developers understand:
24
+
25
+ * Code structure
26
+ * Function call relationships
27
+ * File dependencies
28
+ * Overall architecture
29
+
30
+ ---
31
+
32
+ ## Features
33
+
34
+ * AST-based parsing of Python code
35
+ * Function call graph generation
36
+ * Dependency graph (imports)
37
+ * Interactive visualization in browser
38
+ * Focus on specific files
39
+ * Hide external libraries (stdlib & third-party)
40
+ * Fast CLI-based workflow
41
+
42
+ ---
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ pip install codegraph-ai
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Quick Start
53
+
54
+ ```bash
55
+ codegraph index
56
+ codegraph plot
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Commands
62
+
63
+ ### 1. Index your codebase
64
+
65
+ Scan and build the graph:
66
+
67
+ ```bash
68
+ codegraph index
69
+ ```
70
+
71
+ Index a specific folder:
72
+
73
+ ```bash
74
+ codegraph index path/to/your/project
75
+ ```
76
+
77
+ ---
78
+
79
+ ### 2. Visualize the graph
80
+
81
+ ```bash
82
+ codegraph plot
83
+ ```
84
+
85
+ This opens an interactive graph in your browser.
86
+
87
+ ---
88
+
89
+ ## Advanced Usage
90
+
91
+ ### Hide external libraries
92
+
93
+ Removes standard library and third-party dependencies from the graph:
94
+
95
+ ```bash
96
+ codegraph plot --hide-external
97
+ ```
98
+
99
+ ---
100
+
101
+ ### Focus on a specific file
102
+
103
+ Shows only a file and its direct relationships:
104
+
105
+ ```bash
106
+ codegraph plot --focus cli.py
107
+ ```
108
+
109
+ ---
110
+
111
+ ### Filter by node type
112
+
113
+ Show only certain types of nodes:
114
+
115
+ ```bash
116
+ codegraph plot --level file
117
+ codegraph plot --level function
118
+ codegraph plot --level class
119
+ ```
120
+
121
+ ---
122
+
123
+ ### Filter by edge type
124
+
125
+ Show only specific relationships:
126
+
127
+ ```bash
128
+ codegraph plot --edge-type calls
129
+ codegraph plot --edge-type imports
130
+ codegraph plot --edge-type contains
131
+ codegraph plot --edge-type all
132
+ ```
133
+
134
+ ---
135
+
136
+ ### Combine filters
137
+
138
+ ```bash
139
+ codegraph plot --focus cli.py --hide-external --edge-type calls
140
+ ```
141
+
142
+ ---
143
+
144
+ ## How It Works
145
+
146
+ 1. Parses Python files using AST
147
+ 2. Extracts:
148
+
149
+ * Functions
150
+ * Classes
151
+ * Imports
152
+ * Function calls
153
+ 3. Builds a directed knowledge graph
154
+ 4. Renders it as an interactive visualization
155
+
156
+ ---
157
+
158
+ ## Graph Semantics
159
+
160
+ ### Node Types
161
+
162
+ | Type | Description |
163
+ | -------- | ------------------- |
164
+ | File | Python file |
165
+ | Function | Function or method |
166
+ | Class | Class definition |
167
+ | Module | External dependency |
168
+
169
+ ---
170
+
171
+ ### Edge Types
172
+
173
+ | Relation | Meaning |
174
+ | ---------- | ------------------------------- |
175
+ | contains | File/Class contains function |
176
+ | calls | Function calls another function |
177
+ | imports | File imports module |
178
+ | defined_in | Function belongs to file |
179
+
180
+ ---
181
+
182
+ ## Output Files
183
+
184
+ After indexing:
185
+
186
+ ```
187
+ .codegraph/graph.json
188
+ ```
189
+
190
+ After visualization:
191
+
192
+ ```
193
+ graph.html
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Example Workflow
199
+
200
+ ```bash
201
+ codegraph index
202
+ codegraph plot --hide-external
203
+ ```
204
+
205
+ ---
206
+
207
+ ## Use Cases
208
+
209
+ * Understand large codebases quickly
210
+ * Visualize architecture
211
+ * Debug dependencies
212
+ * Explore function interactions
213
+ * Prepare for refactoring
214
+
215
+ ---
216
+
217
+ ## Author
218
+
219
+ Aditya Jogdand
220
+
221
+ ---
222
+
223
+ ## License
224
+
225
+ MIT License
@@ -0,0 +1,207 @@
1
+ # CodeGraph AI
2
+
3
+ **CodeGraph AI** is a CLI tool that analyzes your Python codebase and visualizes it as an interactive knowledge graph.
4
+
5
+ It helps developers understand:
6
+
7
+ * Code structure
8
+ * Function call relationships
9
+ * File dependencies
10
+ * Overall architecture
11
+
12
+ ---
13
+
14
+ ## Features
15
+
16
+ * AST-based parsing of Python code
17
+ * Function call graph generation
18
+ * Dependency graph (imports)
19
+ * Interactive visualization in browser
20
+ * Focus on specific files
21
+ * Hide external libraries (stdlib & third-party)
22
+ * Fast CLI-based workflow
23
+
24
+ ---
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ pip install codegraph-ai
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Quick Start
35
+
36
+ ```bash
37
+ codegraph index
38
+ codegraph plot
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Commands
44
+
45
+ ### 1. Index your codebase
46
+
47
+ Scan and build the graph:
48
+
49
+ ```bash
50
+ codegraph index
51
+ ```
52
+
53
+ Index a specific folder:
54
+
55
+ ```bash
56
+ codegraph index path/to/your/project
57
+ ```
58
+
59
+ ---
60
+
61
+ ### 2. Visualize the graph
62
+
63
+ ```bash
64
+ codegraph plot
65
+ ```
66
+
67
+ This opens an interactive graph in your browser.
68
+
69
+ ---
70
+
71
+ ## Advanced Usage
72
+
73
+ ### Hide external libraries
74
+
75
+ Removes standard library and third-party dependencies from the graph:
76
+
77
+ ```bash
78
+ codegraph plot --hide-external
79
+ ```
80
+
81
+ ---
82
+
83
+ ### Focus on a specific file
84
+
85
+ Shows only a file and its direct relationships:
86
+
87
+ ```bash
88
+ codegraph plot --focus cli.py
89
+ ```
90
+
91
+ ---
92
+
93
+ ### Filter by node type
94
+
95
+ Show only certain types of nodes:
96
+
97
+ ```bash
98
+ codegraph plot --level file
99
+ codegraph plot --level function
100
+ codegraph plot --level class
101
+ ```
102
+
103
+ ---
104
+
105
+ ### Filter by edge type
106
+
107
+ Show only specific relationships:
108
+
109
+ ```bash
110
+ codegraph plot --edge-type calls
111
+ codegraph plot --edge-type imports
112
+ codegraph plot --edge-type contains
113
+ codegraph plot --edge-type all
114
+ ```
115
+
116
+ ---
117
+
118
+ ### Combine filters
119
+
120
+ ```bash
121
+ codegraph plot --focus cli.py --hide-external --edge-type calls
122
+ ```
123
+
124
+ ---
125
+
126
+ ## How It Works
127
+
128
+ 1. Parses Python files using AST
129
+ 2. Extracts:
130
+
131
+ * Functions
132
+ * Classes
133
+ * Imports
134
+ * Function calls
135
+ 3. Builds a directed knowledge graph
136
+ 4. Renders it as an interactive visualization
137
+
138
+ ---
139
+
140
+ ## Graph Semantics
141
+
142
+ ### Node Types
143
+
144
+ | Type | Description |
145
+ | -------- | ------------------- |
146
+ | File | Python file |
147
+ | Function | Function or method |
148
+ | Class | Class definition |
149
+ | Module | External dependency |
150
+
151
+ ---
152
+
153
+ ### Edge Types
154
+
155
+ | Relation | Meaning |
156
+ | ---------- | ------------------------------- |
157
+ | contains | File/Class contains function |
158
+ | calls | Function calls another function |
159
+ | imports | File imports module |
160
+ | defined_in | Function belongs to file |
161
+
162
+ ---
163
+
164
+ ## Output Files
165
+
166
+ After indexing:
167
+
168
+ ```
169
+ .codegraph/graph.json
170
+ ```
171
+
172
+ After visualization:
173
+
174
+ ```
175
+ graph.html
176
+ ```
177
+
178
+ ---
179
+
180
+ ## Example Workflow
181
+
182
+ ```bash
183
+ codegraph index
184
+ codegraph plot --hide-external
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Use Cases
190
+
191
+ * Understand large codebases quickly
192
+ * Visualize architecture
193
+ * Debug dependencies
194
+ * Explore function interactions
195
+ * Prepare for refactoring
196
+
197
+ ---
198
+
199
+ ## Author
200
+
201
+ Aditya Jogdand
202
+
203
+ ---
204
+
205
+ ## License
206
+
207
+ MIT License
@@ -9,6 +9,7 @@ import networkx as nx
9
9
  from pathlib import Path
10
10
  from typing import Optional
11
11
  from codegraph.parsers.python_parser import PythonParser
12
+ from codegraph.parsers.multimodal_parser import MultiModalParser
12
13
  from codegraph.graph.builder import GraphBuilder
13
14
 
14
15
  app = typer.Typer()
@@ -20,6 +21,23 @@ def main():
20
21
  pass
21
22
 
22
23
 
24
+ IGNORE_DIRS = {
25
+ "venv", ".venv", "env", "bin", "Scripts",
26
+ ".git", "__pycache__", "node_modules", ".codegraph"
27
+ }
28
+ IGNORE_FILES = {"graph.json", ".DS_Store"}
29
+ IGNORE_EXTENSIONS = {".pyc", ".log", ".pyo", ".pyd"}
30
+
31
+
32
+ def is_virtualenv(path: Path) -> bool:
33
+ """Detect if a directory is a virtual environment based on its structure."""
34
+ return (
35
+ (path / "pyvenv.cfg").exists()
36
+ or (path / "bin" / "python").exists()
37
+ or (path / "Scripts" / "python.exe").exists()
38
+ )
39
+
40
+
23
41
  @app.command()
24
42
  def index(
25
43
  path: str = typer.Argument(".", help="Path to the repo or folder to index")
@@ -32,31 +50,81 @@ def index(
32
50
  raise typer.Exit(code=1)
33
51
 
34
52
  typer.echo(f"Indexing: {root}\n")
35
- py_files = list(root.rglob("*.py"))
53
+
54
+ # Phase A: Identify top-level custom virtualenvs
55
+ venv_dirs = set()
56
+ for item in root.iterdir():
57
+ if item.is_dir() and is_virtualenv(item):
58
+ venv_dirs.add(item)
59
+
60
+ # Phase B: Filtered Scan
61
+ all_files = []
62
+ for p in root.rglob("*"):
63
+ if not p.is_file():
64
+ continue
65
+
66
+ # 1. Skip if any parent directory is in IGNORE_DIRS
67
+ if any(part in IGNORE_DIRS for part in p.parts):
68
+ continue
69
+
70
+ # 2. Skip if inside a detected custom venv
71
+ if any(v_dir in p.parents for v_dir in venv_dirs):
72
+ continue
73
+
74
+ # 3. Skip if filename is ignored
75
+ if p.name in IGNORE_FILES:
76
+ continue
77
+
78
+ # 4. Skip if extension is ignored
79
+ if p.suffix.lower() in IGNORE_EXTENSIONS:
80
+ continue
81
+
82
+ all_files.append(p)
83
+
84
+ py_files = [f for f in all_files if f.suffix == ".py"]
85
+ asset_exts = {
86
+ ".csv", ".json", ".db", ".sqlite",
87
+ ".pdf",
88
+ ".png", ".jpg", ".jpeg"
89
+ }
90
+ asset_files = [f for f in all_files if f.suffix.lower() in asset_exts]
36
91
 
37
- if not py_files:
38
- typer.echo("No Python files found.")
92
+ if not py_files and not asset_files:
93
+ typer.echo("No supported files found (everything might be ignored).")
39
94
  raise typer.Exit()
40
95
 
41
- typer.echo(f"Found {len(py_files)} Python file(s)\n")
96
+ typer.echo(f"Found {len(py_files)} Python file(s) and {len(asset_files)} asset(s)\n")
42
97
 
43
98
  # Step 1 — Parse
44
- parser = PythonParser()
99
+ py_parser = PythonParser()
100
+ mm_parser = MultiModalParser()
101
+
45
102
  parsed_files = []
103
+ parsed_assets = []
46
104
  failed_files = []
47
105
 
106
+ # Parse Python files
48
107
  for filepath in py_files:
49
- result = parser.parse_file(str(filepath))
108
+ result = py_parser.parse_file(str(filepath))
50
109
  if result.errors:
51
110
  failed_files.append((str(filepath), result.errors))
52
111
  else:
53
- typer.echo(f" ✔ {filepath.relative_to(root)}")
112
+ typer.echo(f" ✔ [code] {filepath.relative_to(root)}")
54
113
  parsed_files.append(result)
55
114
 
115
+ # Parse assets
116
+ for filepath in asset_files:
117
+ try:
118
+ asset = mm_parser.parse(str(filepath))
119
+ typer.echo(f" ✔ [asset] {filepath.relative_to(root)}")
120
+ parsed_assets.append(asset)
121
+ except Exception as e:
122
+ failed_files.append((str(filepath), [str(e)]))
123
+
56
124
  # Step 2 — Build graph
57
125
  typer.echo("\nBuilding graph...")
58
126
  builder = GraphBuilder()
59
- builder.build(parsed_files)
127
+ builder.build(parsed_files, parsed_assets)
60
128
  summary = builder.summary()
61
129
 
62
130
  # Step 3 — Save to .codegraph/graph.json
@@ -163,9 +231,13 @@ def _build_premium_html(G: nx.DiGraph) -> str:
163
231
  STYLES = {
164
232
  "file": {"color": "#4A90E2", "shape": "diamond", "size": 28, "font_color": "#ffffff"},
165
233
  "class": {"color": "#F5A623", "shape": "hexagon", "size": 24, "font_color": "#ffffff"},
166
- "function": {"color": "#50C878", "shape": "dot", "size": 16, "font_color": "#ffffff"},
167
- "method": {"color": "#7ED6A8", "shape": "dot", "size": 14, "font_color": "#ffffff"},
234
+ "function": {"color": "#50C878", "shape": "dot", "size": 16, "font_color": "#ffffff"},
235
+ "method": {"color": "#7ED6A8", "shape": "dot", "size": 14, "font_color": "#ffffff"},
168
236
  "module": {"color": "#B0BEC5", "shape": "box", "size": 14, "font_color": "#ffffff"},
237
+ "dataset": {"color": "#FFD700", "shape": "diamond", "size": 22, "font_color": "#ffffff"},
238
+ "database": {"color": "#FF69B4", "shape": "database", "size": 24, "font_color": "#ffffff"},
239
+ "document": {"color": "#9B59B6", "shape": "diamond", "size": 24, "font_color": "#ffffff"},
240
+ "image": {"color": "#5DADE2", "shape": "diamond", "size": 24, "font_color": "#ffffff"},
169
241
  }
170
242
 
171
243
  EDGE_COLORS = {
@@ -173,6 +245,8 @@ def _build_premium_html(G: nx.DiGraph) -> str:
173
245
  "calls": "#50C878",
174
246
  "imports": "#B0BEC5",
175
247
  "defined_in": "#E8E8E8",
248
+ "uses": "#FFD700",
249
+ "references": "#9B59B6",
176
250
  }
177
251
 
178
252
  nodes_js = []
@@ -188,10 +262,41 @@ def _build_premium_html(G: nx.DiGraph) -> str:
188
262
 
189
263
  # Tooltip
190
264
  tooltip_parts = [f"<b>{label}</b>", f"Kind: {kind}"]
191
- if attrs.get("file"):
265
+ if attrs.get("filename"):
266
+ tooltip_parts.append(f"File: {attrs['filename']}")
267
+ elif attrs.get("file"):
192
268
  tooltip_parts.append(f"File: {attrs['file'].replace('file:', '')}")
193
269
  if attrs.get("cls"):
194
270
  tooltip_parts.append(f"Class: {attrs['cls']}")
271
+
272
+ # MultiModal Metadata for tooltips
273
+ metadata = attrs.get("metadata", {})
274
+ if kind == "dataset":
275
+ if "columns" in metadata: tooltip_parts.append(f"Columns: {', '.join(metadata['columns'])}")
276
+ if "keys" in metadata: tooltip_parts.append(f"Keys: {', '.join(metadata['keys'])}")
277
+ elif kind == "database":
278
+ if "tables" in metadata: tooltip_parts.append(f"Tables: {', '.join(metadata['tables'])}")
279
+ elif kind == "document":
280
+ if "num_pages" in metadata: tooltip_parts.append(f"Pages: {metadata['num_pages']}")
281
+ if "text_preview" in metadata: tooltip_parts.append(f"<br>Preview: <i>{metadata['text_preview']}</i>")
282
+ elif kind == "image":
283
+ if "text" in metadata and metadata["text"]: tooltip_parts.append(f"<br>OCR Text: <i>{metadata['text']}</i>")
284
+
285
+ # Add metadata for datasets/databases
286
+ metadata = attrs.get("metadata", {})
287
+ if metadata:
288
+ if "columns" in metadata:
289
+ cols = ", ".join(metadata["columns"][:5])
290
+ if len(metadata["columns"]) > 5: cols += "..."
291
+ tooltip_parts.append(f"Columns: {cols}")
292
+ if "tables" in metadata:
293
+ tbls = ", ".join(metadata["tables"])
294
+ tooltip_parts.append(f"Tables: {tbls}")
295
+ if "keys" in metadata:
296
+ keys = ", ".join(metadata["keys"][:5])
297
+ if len(metadata["keys"]) > 5: keys += "..."
298
+ tooltip_parts.append(f"Keys: {keys}")
299
+
195
300
  if external:
196
301
  tooltip_parts.append("<i>external</i>")
197
302
  tooltip = "<br>".join(tooltip_parts)
@@ -337,10 +442,15 @@ def _build_premium_html(G: nx.DiGraph) -> str:
337
442
  <div class="legend-item"><div class="legend-dot" style="background:#50C878"></div>Function</div>
338
443
  <div class="legend-item"><div class="legend-dot" style="background:#7ED6A8"></div>Method</div>
339
444
  <div class="legend-item"><div class="legend-dot" style="background:#B0BEC5;border-radius:2px"></div>Module</div>
445
+ <div class="legend-item"><div class="legend-dot" style="background:#FFD700;clip-path:polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)"></div>Dataset</div>
446
+ <div class="legend-item"><div class="legend-dot" style="background:#FF69B4;border-radius:2px"></div>Database</div>
447
+ <div class="legend-item"><div class="legend-dot" style="background:#9B59B6;clip-path:polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)"></div>Document</div>
448
+ <div class="legend-item"><div class="legend-dot" style="background:#5DADE2;clip-path:polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)"></div>Image</div>
340
449
  <span style="font-size:11px; color:#546E7A; font-weight: 700; margin-left:12px; margin-right:4px; letter-spacing: 0.05em;">EDGES</span>
341
450
  <div class="legend-item"><div style="width:20px;height:2px;background:#4A90E2;opacity:0.6"></div>contains</div>
342
451
  <div class="legend-item"><div style="width:20px;height:2px;background:#50C878;opacity:0.6"></div>calls</div>
343
452
  <div class="legend-item"><div style="width:20px;height:1px;background:#B0BEC5;border-top:1px dashed #B0BEC5"></div>imports</div>
453
+ <div class="legend-item"><div style="width:20px;height:2px;background:#FFD700;opacity:0.6"></div>uses</div>
344
454
  </div>
345
455
 
346
456
  <div id="graph-container">