pycode-kg 0.19.3__tar.gz → 0.21.0__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.
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/PKG-INFO +16 -19
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/README.md +8 -7
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/pyproject.toml +56 -47
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/__init__.py +3 -3
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/analysis/__init__.py +6 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/analysis/bridge.py +1 -1
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/analysis/centrality.py +1 -1
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/analysis/framework_detector.py +2 -2
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/app.py +122 -394
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/architecture.py +1 -1
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/__init__.py +1 -1
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_analyze.py +4 -4
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_architecture.py +1 -1
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_build.py +17 -21
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_build_full.py +14 -24
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_explain.py +4 -12
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_hooks.py +11 -27
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_init.py +4 -7
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_mcp.py +8 -8
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_model.py +2 -2
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_query.py +9 -27
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_snapshot.py +0 -1
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_viz.py +109 -2
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/options.py +6 -6
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/explain.py +2 -8
- pycode_kg-0.21.0/src/pycode_kg/graph_html.py +131 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/kg.py +15 -17
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/layout3d.py +6 -16
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/mcp_server.py +55 -55
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/module/__init__.py +1 -1
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/module/extractor.py +2 -2
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg.py +1 -1
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg_thorough_analysis.py +23 -23
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/snapshots.py +1 -1
- pycode_kg-0.21.0/src/pycode_kg/theme.py +188 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/viz3d.py +93 -36
- pycode_kg-0.19.3/src/pycode_kg/build_pycodekg_lancedb.py +0 -15
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/LICENSE +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/.DS_Store +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/__main__.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/analysis/hybrid_rank.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/build_pycodekg_sqlite.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_bridges.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_centrality.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_framework_nodes.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/main.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/config.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/graph.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/index.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/module/base.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/module/types.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg_query.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg_snippet_packer.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg_viz.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg_viz3d.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/ranking/__init__.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/ranking/cli_rank.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/ranking/coderank.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/sql/004_add_centrality_table.sql +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/store.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/utils.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/visitor.py +0 -0
- {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/viz3d_timeline.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pycode-kg
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.21.0
|
|
4
4
|
Summary: A tool to build a searchable knowledge graph from Python repositories
|
|
5
5
|
License-Expression: Elastic-2.0
|
|
6
6
|
License-File: LICENSE
|
|
7
|
-
Keywords: knowledge-graph,code-analysis,ast,
|
|
7
|
+
Keywords: knowledge-graph,code-analysis,ast,sqlite-vec,sqlite,semantic-search
|
|
8
8
|
Author: Eric G. Suchanek, PhD
|
|
9
|
-
Author-email: suchanek@
|
|
9
|
+
Author-email: suchanek@flux-frontiers.com
|
|
10
10
|
Requires-Python: >=3.12,<3.14
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -17,7 +17,6 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Provides-Extra: all
|
|
19
19
|
Provides-Extra: dev
|
|
20
|
-
Provides-Extra: kgdeps
|
|
21
20
|
Provides-Extra: viz
|
|
22
21
|
Provides-Extra: viz3d
|
|
23
22
|
Requires-Dist: PyQt5 (>=5.15.0) ; extra == "all"
|
|
@@ -25,12 +24,11 @@ Requires-Dist: PyQt5 (>=5.15.0) ; extra == "viz3d"
|
|
|
25
24
|
Requires-Dist: click (>=8.1.0,<9)
|
|
26
25
|
Requires-Dist: detect-secrets (>=1.5.0) ; extra == "all"
|
|
27
26
|
Requires-Dist: detect-secrets (>=1.5.0) ; extra == "dev"
|
|
28
|
-
Requires-Dist:
|
|
29
|
-
Requires-Dist: doc-kg (>=0.15.2) ; extra == "kgdeps"
|
|
30
|
-
Requires-Dist: kgmodule-utils[semantic] (>=0.3.1)
|
|
27
|
+
Requires-Dist: kgmodule-utils[semantic,sqlite-vec,viz] (>=0.9.0)
|
|
31
28
|
Requires-Dist: markdown (>=3.6) ; extra == "all"
|
|
32
29
|
Requires-Dist: markdown (>=3.6) ; extra == "viz3d"
|
|
33
30
|
Requires-Dist: mcp (>=1.0.0)
|
|
31
|
+
Requires-Dist: networkx (>=3.0)
|
|
34
32
|
Requires-Dist: numpy (>=1.24.0)
|
|
35
33
|
Requires-Dist: pandas (>=2.0.0)
|
|
36
34
|
Requires-Dist: param (>=2.0.0) ; extra == "all"
|
|
@@ -41,8 +39,6 @@ Requires-Dist: plotly (>=5.14.0) ; extra == "all"
|
|
|
41
39
|
Requires-Dist: plotly (>=5.14.0) ; extra == "viz"
|
|
42
40
|
Requires-Dist: pre-commit (>=4.5.1) ; extra == "all"
|
|
43
41
|
Requires-Dist: pre-commit (>=4.5.1) ; extra == "dev"
|
|
44
|
-
Requires-Dist: pylint (>=4.0.5) ; extra == "all"
|
|
45
|
-
Requires-Dist: pylint (>=4.0.5) ; extra == "dev"
|
|
46
42
|
Requires-Dist: pytest (>=8.0.0) ; extra == "all"
|
|
47
43
|
Requires-Dist: pytest (>=8.0.0) ; extra == "dev"
|
|
48
44
|
Requires-Dist: pytest-cov (>=5.0.0) ; extra == "all"
|
|
@@ -58,12 +54,12 @@ Requires-Dist: ruff (>=0.4.0) ; extra == "all"
|
|
|
58
54
|
Requires-Dist: ruff (>=0.4.0) ; extra == "dev"
|
|
59
55
|
Requires-Dist: safetensors (>=0.5.0)
|
|
60
56
|
Requires-Dist: sentence-transformers (>=5.4.1)
|
|
61
|
-
Requires-Dist: streamlit (>=1.
|
|
62
|
-
Requires-Dist: streamlit (>=1.
|
|
57
|
+
Requires-Dist: streamlit (>=1.56.0) ; extra == "all"
|
|
58
|
+
Requires-Dist: streamlit (>=1.56.0) ; extra == "viz"
|
|
63
59
|
Requires-Dist: torch (>=2.5.1)
|
|
64
60
|
Requires-Dist: trame-vtk (>=2.0.0) ; extra == "all"
|
|
65
61
|
Requires-Dist: trame-vtk (>=2.0.0) ; extra == "viz3d"
|
|
66
|
-
Requires-Dist: transformers (>=
|
|
62
|
+
Requires-Dist: transformers (>=5.5.0,<6)
|
|
67
63
|
Requires-Dist: ty (>=0.0.41) ; extra == "all"
|
|
68
64
|
Requires-Dist: ty (>=0.0.41) ; extra == "dev"
|
|
69
65
|
Project-URL: Homepage, https://github.com/Flux-Frontiers/pycode_kg
|
|
@@ -77,7 +73,7 @@ Description-Content-Type: text/markdown
|
|
|
77
73
|
|
|
78
74
|
[](https://www.python.org/)
|
|
79
75
|
[](https://www.elastic.co/licensing/elastic-license)
|
|
80
|
-
[](https://github.com/Flux-Frontiers/pycode_kg/releases)
|
|
81
77
|
[](https://github.com/Flux-Frontiers/pycode_kg/actions/workflows/ci.yml)
|
|
82
78
|
[](https://python-poetry.org/)
|
|
83
79
|
[](https://zenodo.org/badge/latestdoi/1202379010)
|
|
@@ -86,7 +82,7 @@ Description-Content-Type: text/markdown
|
|
|
86
82
|
|
|
87
83
|
**PyCodeKG turns a Python codebase into a deterministic, queryable knowledge graph — and uses it to produce architectural analyses you can act on, with or without an LLM in the loop.**
|
|
88
84
|
|
|
89
|
-
It walks the AST of every module, class, function, and method in your repo, extracts the typed relationships that actually hold the code together (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`), and stores the result in SQLite. A
|
|
85
|
+
It walks the AST of every module, class, function, and method in your repo, extracts the typed relationships that actually hold the code together (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`), and stores the result in SQLite. A sqlite-vec vector index sits alongside the graph so that *"authentication flow"* and *"verify_jwt"* both find the right place to start exploring. From there you can rank functions by structural importance, trace fan-in across import aliases, detect circular imports and dead code, render the call graph in 3D, snapshot metrics for diffing across releases, or hand the whole thing to Claude over MCP.
|
|
90
86
|
|
|
91
87
|
The original motivation was simple: **produce thorough, defensible analyses of Python codebases that don't depend on inference**. Every result is computed from the AST and the graph — no model is asked to guess. When an LLM is present, it consumes the *same* grounded output as a structured context pack, and the hallucinations that plague "embed-the-repo" tools largely disappear.
|
|
92
88
|
|
|
@@ -197,7 +193,7 @@ That's the recommended path. Variants (minimal install, MCP-only, contributor se
|
|
|
197
193
|
|
|
198
194
|
Search is hybrid by design. A query like *"authentication flow"* runs in two phases:
|
|
199
195
|
|
|
200
|
-
1. **Vector phase** — the query is embedded with a local sentence-transformer (cached after first download) and
|
|
196
|
+
1. **Vector phase** — the query is embedded with a local sentence-transformer (cached after first download) and sqlite-vec returns the `k` closest functions, classes, and modules by exact cosine similarity.
|
|
201
197
|
2. **Graph expansion phase** — each seed hit is expanded `hop` BFS steps along the typed edges (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`) so call chains and module relationships surface alongside the names that matched.
|
|
202
198
|
|
|
203
199
|
**Structure is treated as ground truth; the embeddings are strictly an acceleration layer.** When the graph and the vector index disagree, the graph wins. This is why fan-in lookups are accurate even for same-named symbols across modules — `RESOLVES_TO` edges bridge call sites through their import aliases, and `callers()` does a two-phase reverse traversal that grep simply cannot replicate.
|
|
@@ -217,6 +213,7 @@ The graph is built around four node kinds (module, class, function, method) and
|
|
|
217
213
|
| **Pull source-grounded context for an LLM** | `pycodekg pack "..." --format md` | [docs/CHEATSHEET.md](docs/CHEATSHEET.md) |
|
|
218
214
|
| **Run a hybrid semantic + structural query** | `pycodekg query "..."` | [docs/CHEATSHEET.md](docs/CHEATSHEET.md) |
|
|
219
215
|
| **Browse the graph interactively** | `pycodekg viz` (Streamlit) | [docs/INSTALLATION.md](docs/INSTALLATION.md) |
|
|
216
|
+
| **Share a graph as one file** | `pycodekg viz-export -o graph.html` | opens from `file://`, no server |
|
|
220
217
|
| **See call graphs in 3-D** *(active development — functional but rough)* | `pycodekg viz3d --layout funnel` | [docs/VIZ3D.md](docs/VIZ3D.md) |
|
|
221
218
|
| **Wire it into Claude / Copilot / Cline** | `pycodekg mcp` | [docs/MCP.md](docs/MCP.md) |
|
|
222
219
|
|
|
@@ -231,7 +228,7 @@ src/pycode_kg/
|
|
|
231
228
|
├── visitor.py # AST extraction (three-pass: structure, calls, dataflow)
|
|
232
229
|
├── graph.py # GraphBuilder: file discovery + dispatch
|
|
233
230
|
├── store.py # SQLite persistence + canonical edges
|
|
234
|
-
├── index.py #
|
|
231
|
+
├── index.py # sqlite-vec semantic index
|
|
235
232
|
├── pycodekg.py # Public façade
|
|
236
233
|
├── pycodekg_query.py # Hybrid query
|
|
237
234
|
├── pycodekg_snippet_packer.py # Source-grounded packs
|
|
@@ -273,13 +270,13 @@ If you use PyCodeKG in your research or project, please cite it:
|
|
|
273
270
|
|
|
274
271
|
[](https://zenodo.org/badge/latestdoi/1202379010)
|
|
275
272
|
|
|
276
|
-
> Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.
|
|
273
|
+
> Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.21.0) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.19834777
|
|
277
274
|
|
|
278
275
|
```bibtex
|
|
279
276
|
@software{suchanek_pycode_kg,
|
|
280
277
|
author = {Suchanek, Eric G.},
|
|
281
278
|
title = {{PyCodeKG}: A Knowledge Graph for Python Codebases},
|
|
282
|
-
version = {0.
|
|
279
|
+
version = {0.21.0},
|
|
283
280
|
year = {2026},
|
|
284
281
|
publisher = {Flux-Frontiers},
|
|
285
282
|
url = {https://github.com/Flux-Frontiers/pycode_kg},
|
|
@@ -299,7 +296,7 @@ If you use PyCodeKG in your research or project, please cite it:
|
|
|
299
296
|
|
|
300
297
|
- **Issues** — [GitHub Issues](https://github.com/Flux-Frontiers/pycode_kg/issues)
|
|
301
298
|
- Sister projects [DocKG](https://github.com/Flux-Frontiers/doc_kg) and [MetaboKG](https://github.com/Flux-Frontiers/metabo_kg)
|
|
302
|
-
-
|
|
299
|
+
- sqlite-vec, sentence-transformers, PyVista, Streamlit, and FastMCP for the foundations
|
|
303
300
|
|
|
304
301
|
---
|
|
305
302
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
[](https://www.python.org/)
|
|
7
7
|
[](https://www.elastic.co/licensing/elastic-license)
|
|
8
|
-
[](https://github.com/Flux-Frontiers/pycode_kg/releases)
|
|
9
9
|
[](https://github.com/Flux-Frontiers/pycode_kg/actions/workflows/ci.yml)
|
|
10
10
|
[](https://python-poetry.org/)
|
|
11
11
|
[](https://zenodo.org/badge/latestdoi/1202379010)
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
**PyCodeKG turns a Python codebase into a deterministic, queryable knowledge graph — and uses it to produce architectural analyses you can act on, with or without an LLM in the loop.**
|
|
16
16
|
|
|
17
|
-
It walks the AST of every module, class, function, and method in your repo, extracts the typed relationships that actually hold the code together (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`), and stores the result in SQLite. A
|
|
17
|
+
It walks the AST of every module, class, function, and method in your repo, extracts the typed relationships that actually hold the code together (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`), and stores the result in SQLite. A sqlite-vec vector index sits alongside the graph so that *"authentication flow"* and *"verify_jwt"* both find the right place to start exploring. From there you can rank functions by structural importance, trace fan-in across import aliases, detect circular imports and dead code, render the call graph in 3D, snapshot metrics for diffing across releases, or hand the whole thing to Claude over MCP.
|
|
18
18
|
|
|
19
19
|
The original motivation was simple: **produce thorough, defensible analyses of Python codebases that don't depend on inference**. Every result is computed from the AST and the graph — no model is asked to guess. When an LLM is present, it consumes the *same* grounded output as a structured context pack, and the hallucinations that plague "embed-the-repo" tools largely disappear.
|
|
20
20
|
|
|
@@ -125,7 +125,7 @@ That's the recommended path. Variants (minimal install, MCP-only, contributor se
|
|
|
125
125
|
|
|
126
126
|
Search is hybrid by design. A query like *"authentication flow"* runs in two phases:
|
|
127
127
|
|
|
128
|
-
1. **Vector phase** — the query is embedded with a local sentence-transformer (cached after first download) and
|
|
128
|
+
1. **Vector phase** — the query is embedded with a local sentence-transformer (cached after first download) and sqlite-vec returns the `k` closest functions, classes, and modules by exact cosine similarity.
|
|
129
129
|
2. **Graph expansion phase** — each seed hit is expanded `hop` BFS steps along the typed edges (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`) so call chains and module relationships surface alongside the names that matched.
|
|
130
130
|
|
|
131
131
|
**Structure is treated as ground truth; the embeddings are strictly an acceleration layer.** When the graph and the vector index disagree, the graph wins. This is why fan-in lookups are accurate even for same-named symbols across modules — `RESOLVES_TO` edges bridge call sites through their import aliases, and `callers()` does a two-phase reverse traversal that grep simply cannot replicate.
|
|
@@ -145,6 +145,7 @@ The graph is built around four node kinds (module, class, function, method) and
|
|
|
145
145
|
| **Pull source-grounded context for an LLM** | `pycodekg pack "..." --format md` | [docs/CHEATSHEET.md](docs/CHEATSHEET.md) |
|
|
146
146
|
| **Run a hybrid semantic + structural query** | `pycodekg query "..."` | [docs/CHEATSHEET.md](docs/CHEATSHEET.md) |
|
|
147
147
|
| **Browse the graph interactively** | `pycodekg viz` (Streamlit) | [docs/INSTALLATION.md](docs/INSTALLATION.md) |
|
|
148
|
+
| **Share a graph as one file** | `pycodekg viz-export -o graph.html` | opens from `file://`, no server |
|
|
148
149
|
| **See call graphs in 3-D** *(active development — functional but rough)* | `pycodekg viz3d --layout funnel` | [docs/VIZ3D.md](docs/VIZ3D.md) |
|
|
149
150
|
| **Wire it into Claude / Copilot / Cline** | `pycodekg mcp` | [docs/MCP.md](docs/MCP.md) |
|
|
150
151
|
|
|
@@ -159,7 +160,7 @@ src/pycode_kg/
|
|
|
159
160
|
├── visitor.py # AST extraction (three-pass: structure, calls, dataflow)
|
|
160
161
|
├── graph.py # GraphBuilder: file discovery + dispatch
|
|
161
162
|
├── store.py # SQLite persistence + canonical edges
|
|
162
|
-
├── index.py #
|
|
163
|
+
├── index.py # sqlite-vec semantic index
|
|
163
164
|
├── pycodekg.py # Public façade
|
|
164
165
|
├── pycodekg_query.py # Hybrid query
|
|
165
166
|
├── pycodekg_snippet_packer.py # Source-grounded packs
|
|
@@ -201,13 +202,13 @@ If you use PyCodeKG in your research or project, please cite it:
|
|
|
201
202
|
|
|
202
203
|
[](https://zenodo.org/badge/latestdoi/1202379010)
|
|
203
204
|
|
|
204
|
-
> Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.
|
|
205
|
+
> Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.21.0) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.19834777
|
|
205
206
|
|
|
206
207
|
```bibtex
|
|
207
208
|
@software{suchanek_pycode_kg,
|
|
208
209
|
author = {Suchanek, Eric G.},
|
|
209
210
|
title = {{PyCodeKG}: A Knowledge Graph for Python Codebases},
|
|
210
|
-
version = {0.
|
|
211
|
+
version = {0.21.0},
|
|
211
212
|
year = {2026},
|
|
212
213
|
publisher = {Flux-Frontiers},
|
|
213
214
|
url = {https://github.com/Flux-Frontiers/pycode_kg},
|
|
@@ -227,7 +228,7 @@ If you use PyCodeKG in your research or project, please cite it:
|
|
|
227
228
|
|
|
228
229
|
- **Issues** — [GitHub Issues](https://github.com/Flux-Frontiers/pycode_kg/issues)
|
|
229
230
|
- Sister projects [DocKG](https://github.com/Flux-Frontiers/doc_kg) and [MetaboKG](https://github.com/Flux-Frontiers/metabo_kg)
|
|
230
|
-
-
|
|
231
|
+
- sqlite-vec, sentence-transformers, PyVista, Streamlit, and FastMCP for the foundations
|
|
231
232
|
|
|
232
233
|
---
|
|
233
234
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# pyproject.toml — PyCodeKG package configuration (PEP 621)
|
|
2
2
|
#
|
|
3
3
|
# Author: Eric G. Suchanek, PhD
|
|
4
|
-
# Last Revision: 2026-
|
|
4
|
+
# Last Revision: 2026-07-28
|
|
5
5
|
#
|
|
6
6
|
# Build system : Poetry 2.x with PEP 621 [project] table
|
|
7
7
|
#
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
# pip install -e ".[dev]" core + dev tools (pytest, ruff, ty, etc.)
|
|
11
11
|
# pip install -e ".[viz]" core + Streamlit/Plotly/PyVis visualizer
|
|
12
12
|
# pip install -e ".[viz3d]" core + PyVista 3D visualizer
|
|
13
|
-
# pip install -e ".[kgdeps]" core + KG integrations (doc-kg, agent-kg)
|
|
14
13
|
# pip install -e ".[all]" everything above
|
|
15
14
|
# pip install -e "." core runtime only
|
|
16
15
|
#
|
|
@@ -20,7 +19,6 @@
|
|
|
20
19
|
# poetry install --extras "dev" core + dev tools only
|
|
21
20
|
# poetry install --extras "viz" core + Streamlit/Plotly visualizer only
|
|
22
21
|
# poetry install --extras "viz3d" core + 3D visualizer only
|
|
23
|
-
# poetry install --extras "kgdeps" core + KG integrations only
|
|
24
22
|
# poetry install core runtime only
|
|
25
23
|
#
|
|
26
24
|
# First-time setup
|
|
@@ -46,29 +44,40 @@ build-backend = "poetry.core.masonry.api"
|
|
|
46
44
|
[tool.poetry]
|
|
47
45
|
packages = [{ include = "pycode_kg", from = "src" }]
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
# CPU-only torch on Linux: dev/CI here has no GPU, but the default PyPI linux
|
|
48
|
+
# wheel bundles the full CUDA runtime (~2.7G of nvidia-* packages, ~700M of
|
|
49
|
+
# triton) regardless. "explicit" priority means only packages naming this
|
|
50
|
+
# source use it — nothing else is redirected off PyPI. This affects local/CI
|
|
51
|
+
# installs only; it is not part of published wheel metadata, so `pip install
|
|
52
|
+
# pycode-kg` for a GPU user still resolves torch normally.
|
|
53
|
+
#
|
|
54
|
+
# Linux only: macOS/Windows torch builds are already CPU/MPS, and this index
|
|
55
|
+
# publishes the macOS ones without the "+cpu" local version label, so locking
|
|
56
|
+
# it globally leaves those platforms with no installable candidate.
|
|
57
|
+
[[tool.poetry.source]]
|
|
58
|
+
name = "pytorch-cpu"
|
|
59
|
+
url = "https://download.pytorch.org/whl/cpu"
|
|
60
|
+
priority = "explicit"
|
|
61
|
+
|
|
62
|
+
[tool.poetry.dependencies]
|
|
63
|
+
torch = [
|
|
64
|
+
{ markers = "sys_platform == 'linux'", source = "pytorch-cpu" },
|
|
65
|
+
{ markers = "sys_platform != 'linux'" },
|
|
66
|
+
]
|
|
58
67
|
|
|
59
68
|
# ---------------------------------------------------------------------------
|
|
60
69
|
# PEP 621 project metadata
|
|
61
70
|
# ---------------------------------------------------------------------------
|
|
62
71
|
[project]
|
|
63
72
|
name = "pycode-kg"
|
|
64
|
-
version = "0.
|
|
73
|
+
version = "0.21.0"
|
|
65
74
|
description = "A tool to build a searchable knowledge graph from Python repositories"
|
|
66
75
|
readme = "README.md"
|
|
67
76
|
license = "Elastic-2.0"
|
|
68
77
|
authors = [
|
|
69
|
-
{ name = "Eric G. Suchanek, PhD", email = "suchanek@
|
|
78
|
+
{ name = "Eric G. Suchanek, PhD", email = "suchanek@flux-frontiers.com" }
|
|
70
79
|
]
|
|
71
|
-
keywords = ["knowledge-graph", "code-analysis", "ast", "
|
|
80
|
+
keywords = ["knowledge-graph", "code-analysis", "ast", "sqlite-vec", "sqlite", "semantic-search"]
|
|
72
81
|
classifiers = [
|
|
73
82
|
"Development Status :: 4 - Beta",
|
|
74
83
|
"Intended Audience :: Developers",
|
|
@@ -82,14 +91,15 @@ requires-python = ">=3.12,<3.14"
|
|
|
82
91
|
dependencies = [
|
|
83
92
|
"click>=8.1.0,<9",
|
|
84
93
|
"mcp>=1.0.0",
|
|
94
|
+
"networkx>=3.0",
|
|
85
95
|
"numpy>=1.24.0",
|
|
86
96
|
"pandas>=2.0.0",
|
|
87
97
|
"rich>=14.3.3,<15",
|
|
88
98
|
"safetensors>=0.5.0",
|
|
89
99
|
"sentence-transformers>=5.4.1",
|
|
90
100
|
"torch>=2.5.1",
|
|
91
|
-
"transformers>=
|
|
92
|
-
"kgmodule-utils[semantic]>=0.
|
|
101
|
+
"transformers>=5.5.0,<6",
|
|
102
|
+
"kgmodule-utils[semantic,sqlite-vec,viz]>=0.9.0",
|
|
93
103
|
]
|
|
94
104
|
|
|
95
105
|
[project.optional-dependencies]
|
|
@@ -98,17 +108,14 @@ dev = [
|
|
|
98
108
|
"ty>=0.0.41",
|
|
99
109
|
"pdoc>=14.0.0",
|
|
100
110
|
"pre-commit>=4.5.1",
|
|
101
|
-
"pylint>=4.0.5",
|
|
102
111
|
"pytest>=8.0.0",
|
|
103
112
|
"pytest-cov>=5.0.0",
|
|
104
113
|
"ruff>=0.4.0",
|
|
105
|
-
"doc-kg>=0.15.2",
|
|
106
|
-
# agent-kg not yet on PyPI — install manually: pip install git+https://github.com/Flux-Frontiers/agent_kg.git
|
|
107
114
|
]
|
|
108
115
|
viz = [
|
|
109
116
|
"plotly>=5.14.0",
|
|
110
117
|
"pyvis>=0.3.2",
|
|
111
|
-
"streamlit>=1.
|
|
118
|
+
"streamlit>=1.56.0",
|
|
112
119
|
]
|
|
113
120
|
viz3d = [
|
|
114
121
|
"markdown>=3.6",
|
|
@@ -119,10 +126,14 @@ viz3d = [
|
|
|
119
126
|
"trame-vtk>=2.0.0",
|
|
120
127
|
]
|
|
121
128
|
|
|
122
|
-
#
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
# Cross-KG sibling packages (doc-kg, pycode-kg, agent-kg, kg-rag) are NOT
|
|
130
|
+
# declared here. They are never imported by this package, and listing them
|
|
131
|
+
# forces poetry's universal resolution to reconcile the transformers pin of
|
|
132
|
+
# every *published* sibling against this project's own -- a deadlock, since
|
|
133
|
+
# doc-kg and pycode-kg each depend on the other. Install them by hand:
|
|
134
|
+
# pip install doc-kg pycode-kg # both on PyPI
|
|
135
|
+
# pip install 'kg-rag @ git+https://github.com/Flux-Frontiers/KGRAG.git'
|
|
136
|
+
# pip install 'agent-kg @ git+https://github.com/Flux-Frontiers/agent_kg.git'
|
|
126
137
|
all = [
|
|
127
138
|
"detect-secrets>=1.5.0",
|
|
128
139
|
"markdown>=3.6",
|
|
@@ -130,7 +141,6 @@ all = [
|
|
|
130
141
|
"pdoc>=14.0.0",
|
|
131
142
|
"plotly>=5.14.0",
|
|
132
143
|
"pre-commit>=4.5.1",
|
|
133
|
-
"pylint>=4.0.5",
|
|
134
144
|
"PyQt5>=5.15.0",
|
|
135
145
|
"pytest>=8.0.0",
|
|
136
146
|
"pytest-cov>=5.0.0",
|
|
@@ -138,7 +148,7 @@ all = [
|
|
|
138
148
|
"pyvistaqt>=0.11.0",
|
|
139
149
|
"pyvis>=0.3.2",
|
|
140
150
|
"ruff>=0.4.0",
|
|
141
|
-
"streamlit>=1.
|
|
151
|
+
"streamlit>=1.56.0",
|
|
142
152
|
"trame-vtk>=2.0.0",
|
|
143
153
|
"ty>=0.0.41",
|
|
144
154
|
]
|
|
@@ -152,7 +162,7 @@ pycodekg = "pycode_kg.cli.main:cli"
|
|
|
152
162
|
pycodekg-analyze = "pycode_kg.cli.cmd_analyze:analyze"
|
|
153
163
|
pycodekg-architecture = "pycode_kg.cli.cmd_architecture:architecture"
|
|
154
164
|
pycodekg-build = "pycode_kg.cli.cmd_build_full:build"
|
|
155
|
-
pycodekg-build-
|
|
165
|
+
pycodekg-build-index = "pycode_kg.cli.cmd_build:build_index"
|
|
156
166
|
pycodekg-build-sqlite = "pycode_kg.cli.cmd_build:build_sqlite"
|
|
157
167
|
pycodekg-centrality = "pycode_kg.cli.cmd_centrality:cmd_centrality"
|
|
158
168
|
pycodekg-download-model = "pycode_kg.cli.cmd_model:download_model"
|
|
@@ -172,11 +182,24 @@ pycodekg-viz3d = "pycode_kg.cli.cmd_viz:viz3d"
|
|
|
172
182
|
[tool.ruff]
|
|
173
183
|
line-length = 100
|
|
174
184
|
target-version = "py312"
|
|
185
|
+
# Vendored agent scratch dirs (Claude Code skills, Codex) — not project code.
|
|
186
|
+
# The pre-commit hook's exclude can't cover these (it runs with
|
|
187
|
+
# pass_filenames: false), so the exclusion must live here.
|
|
188
|
+
extend-exclude = [".claude", ".agents", ".codex"]
|
|
175
189
|
|
|
176
190
|
[tool.ruff.lint]
|
|
177
|
-
|
|
191
|
+
# B023, BLE001, PLC0415 replace the retired pylint hook's cell-var-from-loop,
|
|
192
|
+
# broad-exception-caught, and import-outside-toplevel checks.
|
|
193
|
+
select = ["E", "F", "W", "I", "UP", "B023", "BLE001", "PLC0415"]
|
|
178
194
|
ignore = ["E501"]
|
|
179
195
|
|
|
196
|
+
[tool.ruff.lint.per-file-ignores]
|
|
197
|
+
# viz3d is GUI code full of deliberate lazy imports (optional Qt/pyvista deps).
|
|
198
|
+
"src/pycode_kg/viz3d.py" = ["PLC0415"]
|
|
199
|
+
# Test imports are often deliberately lazy — they must run after sys.modules
|
|
200
|
+
# mocks are installed.
|
|
201
|
+
"tests/**" = ["PLC0415"]
|
|
202
|
+
|
|
180
203
|
[tool.ty.environment]
|
|
181
204
|
python-version = "3.12"
|
|
182
205
|
root = ["src"]
|
|
@@ -192,28 +215,14 @@ unresolved-import = "ignore"
|
|
|
192
215
|
unused-ignore-comment = "ignore"
|
|
193
216
|
|
|
194
217
|
[tool.pytest.ini_options]
|
|
195
|
-
testpaths
|
|
196
|
-
addopts
|
|
218
|
+
testpaths = ["tests"]
|
|
219
|
+
addopts = "-v --tb=short"
|
|
220
|
+
pythonpath = ["src"]
|
|
197
221
|
markers = [
|
|
198
222
|
"slow: marks tests as slow (deselect with '-m not slow')",
|
|
199
|
-
"integration: marks tests that exercise real external dependencies (model,
|
|
223
|
+
"integration: marks tests that exercise real external dependencies (model, sqlite-vec)",
|
|
200
224
|
]
|
|
201
225
|
|
|
202
|
-
[tool.pylint.messages_control]
|
|
203
|
-
disable = ["all"]
|
|
204
|
-
enable = [
|
|
205
|
-
"broad-exception-caught", # W0718
|
|
206
|
-
"cell-var-from-loop", # W0640
|
|
207
|
-
"cyclic-import", # R0401
|
|
208
|
-
"import-outside-toplevel", # C0415
|
|
209
|
-
"undefined-variable", # E0602
|
|
210
|
-
]
|
|
211
|
-
|
|
212
|
-
[tool.pylint.imports]
|
|
213
|
-
# The kg → pycodekg_thorough_analysis cycle is broken at runtime by a lazy
|
|
214
|
-
# import inside PyCodeKG.analyze(). Pylint's static analysis can't see that.
|
|
215
|
-
ignored-modules = ["pycode_kg.pycodekg_thorough_analysis"]
|
|
216
|
-
|
|
217
226
|
# ---------------------------------------------------------------------------
|
|
218
227
|
# PyCodeKG / DocKG index configuration
|
|
219
228
|
# ---------------------------------------------------------------------------
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
pycode_kg: A tool to build a searchable knowledge graph from Python repositories.
|
|
3
3
|
|
|
4
|
-
Pure AST extraction → SQLite (authoritative) →
|
|
4
|
+
Pure AST extraction → SQLite (authoritative) → sqlite-vec (semantic index).
|
|
5
5
|
|
|
6
6
|
Public API
|
|
7
7
|
----------
|
|
@@ -9,7 +9,7 @@ Primary entry point::
|
|
|
9
9
|
|
|
10
10
|
from pycode_kg import PyCodeKG
|
|
11
11
|
|
|
12
|
-
kg = PyCodeKG(repo_root, db_path
|
|
12
|
+
kg = PyCodeKG(repo_root, db_path)
|
|
13
13
|
stats = kg.build(wipe=True)
|
|
14
14
|
result = kg.query("database connection setup")
|
|
15
15
|
pack = kg.pack("configuration loading")
|
|
@@ -32,7 +32,7 @@ KGModule SDK (build new domain KGs)::
|
|
|
32
32
|
from pycode_kg import KGModule, KGExtractor, PyCodeKGExtractor, NodeSpec, EdgeSpec
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
|
-
__version__ = "0.
|
|
35
|
+
__version__ = "0.21.0"
|
|
36
36
|
__author__ = "Eric G. Suchanek, PhD"
|
|
37
37
|
|
|
38
38
|
# Low-level primitives (locked v0 contract)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Analysis primitives for PyCodeKG."""
|
|
2
2
|
|
|
3
|
+
from kg_utils.analysis.scores import MetricRef, ScoreSet, available_metrics, load_scores
|
|
4
|
+
|
|
3
5
|
from .centrality import (
|
|
4
6
|
CentralityConfig,
|
|
5
7
|
CentralityRecord,
|
|
@@ -10,6 +12,10 @@ from .centrality import (
|
|
|
10
12
|
__all__ = [
|
|
11
13
|
"CentralityConfig",
|
|
12
14
|
"CentralityRecord",
|
|
15
|
+
"MetricRef",
|
|
16
|
+
"ScoreSet",
|
|
13
17
|
"StructuralImportanceRanker",
|
|
14
18
|
"aggregate_module_scores",
|
|
19
|
+
"available_metrics",
|
|
20
|
+
"load_scores",
|
|
15
21
|
]
|
|
@@ -4,7 +4,7 @@ Measures module interaction complexity: how many unique modules each module call
|
|
|
4
4
|
For well-modularized codebases, identifies orchestrator and hub modules.
|
|
5
5
|
|
|
6
6
|
Author: Eric G. Suchanek, PhD
|
|
7
|
-
Last Revision: 2026-
|
|
7
|
+
Last Revision: 2026-04-27 23:29:23
|
|
8
8
|
License: Elastic 2.0
|
|
9
9
|
"""
|
|
10
10
|
|
|
@@ -3,7 +3,7 @@ Framework Detector for PyCodeKG.
|
|
|
3
3
|
Identifies repo-defining abstractions using centrality and cross-module signals.
|
|
4
4
|
|
|
5
5
|
Author: Eric G. Suchanek, PhD
|
|
6
|
-
Last Revision: 2026-
|
|
6
|
+
Last Revision: 2026-07-15 22:51:18
|
|
7
7
|
License: Elastic 2.0
|
|
8
8
|
"""
|
|
9
9
|
|
|
@@ -62,7 +62,7 @@ def detect_framework_nodes(
|
|
|
62
62
|
# against the module_connectivity metric. Both signals end up keyed by
|
|
63
63
|
# bare module path (e.g. "src/pycode_kg/store.py"), which we map to "mod:..."
|
|
64
64
|
# IDs for output.
|
|
65
|
-
from pycode_kg.analysis.centrality import ( #
|
|
65
|
+
from pycode_kg.analysis.centrality import ( # noqa: PLC0415
|
|
66
66
|
StructuralImportanceRanker,
|
|
67
67
|
aggregate_module_scores,
|
|
68
68
|
)
|