codeui-python 0.1.0__tar.gz → 0.1.1__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.
- {codeui_python-0.1.0 → codeui_python-0.1.1}/LICENSE +1 -1
- codeui_python-0.1.1/PKG-INFO +171 -0
- codeui_python-0.1.1/README.md +139 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/pyproject.toml +5 -4
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/__init__.py +1 -1
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/agent/context.py +19 -3
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/analysis/dead_code.py +13 -2
- codeui_python-0.1.1/src/codeui/analysis/undefined.py +167 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/analysis/unresolved_import.py +34 -4
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/cli/main.py +101 -7
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/core/cache.py +54 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/core/graph.py +233 -3
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/core/override.py +1 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/core/resolver.py +51 -37
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/errors.py +10 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/lang/base.py +5 -2
- codeui_python-0.1.1/src/codeui/lang/cpp.py +271 -0
- codeui_python-0.1.1/src/codeui/lang/csharp.py +262 -0
- codeui_python-0.1.1/src/codeui/lang/dart.py +278 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/lang/generic.py +6 -4
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/lang/go.py +5 -2
- codeui_python-0.1.1/src/codeui/lang/java.py +320 -0
- codeui_python-0.1.1/src/codeui/lang/kotlin.py +303 -0
- codeui_python-0.1.1/src/codeui/lang/php.py +275 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/lang/python.py +49 -7
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/lang/registry.py +22 -2
- codeui_python-0.1.1/src/codeui/lang/ruby.py +270 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/lang/rust.py +5 -2
- codeui_python-0.1.1/src/codeui/lang/scala.py +290 -0
- codeui_python-0.1.1/src/codeui/lang/swift.py +276 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/lang/ts.py +99 -8
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/report/sarif_emitter.py +2 -1
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/server/server.py +156 -85
- codeui_python-0.1.1/src/codeui/server/static/css/styles.css +1609 -0
- codeui_python-0.1.1/src/codeui/server/static/index.html +199 -0
- codeui_python-0.1.1/src/codeui/server/static/js/api.js +485 -0
- codeui_python-0.1.1/src/codeui/server/static/js/app.js +1044 -0
- codeui_python-0.1.1/src/codeui/server/static/js/graph_canvas.js +1485 -0
- codeui_python-0.1.1/src/codeui/server/static/js/minimap.js +383 -0
- codeui_python-0.1.1/src/codeui/server/static/js/sidebar.js +268 -0
- codeui_python-0.1.1/src/codeui/server/static/js/state.js +83 -0
- codeui_python-0.1.1/src/codeui/server/static/js/subgraph_window.js +1208 -0
- codeui_python-0.1.1/src/codeui/server/static/js/theme.js +332 -0
- codeui_python-0.1.1/src/codeui/tracer/__init__.py +4 -0
- codeui_python-0.1.1/src/codeui/tracer/tracer.py +138 -0
- codeui_python-0.1.1/src/codeui_python.egg-info/PKG-INFO +171 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui_python.egg-info/SOURCES.txt +20 -1
- codeui_python-0.1.1/tests/test_cache.py +77 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/tests/test_cli.py +33 -0
- codeui_python-0.1.1/tests/test_dytr_integration.py +119 -0
- codeui_python-0.1.1/tests/test_graph.py +140 -0
- codeui_python-0.1.1/tests/test_languages.py +145 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/tests/test_overrides.py +8 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/tests/test_resolver.py +16 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/tests/test_server.py +36 -0
- codeui_python-0.1.0/PKG-INFO +0 -191
- codeui_python-0.1.0/README.md +0 -154
- codeui_python-0.1.0/setup.py +0 -53
- codeui_python-0.1.0/src/codeui/analysis/undefined.py +0 -97
- codeui_python-0.1.0/src/codeui/tracer/__init__.py +0 -1
- codeui_python-0.1.0/src/codeui/tracer/tracer.py +0 -147
- codeui_python-0.1.0/src/codeui_python.egg-info/PKG-INFO +0 -191
- codeui_python-0.1.0/tests/test_cache.py +0 -38
- codeui_python-0.1.0/tests/test_graph.py +0 -70
- codeui_python-0.1.0/tests/test_languages.py +0 -39
- {codeui_python-0.1.0 → codeui_python-0.1.1}/setup.cfg +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/agent/__init__.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/agent/contribution.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/agent/edit_tools.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/agent/integrations.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/agent/mcp_server.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/analysis/__init__.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/analysis/api_drift.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/analysis/base.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/analysis/circular.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/analysis/duplicates.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/analysis/runner.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/analysis/shadowing.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/analysis/unreachable.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/cli/__init__.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/core/__init__.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/core/ir.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/core/repo.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/lang/__init__.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/plugins/__init__.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/plugins/registry.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/report/__init__.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/report/json_emitter.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/report/markdown_emitter.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui/server/__init__.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui_python.egg-info/dependency_links.txt +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui_python.egg-info/entry_points.txt +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui_python.egg-info/requires.txt +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/src/codeui_python.egg-info/top_level.txt +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/tests/test_agent.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/tests/test_analyzers.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/tests/test_contribution.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/tests/test_edge_cases.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/tests/test_repo.py +0 -0
- {codeui_python-0.1.0 → codeui_python-0.1.1}/tests/test_tracer.py +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codeui-python
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Universal static analysis code intelligence library, defect detector, graph visualizer, and agent context builder
|
|
5
|
+
Author-email: Akram Alsubari <akram.alsubari87@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/AAlsubari/codeUI
|
|
8
|
+
Project-URL: Documentation, https://github.com/AAlsubari/codeUI#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/AAlsubari/codeUI.git
|
|
10
|
+
Project-URL: Issues, https://github.com/AAlsubari/codeUI/issues
|
|
11
|
+
Keywords: code-analysis,static-analysis,code-graph,ast,ai-agents,code-intelligence,llm-context,defect-detection
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
21
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
28
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
29
|
+
Requires-Dist: build; extra == "dev"
|
|
30
|
+
Requires-Dist: twine; extra == "dev"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# codeui-python 🌐⚡
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/codeui-python/)
|
|
36
|
+
[](https://www.python.org/)
|
|
37
|
+
[](https://opensource.org/licenses/MIT)
|
|
38
|
+
[](https://github.com/AAlsubari/codeUI)
|
|
39
|
+
|
|
40
|
+
**`codeui-python`** (`codeui`) is an open-source static analysis engine that converts any Python or polyglot software repository into a rich, **interactive web graph visualizer**, call-hierarchy tracer, defect detector, live code editor, and AI agent context builder.
|
|
41
|
+
|
|
42
|
+
It safely parses codebases via AST (Abstract Syntax Tree) without ever executing or importing target code, producing a universal intermediate representation (IR) graph.
|
|
43
|
+
|
|
44
|
+
📦 **PyPI Package**: [https://pypi.org/project/codeui-python/](https://pypi.org/project/codeui-python/)
|
|
45
|
+
🐙 **GitHub Repository**: [https://github.com/AAlsubari/codeUI](https://github.com/AAlsubari/codeUI)
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 🌟 Main Features
|
|
50
|
+
|
|
51
|
+
### 1. 🕸️ Convert Any Project into an Interactive Graph
|
|
52
|
+
Effortlessly explore your entire codebase as a force-directed, interactive visual dependency graph:
|
|
53
|
+
- **Universal AST Parsing**: Maps modules, classes, functions, variables, imports, and calls across Python, TypeScript, Go, Rust, Java, .etc.
|
|
54
|
+
- **Multi-Window Subgraph Workspaces**: Open symbols, modules, and call chains in floating, draggable windows.
|
|
55
|
+
- **Cross-Usage Navigation**: Trace incoming/outgoing references across files in real time.
|
|
56
|
+
|
|
57
|
+
### 2. 📝 Interactive Code Editor & Live Edits
|
|
58
|
+
Edit and refactor code directly inside the graph UI (`http://127.0.0.1:3000`):
|
|
59
|
+
- **Direct Disk Writing**: Save edits directly to your local source files on disk with a single click.
|
|
60
|
+
- **In-Memory Shadow Overrides**: Test edits non-destructively in an in-memory shadow store with instant diff inspection before writing to disk.
|
|
61
|
+
|
|
62
|
+
### 3. 🔍 Static Defect Detection Engine
|
|
63
|
+
Includes 8 built-in static defect analyzers that identify structural code bugs before runtime:
|
|
64
|
+
- `undefined`: Missing or undefined symbols and functions.
|
|
65
|
+
- `dead_code`: Unreferenced private functions and unused module exports.
|
|
66
|
+
- `unresolved_import`: Broken or unresolvable import statements.
|
|
67
|
+
- `circular`: Cyclic dependency chains via Tarjan's Strongly Connected Components algorithm.
|
|
68
|
+
- `duplicates`: Structural code clones and duplicate routines.
|
|
69
|
+
- `unreachable`: Code paths following terminal control statements (`return`, `raise`, `exit`).
|
|
70
|
+
- `shadowing`: Variable shadowing across nested lexical scopes.
|
|
71
|
+
- `api_drift`: Public API signature changes and breaking contract drift against baseline snapshots.
|
|
72
|
+
|
|
73
|
+
### 4. 🤖 AI Agent Context Engine
|
|
74
|
+
- **Smart Subgraph Bundling**: Extracts minimal, context-complete subgraphs for LLMs (Claude, GPT-4, Gemini) without token bloat.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## ⚠️ Initial Release Notice & Call for Contributions
|
|
80
|
+
|
|
81
|
+
> **Note on Version 0.1.1**:
|
|
82
|
+
> `codeui-python` is currently in an **initial pre-release version**. Static analysis across complex, dynamic multi-language codebases is intricate, and you may encounter bugs, unparsed syntax edge cases, or unsupported language features.
|
|
83
|
+
>
|
|
84
|
+
> 🚀 **We Welcome All Contributions!**
|
|
85
|
+
> We actively invite developers, researchers, and open-source contributors to try `codeui-python`, report issues, submit feature requests, or open pull requests to help expand language support and parser capabilities.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 📦 Installation
|
|
90
|
+
|
|
91
|
+
Install the library via PyPI:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install codeui-python
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Or install the development version from source:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git clone https://github.com/AAlsubari/codeUI.git
|
|
101
|
+
cd codeUI
|
|
102
|
+
pip install -e ".[dev]"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 🚀 Quickstart
|
|
108
|
+
|
|
109
|
+
### 1. Launch Interactive Graph Visualizer
|
|
110
|
+
|
|
111
|
+
Run `codeui serve` in any repository directory to open the interactive browser graph:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
codeui serve . --port 3000
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Then open `http://127.0.0.1:3000` in your browser to interactively explore, search, trace, and edit your code.
|
|
118
|
+
|
|
119
|
+
### 2. Command Line Interface (CLI)
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# Scan a codebase into a JSON graph representation
|
|
123
|
+
codeui scan .
|
|
124
|
+
|
|
125
|
+
# Trace forward execution dependencies for a symbol
|
|
126
|
+
codeui trace "src/main.py::run" . --direction forward --depth 3
|
|
127
|
+
|
|
128
|
+
# Generate minimal LLM Context Bundle for AI agents
|
|
129
|
+
codeui context . --symbol "src/main.py::run"
|
|
130
|
+
|
|
131
|
+
# Scan codebase for defects (SARIF format)
|
|
132
|
+
codeui defects . --format sarif
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 3. Python API Usage
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from pathlib import Path
|
|
139
|
+
from codeui.cli.main import scan_project
|
|
140
|
+
from codeui.tracer.tracer import Tracer
|
|
141
|
+
from codeui.agent.context import ContextBuilder
|
|
142
|
+
|
|
143
|
+
# 1. Scan codebase into a Universal AST Graph (No code execution)
|
|
144
|
+
graph = scan_project(Path("."))
|
|
145
|
+
|
|
146
|
+
# 2. Perform Call Graph Tracing
|
|
147
|
+
tracer = Tracer(graph)
|
|
148
|
+
dependencies = list(tracer.forward("src/main.py::run"))
|
|
149
|
+
|
|
150
|
+
# 3. Extract LLM Context Bundle for AI Agents
|
|
151
|
+
builder = ContextBuilder(graph)
|
|
152
|
+
bundle = builder.for_symbol("src/main.py::run", depth=2)
|
|
153
|
+
print(bundle.to_json())
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 📚 Documentation & Resources
|
|
159
|
+
|
|
160
|
+
- [Quickstart Guide](./docs/quickstart.md)
|
|
161
|
+
- [Python API Reference](./docs/api.md)
|
|
162
|
+
- [AI Agent Integration & Context Engine](./docs/agent_integration.md)
|
|
163
|
+
- [Architecture Overview](./docs/architecture.md)
|
|
164
|
+
- [Static Analyzer & Defect Reference](./docs/analyzer_reference.md)
|
|
165
|
+
- [Extending codeui](./docs/extending.md)
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 📄 License
|
|
170
|
+
|
|
171
|
+
`codeui-python` is distributed under the [MIT License](./LICENSE). Copyright (c) 2026 Akram Alsubari and contributors.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# codeui-python 🌐⚡
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/codeui-python/)
|
|
4
|
+
[](https://www.python.org/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://github.com/AAlsubari/codeUI)
|
|
7
|
+
|
|
8
|
+
**`codeui-python`** (`codeui`) is an open-source static analysis engine that converts any Python or polyglot software repository into a rich, **interactive web graph visualizer**, call-hierarchy tracer, defect detector, live code editor, and AI agent context builder.
|
|
9
|
+
|
|
10
|
+
It safely parses codebases via AST (Abstract Syntax Tree) without ever executing or importing target code, producing a universal intermediate representation (IR) graph.
|
|
11
|
+
|
|
12
|
+
📦 **PyPI Package**: [https://pypi.org/project/codeui-python/](https://pypi.org/project/codeui-python/)
|
|
13
|
+
🐙 **GitHub Repository**: [https://github.com/AAlsubari/codeUI](https://github.com/AAlsubari/codeUI)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 🌟 Main Features
|
|
18
|
+
|
|
19
|
+
### 1. 🕸️ Convert Any Project into an Interactive Graph
|
|
20
|
+
Effortlessly explore your entire codebase as a force-directed, interactive visual dependency graph:
|
|
21
|
+
- **Universal AST Parsing**: Maps modules, classes, functions, variables, imports, and calls across Python, TypeScript, Go, Rust, Java, .etc.
|
|
22
|
+
- **Multi-Window Subgraph Workspaces**: Open symbols, modules, and call chains in floating, draggable windows.
|
|
23
|
+
- **Cross-Usage Navigation**: Trace incoming/outgoing references across files in real time.
|
|
24
|
+
|
|
25
|
+
### 2. 📝 Interactive Code Editor & Live Edits
|
|
26
|
+
Edit and refactor code directly inside the graph UI (`http://127.0.0.1:3000`):
|
|
27
|
+
- **Direct Disk Writing**: Save edits directly to your local source files on disk with a single click.
|
|
28
|
+
- **In-Memory Shadow Overrides**: Test edits non-destructively in an in-memory shadow store with instant diff inspection before writing to disk.
|
|
29
|
+
|
|
30
|
+
### 3. 🔍 Static Defect Detection Engine
|
|
31
|
+
Includes 8 built-in static defect analyzers that identify structural code bugs before runtime:
|
|
32
|
+
- `undefined`: Missing or undefined symbols and functions.
|
|
33
|
+
- `dead_code`: Unreferenced private functions and unused module exports.
|
|
34
|
+
- `unresolved_import`: Broken or unresolvable import statements.
|
|
35
|
+
- `circular`: Cyclic dependency chains via Tarjan's Strongly Connected Components algorithm.
|
|
36
|
+
- `duplicates`: Structural code clones and duplicate routines.
|
|
37
|
+
- `unreachable`: Code paths following terminal control statements (`return`, `raise`, `exit`).
|
|
38
|
+
- `shadowing`: Variable shadowing across nested lexical scopes.
|
|
39
|
+
- `api_drift`: Public API signature changes and breaking contract drift against baseline snapshots.
|
|
40
|
+
|
|
41
|
+
### 4. 🤖 AI Agent Context Engine
|
|
42
|
+
- **Smart Subgraph Bundling**: Extracts minimal, context-complete subgraphs for LLMs (Claude, GPT-4, Gemini) without token bloat.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## ⚠️ Initial Release Notice & Call for Contributions
|
|
48
|
+
|
|
49
|
+
> **Note on Version 0.1.1**:
|
|
50
|
+
> `codeui-python` is currently in an **initial pre-release version**. Static analysis across complex, dynamic multi-language codebases is intricate, and you may encounter bugs, unparsed syntax edge cases, or unsupported language features.
|
|
51
|
+
>
|
|
52
|
+
> 🚀 **We Welcome All Contributions!**
|
|
53
|
+
> We actively invite developers, researchers, and open-source contributors to try `codeui-python`, report issues, submit feature requests, or open pull requests to help expand language support and parser capabilities.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 📦 Installation
|
|
58
|
+
|
|
59
|
+
Install the library via PyPI:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install codeui-python
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Or install the development version from source:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git clone https://github.com/AAlsubari/codeUI.git
|
|
69
|
+
cd codeUI
|
|
70
|
+
pip install -e ".[dev]"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 🚀 Quickstart
|
|
76
|
+
|
|
77
|
+
### 1. Launch Interactive Graph Visualizer
|
|
78
|
+
|
|
79
|
+
Run `codeui serve` in any repository directory to open the interactive browser graph:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
codeui serve . --port 3000
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Then open `http://127.0.0.1:3000` in your browser to interactively explore, search, trace, and edit your code.
|
|
86
|
+
|
|
87
|
+
### 2. Command Line Interface (CLI)
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Scan a codebase into a JSON graph representation
|
|
91
|
+
codeui scan .
|
|
92
|
+
|
|
93
|
+
# Trace forward execution dependencies for a symbol
|
|
94
|
+
codeui trace "src/main.py::run" . --direction forward --depth 3
|
|
95
|
+
|
|
96
|
+
# Generate minimal LLM Context Bundle for AI agents
|
|
97
|
+
codeui context . --symbol "src/main.py::run"
|
|
98
|
+
|
|
99
|
+
# Scan codebase for defects (SARIF format)
|
|
100
|
+
codeui defects . --format sarif
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 3. Python API Usage
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from pathlib import Path
|
|
107
|
+
from codeui.cli.main import scan_project
|
|
108
|
+
from codeui.tracer.tracer import Tracer
|
|
109
|
+
from codeui.agent.context import ContextBuilder
|
|
110
|
+
|
|
111
|
+
# 1. Scan codebase into a Universal AST Graph (No code execution)
|
|
112
|
+
graph = scan_project(Path("."))
|
|
113
|
+
|
|
114
|
+
# 2. Perform Call Graph Tracing
|
|
115
|
+
tracer = Tracer(graph)
|
|
116
|
+
dependencies = list(tracer.forward("src/main.py::run"))
|
|
117
|
+
|
|
118
|
+
# 3. Extract LLM Context Bundle for AI Agents
|
|
119
|
+
builder = ContextBuilder(graph)
|
|
120
|
+
bundle = builder.for_symbol("src/main.py::run", depth=2)
|
|
121
|
+
print(bundle.to_json())
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 📚 Documentation & Resources
|
|
127
|
+
|
|
128
|
+
- [Quickstart Guide](./docs/quickstart.md)
|
|
129
|
+
- [Python API Reference](./docs/api.md)
|
|
130
|
+
- [AI Agent Integration & Context Engine](./docs/agent_integration.md)
|
|
131
|
+
- [Architecture Overview](./docs/architecture.md)
|
|
132
|
+
- [Static Analyzer & Defect Reference](./docs/analyzer_reference.md)
|
|
133
|
+
- [Extending codeui](./docs/extending.md)
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 📄 License
|
|
138
|
+
|
|
139
|
+
`codeui-python` is distributed under the [MIT License](./LICENSE). Copyright (c) 2026 Akram Alsubari and contributors.
|
|
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codeui-python"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.1"
|
|
8
8
|
description = "Universal static analysis code intelligence library, defect detector, graph visualizer, and agent context builder"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
11
|
-
{ name = "Akram Alsubari", email = "
|
|
11
|
+
{ name = "Akram Alsubari", email = "akram.alsubari87@gmail.com" }
|
|
12
12
|
]
|
|
13
13
|
license = { text = "MIT" }
|
|
14
14
|
requires-python = ">=3.10"
|
|
@@ -60,14 +60,15 @@ codeui = "codeui.cli.main:main"
|
|
|
60
60
|
where = ["src"]
|
|
61
61
|
include = ["codeui*"]
|
|
62
62
|
|
|
63
|
+
[tool.setuptools.package-data]
|
|
64
|
+
codeui = ["server/static/**/*", "server/static/*"]
|
|
65
|
+
|
|
63
66
|
[tool.pytest.ini_options]
|
|
64
|
-
pythonpath = ["src"]
|
|
65
67
|
testpaths = ["tests"]
|
|
66
68
|
addopts = "--doctest-modules"
|
|
67
69
|
|
|
68
70
|
[tool.mypy]
|
|
69
71
|
python_version = "3.10"
|
|
70
|
-
mypy_path = "src"
|
|
71
72
|
strict = true
|
|
72
73
|
warn_return_any = true
|
|
73
74
|
warn_unused_configs = true
|
|
@@ -110,7 +110,9 @@ class ContextBuilder:
|
|
|
110
110
|
|
|
111
111
|
relevant_findings = [
|
|
112
112
|
f.to_dict() for f in self.graph.get_findings()
|
|
113
|
-
if f.symbol_id in {s.id for s in syms} or
|
|
113
|
+
if (f.symbol_id and f.symbol_id in {s.id for s in syms}) or (
|
|
114
|
+
f.location and target_sym.location and f.location.file_id == target_sym.location.file_id
|
|
115
|
+
)
|
|
114
116
|
]
|
|
115
117
|
|
|
116
118
|
manifest = {
|
|
@@ -147,7 +149,7 @@ class ContextBuilder:
|
|
|
147
149
|
bodies[s.id] = f"{cm} {file_id}:{s.location.start_line if s.location else 1}\n{s.signature or s.name}"
|
|
148
150
|
relevant_findings = [
|
|
149
151
|
f.to_dict() for f in self.graph.get_findings()
|
|
150
|
-
if f.location.file_id == file_id
|
|
152
|
+
if f.location and f.location.file_id == file_id
|
|
151
153
|
]
|
|
152
154
|
return ContextBundle(
|
|
153
155
|
symbol_bodies=bodies,
|
|
@@ -189,6 +191,18 @@ class ContextBuilder:
|
|
|
189
191
|
manifest={"query": task.query, "symbols": task.target_symbols, "files": task.target_files},
|
|
190
192
|
)
|
|
191
193
|
|
|
194
|
+
def build_context(self, task: TaskSpec, depth: int = 1) -> ContextBundle:
|
|
195
|
+
"""Alias for for_task to build context bundle.
|
|
196
|
+
Example:
|
|
197
|
+
>>> g = Graph()
|
|
198
|
+
>>> builder = ContextBuilder(g)
|
|
199
|
+
>>> spec = TaskSpec("Fix issue")
|
|
200
|
+
>>> bundle = builder.build_context(spec)
|
|
201
|
+
>>> "query" in bundle.manifest
|
|
202
|
+
True
|
|
203
|
+
"""
|
|
204
|
+
return self.for_task(task, depth=depth)
|
|
205
|
+
|
|
192
206
|
def for_defect(self, finding_id: str) -> ContextBundle:
|
|
193
207
|
"""Build context bundle targeting a specific defect finding.
|
|
194
208
|
Example:
|
|
@@ -204,4 +218,6 @@ class ContextBuilder:
|
|
|
204
218
|
f = matching[0]
|
|
205
219
|
if f.symbol_id:
|
|
206
220
|
return self.for_symbol(f.symbol_id, depth=1)
|
|
207
|
-
|
|
221
|
+
if f.location and f.location.file_id:
|
|
222
|
+
return self.for_file(f.location.file_id, depth=1)
|
|
223
|
+
return ContextBundle({}, {}, [], [], {"finding_id": finding_id, "status": "no_location"})
|
|
@@ -3,7 +3,7 @@ from pathlib import Path
|
|
|
3
3
|
from typing import ClassVar, Iterable, List, Set
|
|
4
4
|
from codeui.analysis.base import AnalysisContext, Analyzer
|
|
5
5
|
from codeui.core.graph import Graph
|
|
6
|
-
from codeui.core.ir import EdgeKind, Finding, Location, Severity, SymbolKind, Visibility
|
|
6
|
+
from codeui.core.ir import EdgeKind, Finding, LayerKind, Location, Severity, SymbolKind, Visibility
|
|
7
7
|
|
|
8
8
|
class DeadCodeAnalyzer(Analyzer):
|
|
9
9
|
"""Detects unused functions, unused private symbols, and orphan files.
|
|
@@ -22,7 +22,10 @@ class DeadCodeAnalyzer(Analyzer):
|
|
|
22
22
|
"__init__", "__post_init__", "__str__", "__repr__", "__eq__", "__hash__",
|
|
23
23
|
"__iter__", "__getitem__", "__setitem__", "__delitem__", "__len__",
|
|
24
24
|
"__contains__", "__enter__", "__exit__", "__call__", "__await__",
|
|
25
|
-
"constructor", "init", "dispose", "render", "
|
|
25
|
+
"constructor", "init", "dispose", "render", "build", "initialize",
|
|
26
|
+
"setup", "teardown", "setUp", "tearDown", "beforeEach", "afterEach",
|
|
27
|
+
"beforeAll", "afterAll", "onCreate", "onDestroy", "onStart", "onStop",
|
|
28
|
+
"onResume", "onPause", "componentDidMount", "componentWillUnmount"
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
def run(self, graph: Graph, ctx: AnalysisContext) -> Iterable[Finding]:
|
|
@@ -43,6 +46,14 @@ class DeadCodeAnalyzer(Analyzer):
|
|
|
43
46
|
referenced_targets.add(raw_target.split(".")[-1])
|
|
44
47
|
|
|
45
48
|
for sym in graph.get_all_symbols():
|
|
49
|
+
if sym.location and sym.location.file_id:
|
|
50
|
+
cls = graph.get_file_classification(sym.location.file_id)
|
|
51
|
+
if cls.layer in (LayerKind.TEST, LayerKind.CONFIG):
|
|
52
|
+
continue
|
|
53
|
+
file_lower = sym.location.file_id.replace("\\", "/").lower()
|
|
54
|
+
if any(p in file_lower for p in ("/tests/", "/test/", "/benches/", "/bench/", "/examples/", "/example/", "/fixtures/")):
|
|
55
|
+
continue
|
|
56
|
+
|
|
46
57
|
if sym.kind in (SymbolKind.FUNCTION, SymbolKind.METHOD, SymbolKind.CLASS):
|
|
47
58
|
if sym.name in self.ENTRY_POINTS or any(sym.name.startswith(p) for p in self.ENTRY_POINTS):
|
|
48
59
|
continue
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""Undefined symbol analyzer."""
|
|
2
|
+
import builtins
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import ClassVar, Iterable, List, Set
|
|
5
|
+
from codeui.analysis.base import AnalysisContext, Analyzer
|
|
6
|
+
from codeui.core.graph import Graph
|
|
7
|
+
from codeui.core.ir import EdgeKind, Finding, Location, Severity
|
|
8
|
+
|
|
9
|
+
class UndefinedSymbolAnalyzer(Analyzer):
|
|
10
|
+
"""Detects references or calls to undefined symbols.
|
|
11
|
+
Example:
|
|
12
|
+
>>> analyzer = UndefinedSymbolAnalyzer()
|
|
13
|
+
>>> g = Graph()
|
|
14
|
+
>>> ctx = AnalysisContext(Path("."))
|
|
15
|
+
>>> list(analyzer.run(g, ctx))
|
|
16
|
+
[]
|
|
17
|
+
"""
|
|
18
|
+
id: ClassVar[str] = "undefined"
|
|
19
|
+
severity_default: ClassVar[Severity] = Severity.ERROR
|
|
20
|
+
|
|
21
|
+
PYTHON_BUILTINS = set(dir(builtins)) | {
|
|
22
|
+
"Optional", "List", "Dict", "Set", "Tuple", "Any", "Callable", "Union",
|
|
23
|
+
"Sequence", "Iterable", "Mapping", "Type", "ClassVar", "Literal", "Self",
|
|
24
|
+
"dataclass", "field", "asdict", "Path", "Enum", "auto", "StrEnum",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
JS_BUILTINS = {
|
|
28
|
+
"console", "window", "document", "Math", "JSON", "Object", "Array", "String",
|
|
29
|
+
"Number", "Boolean", "Symbol", "Map", "Set", "WeakMap", "WeakSet", "Proxy",
|
|
30
|
+
"Reflect", "Promise", "Error", "TypeError", "RangeError", "SyntaxError",
|
|
31
|
+
"encodeURIComponent", "decodeURIComponent", "encodeURI", "decodeURI",
|
|
32
|
+
"fetch", "setTimeout", "clearTimeout", "setInterval", "clearInterval",
|
|
33
|
+
"Element", "HTMLElement", "Event", "CustomEvent", "URLSearchParams",
|
|
34
|
+
"FormData", "Headers", "Request", "Response", "Blob", "File", "FileReader",
|
|
35
|
+
"localStorage", "sessionStorage", "location", "history", "globalThis",
|
|
36
|
+
"process", "Buffer", "require", "exports", "module", "undefined", "NaN", "Infinity",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
OTHER_BUILTINS = {
|
|
40
|
+
"fmt", "make", "new", "println", "println!", "format!", "vec!", "panic!",
|
|
41
|
+
"main", "self", "this", "super", "__name__", "__file__", "__doc__", "__all__"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
BUILTINS = PYTHON_BUILTINS | JS_BUILTINS | OTHER_BUILTINS
|
|
45
|
+
|
|
46
|
+
def run(self, graph: Graph, ctx: AnalysisContext) -> Iterable[Finding]:
|
|
47
|
+
"""Identify missing symbol references.
|
|
48
|
+
Example:
|
|
49
|
+
>>> analyzer = UndefinedSymbolAnalyzer()
|
|
50
|
+
>>> g = Graph()
|
|
51
|
+
>>> list(analyzer.run(g, AnalysisContext(Path("."))))
|
|
52
|
+
[]
|
|
53
|
+
"""
|
|
54
|
+
findings: List[Finding] = []
|
|
55
|
+
all_symbol_names = {s.name for s in graph.get_all_symbols()}
|
|
56
|
+
all_symbol_names.update(self.BUILTINS)
|
|
57
|
+
file_imports: dict[str, Set[str]] = {}
|
|
58
|
+
for edge in graph.get_edges():
|
|
59
|
+
if edge.kind == EdgeKind.IMPORTS:
|
|
60
|
+
src_file = edge.source_id.split("::")[0]
|
|
61
|
+
file_imports.setdefault(src_file, set())
|
|
62
|
+
raw_mod = edge.target_id.replace("module::", "")
|
|
63
|
+
imported = raw_mod.split(".")[-1]
|
|
64
|
+
file_imports[src_file].add(imported)
|
|
65
|
+
for part in raw_mod.split("."):
|
|
66
|
+
file_imports[src_file].add(part)
|
|
67
|
+
|
|
68
|
+
for edge in graph.get_edges():
|
|
69
|
+
if edge.kind in (EdgeKind.CALLS, EdgeKind.REFERENCES):
|
|
70
|
+
target_id = edge.target_id
|
|
71
|
+
if target_id.startswith("module::"):
|
|
72
|
+
continue
|
|
73
|
+
target_name = target_id.split("::")[-1]
|
|
74
|
+
src_file = edge.source_id.split("::")[0]
|
|
75
|
+
|
|
76
|
+
if "." in target_name:
|
|
77
|
+
continue
|
|
78
|
+
|
|
79
|
+
local_names = set()
|
|
80
|
+
try:
|
|
81
|
+
caller_sym = graph.get_symbol(edge.source_id)
|
|
82
|
+
if caller_sym and caller_sym.kind in (SymbolKind.FUNCTION, SymbolKind.METHOD):
|
|
83
|
+
file_path = ctx.root_dir / caller_sym.location.file_id
|
|
84
|
+
if file_path.exists():
|
|
85
|
+
import ast
|
|
86
|
+
source = file_path.read_text(encoding="utf-8")
|
|
87
|
+
tree = ast.parse(source)
|
|
88
|
+
for node in ast.walk(tree):
|
|
89
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and node.lineno == caller_sym.location.start_line:
|
|
90
|
+
for arg in getattr(node.args, "posonlyargs", []) + getattr(node.args, "args", []) + getattr(node.args, "kwonlyargs", []):
|
|
91
|
+
if hasattr(arg, "arg"):
|
|
92
|
+
local_names.add(arg.arg)
|
|
93
|
+
if getattr(node.args, "vararg", None):
|
|
94
|
+
local_names.add(node.args.vararg.arg)
|
|
95
|
+
if getattr(node.args, "kwarg", None):
|
|
96
|
+
local_names.add(node.args.kwarg.arg)
|
|
97
|
+
|
|
98
|
+
for subnode in ast.walk(node):
|
|
99
|
+
if isinstance(subnode, ast.Assign):
|
|
100
|
+
for target in subnode.targets:
|
|
101
|
+
if isinstance(target, ast.Name):
|
|
102
|
+
local_names.add(target.id)
|
|
103
|
+
elif isinstance(target, (ast.Tuple, ast.List)):
|
|
104
|
+
def _ext_names(t):
|
|
105
|
+
res = set()
|
|
106
|
+
if isinstance(t, ast.Name): res.add(t.id)
|
|
107
|
+
elif isinstance(t, (ast.Tuple, ast.List)):
|
|
108
|
+
for e in t.elts: res.update(_ext_names(e))
|
|
109
|
+
return res
|
|
110
|
+
local_names.update(_ext_names(target))
|
|
111
|
+
elif isinstance(subnode, ast.AnnAssign):
|
|
112
|
+
if isinstance(subnode.target, ast.Name):
|
|
113
|
+
local_names.add(subnode.target.id)
|
|
114
|
+
elif isinstance(subnode, (ast.For, ast.AsyncFor)):
|
|
115
|
+
def _ext_names(t):
|
|
116
|
+
res = set()
|
|
117
|
+
if isinstance(t, ast.Name): res.add(t.id)
|
|
118
|
+
elif isinstance(t, (ast.Tuple, ast.List)):
|
|
119
|
+
for e in t.elts: res.update(_ext_names(e))
|
|
120
|
+
return res
|
|
121
|
+
local_names.update(_ext_names(subnode.target))
|
|
122
|
+
elif isinstance(subnode, (ast.With, ast.AsyncWith)):
|
|
123
|
+
for item in subnode.items:
|
|
124
|
+
if item.optional_vars:
|
|
125
|
+
def _ext_names(t):
|
|
126
|
+
res = set()
|
|
127
|
+
if isinstance(t, ast.Name): res.add(t.id)
|
|
128
|
+
elif isinstance(t, (ast.Tuple, ast.List)):
|
|
129
|
+
for e in t.elts: res.update(_ext_names(e))
|
|
130
|
+
return res
|
|
131
|
+
local_names.update(_ext_names(item.optional_vars))
|
|
132
|
+
elif isinstance(subnode, ast.ExceptHandler):
|
|
133
|
+
if subnode.name:
|
|
134
|
+
local_names.add(subnode.name)
|
|
135
|
+
elif isinstance(subnode, (ast.ListComp, ast.SetComp, ast.DictComp, ast.GeneratorExp)):
|
|
136
|
+
for gen in subnode.generators:
|
|
137
|
+
def _ext_names(t):
|
|
138
|
+
res = set()
|
|
139
|
+
if isinstance(t, ast.Name): res.add(t.id)
|
|
140
|
+
elif isinstance(t, (ast.Tuple, ast.List)):
|
|
141
|
+
for e in t.elts: res.update(_ext_names(e))
|
|
142
|
+
return res
|
|
143
|
+
local_names.update(_ext_names(gen.target))
|
|
144
|
+
break
|
|
145
|
+
except Exception:
|
|
146
|
+
pass
|
|
147
|
+
|
|
148
|
+
if (
|
|
149
|
+
not graph.has_symbol(target_id)
|
|
150
|
+
and target_name not in all_symbol_names
|
|
151
|
+
and target_name not in file_imports.get(src_file, set())
|
|
152
|
+
and target_name not in local_names
|
|
153
|
+
and not target_name.startswith("_")
|
|
154
|
+
):
|
|
155
|
+
loc = edge.location or Location(edge.source_id, 1, 0, 1, 0)
|
|
156
|
+
finding = Finding(
|
|
157
|
+
id=f"undefined::{target_id}",
|
|
158
|
+
rule_id="undefined_symbol",
|
|
159
|
+
message=f"Undefined symbol '{target_name}' referenced",
|
|
160
|
+
severity=self.severity_default,
|
|
161
|
+
location=loc,
|
|
162
|
+
symbol_id=edge.source_id,
|
|
163
|
+
fix_hint=f"Define symbol '{target_name}' or import it from module",
|
|
164
|
+
confidence=0.9,
|
|
165
|
+
)
|
|
166
|
+
findings.append(finding)
|
|
167
|
+
return findings
|