mirror of
https://github.com/safishamsi/graphify.git
synced 2026-07-14 03:17:28 +00:00
- extract.py: use str(path) for node IDs to prevent same-basename collision (#211) - build.py: normalize from/to edge keys before KeyError (#216) - export.py: guard ZeroDivisionError when graph has no edges (#217) - hooks.py: remove stale CODE_EXTS filter, rebuild on any changed file (#222) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,12 @@ def build_from_json(extraction: dict, *, directed: bool = False) -> nx.Graph:
|
||||
G.add_node(node["id"], **{k: v for k, v in node.items() if k != "id"})
|
||||
node_set = set(G.nodes())
|
||||
for edge in extraction.get("edges", []):
|
||||
if "source" not in edge and "from" in edge:
|
||||
edge["source"] = edge["from"]
|
||||
if "target" not in edge and "to" in edge:
|
||||
edge["target"] = edge["to"]
|
||||
if "source" not in edge or "target" not in edge:
|
||||
continue
|
||||
src, tgt = edge["source"], edge["target"]
|
||||
if src not in node_set or tgt not in node_set:
|
||||
continue # skip edges to external/stdlib nodes - expected, not an error
|
||||
|
||||
+2
-2
@@ -346,7 +346,7 @@ def to_html(
|
||||
|
||||
node_community = _node_community_map(communities)
|
||||
degree = dict(G.degree())
|
||||
max_deg = max(degree.values()) if degree else 1
|
||||
max_deg = max(degree.values(), default=1) or 1
|
||||
|
||||
# Build nodes list for vis.js
|
||||
vis_nodes = []
|
||||
@@ -957,7 +957,7 @@ def to_svg(
|
||||
pos = nx.spring_layout(G, seed=42, k=2.0 / (G.number_of_nodes() ** 0.5 + 1))
|
||||
|
||||
degree = dict(G.degree())
|
||||
max_deg = max(degree.values()) if degree else 1
|
||||
max_deg = max(degree.values(), default=1) or 1
|
||||
|
||||
node_colors = [COMMUNITY_COLORS[node_community.get(n, 0) % len(COMMUNITY_COLORS)] for n in G.nodes()]
|
||||
node_sizes = [300 + 1200 * (degree.get(n, 1) / max_deg) for n in G.nodes()]
|
||||
|
||||
+9
-9
@@ -673,7 +673,7 @@ def _extract_generic(path: Path, config: LanguageConfig) -> dict:
|
||||
"weight": weight,
|
||||
})
|
||||
|
||||
file_nid = _make_id(stem)
|
||||
file_nid = _make_id(str(path))
|
||||
add_node(file_nid, path.name, 1)
|
||||
|
||||
def walk(node, parent_class_nid: str | None = None) -> None:
|
||||
@@ -1004,7 +1004,7 @@ def _extract_python_rationale(path: Path, result: dict) -> None:
|
||||
nodes = result["nodes"]
|
||||
edges = result["edges"]
|
||||
seen_ids = {n["id"] for n in nodes}
|
||||
file_nid = _make_id(stem)
|
||||
file_nid = _make_id(str(path))
|
||||
|
||||
def _get_docstring(body_node) -> tuple[str, int] | None:
|
||||
if not body_node:
|
||||
@@ -1200,7 +1200,7 @@ def extract_julia(path: Path) -> dict:
|
||||
"weight": weight,
|
||||
})
|
||||
|
||||
file_nid = _make_id(stem)
|
||||
file_nid = _make_id(str(path))
|
||||
add_node(file_nid, path.name, 1)
|
||||
|
||||
def _func_name_from_signature(sig_node) -> str | None:
|
||||
@@ -1415,7 +1415,7 @@ def extract_go(path: Path) -> dict:
|
||||
"weight": weight,
|
||||
})
|
||||
|
||||
file_nid = _make_id(stem)
|
||||
file_nid = _make_id(str(path))
|
||||
add_node(file_nid, path.name, 1)
|
||||
|
||||
def walk(node) -> None:
|
||||
@@ -1603,7 +1603,7 @@ def extract_rust(path: Path) -> dict:
|
||||
"weight": weight,
|
||||
})
|
||||
|
||||
file_nid = _make_id(stem)
|
||||
file_nid = _make_id(str(path))
|
||||
add_node(file_nid, path.name, 1)
|
||||
|
||||
def walk(node, parent_impl_nid: str | None = None) -> None:
|
||||
@@ -1761,7 +1761,7 @@ def extract_zig(path: Path) -> dict:
|
||||
"confidence": confidence, "source_file": str_path,
|
||||
"source_location": f"L{line}", "weight": weight})
|
||||
|
||||
file_nid = _make_id(stem)
|
||||
file_nid = _make_id(str(path))
|
||||
add_node(file_nid, path.name, 1)
|
||||
|
||||
def _extract_import(node) -> None:
|
||||
@@ -1916,7 +1916,7 @@ def extract_powershell(path: Path) -> dict:
|
||||
"confidence": confidence, "source_file": str_path,
|
||||
"source_location": f"L{line}", "weight": weight})
|
||||
|
||||
file_nid = _make_id(stem)
|
||||
file_nid = _make_id(str(path))
|
||||
add_node(file_nid, path.name, 1)
|
||||
|
||||
_PS_SKIP = frozenset({
|
||||
@@ -2205,7 +2205,7 @@ def extract_objc(path: Path) -> dict:
|
||||
"confidence": confidence, "source_file": str_path,
|
||||
"source_location": f"L{line}", "weight": weight})
|
||||
|
||||
file_nid = _make_id(stem)
|
||||
file_nid = _make_id(str(path))
|
||||
add_node(file_nid, path.name, 1)
|
||||
|
||||
def _read(node) -> str:
|
||||
@@ -2403,7 +2403,7 @@ def extract_elixir(path: Path) -> dict:
|
||||
"confidence": confidence, "source_file": str_path,
|
||||
"source_location": f"L{line}", "weight": weight})
|
||||
|
||||
file_nid = _make_id(stem)
|
||||
file_nid = _make_id(str(path))
|
||||
add_node(file_nid, path.name, 1)
|
||||
|
||||
_IMPORT_KEYWORDS = frozenset({"alias", "import", "require", "use"})
|
||||
|
||||
+2
-8
@@ -46,19 +46,13 @@ $GRAPHIFY_PYTHON -c "
|
||||
import os, sys
|
||||
from pathlib import Path
|
||||
|
||||
CODE_EXTS = {
|
||||
'.py', '.ts', '.js', '.go', '.rs', '.java', '.cpp', '.c', '.rb', '.swift',
|
||||
'.kt', '.cs', '.scala', '.php', '.cc', '.cxx', '.hpp', '.h', '.kts',
|
||||
}
|
||||
|
||||
changed_raw = os.environ.get('GRAPHIFY_CHANGED', '')
|
||||
changed = [Path(f.strip()) for f in changed_raw.strip().splitlines() if f.strip()]
|
||||
code_changed = [f for f in changed if f.suffix.lower() in CODE_EXTS and f.exists()]
|
||||
|
||||
if not code_changed:
|
||||
if not changed:
|
||||
sys.exit(0)
|
||||
|
||||
print(f'[graphify hook] {len(code_changed)} code file(s) changed - rebuilding graph...')
|
||||
print(f'[graphify hook] {len(changed)} file(s) changed - rebuilding graph...')
|
||||
|
||||
try:
|
||||
from graphify.watch import _rebuild_code
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "graphifyy"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
description = "AI coding assistant skill (Claude Code, Codex, OpenCode, Cursor, OpenClaw, Factory Droid, Trae) - turn any folder of code, docs, papers, images, or videos into a queryable knowledge graph"
|
||||
readme = "README.md"
|
||||
license = { file = "LICENSE" }
|
||||
|
||||
Reference in New Issue
Block a user