diff --git a/graphify/analyze.py b/graphify/analyze.py index 8ca7ddac2..b6c0e4c28 100644 --- a/graphify/analyze.py +++ b/graphify/analyze.py @@ -1,6 +1,7 @@ """Graph analysis: god nodes (most connected), surprising connections (cross-community), suggested questions.""" from __future__ import annotations import networkx as nx +from .detect import CODE_EXTENSIONS, DOC_EXTENSIONS, PAPER_EXTENSIONS, IMAGE_EXTENSIONS def _node_community_map(communities: dict[int, list[str]]) -> dict[str, int]: @@ -109,19 +110,13 @@ def _is_concept_node(G: nx.Graph, node_id: str) -> bool: return False -_CODE_EXTENSIONS = {"py", "ts", "tsx", "js", "go", "rs", "java", "rb", "cpp", "c", "h", "cs", "kt", "scala", "php"} -_DOC_EXTENSIONS = {"md", "txt", "rst"} -_PAPER_EXTENSIONS = {"pdf"} -_IMAGE_EXTENSIONS = {"png", "jpg", "jpeg", "webp", "gif", "svg"} - - def _file_category(path: str) -> str: - ext = path.rsplit(".", 1)[-1].lower() if "." in path else "" - if ext in _CODE_EXTENSIONS: + ext = ("." + path.rsplit(".", 1)[-1].lower()) if "." in path else "" + if ext in CODE_EXTENSIONS: return "code" - if ext in _PAPER_EXTENSIONS: + if ext in PAPER_EXTENSIONS: return "paper" - if ext in _IMAGE_EXTENSIONS: + if ext in IMAGE_EXTENSIONS: return "image" return "doc" diff --git a/graphify/cluster.py b/graphify/cluster.py index 09d070405..363d555c8 100644 --- a/graphify/cluster.py +++ b/graphify/cluster.py @@ -52,23 +52,6 @@ def _partition(G: nx.Graph) -> dict[str, int]: return {node: cid for cid, nodes in enumerate(communities) for node in nodes} -def build_graph(nodes: list[dict], edges: list[dict]) -> nx.Graph: - """Build a NetworkX graph from graphify node/edge dicts. - - Preserves original edge direction as _src/_tgt attributes so that - display functions can show relationships in the correct direction, - even though the graph is undirected for structural analysis. - """ - G = nx.Graph() - for n in nodes: - G.add_node(n["id"], **{k: v for k, v in n.items() if k != "id"}) - for e in edges: - attrs = {k: v for k, v in e.items() if k not in ("source", "target")} - attrs["_src"] = e["source"] - attrs["_tgt"] = e["target"] - G.add_edge(e["source"], e["target"], **attrs) - return G - _MAX_COMMUNITY_FRACTION = 0.25 # communities larger than 25% of graph get split _MIN_SPLIT_SIZE = 10 # only split if community has at least this many nodes diff --git a/graphify/watch.py b/graphify/watch.py index c0cabdde8..a1556c94b 100644 --- a/graphify/watch.py +++ b/graphify/watch.py @@ -3,19 +3,10 @@ import json import time from pathlib import Path +from .detect import CODE_EXTENSIONS, DOC_EXTENSIONS, PAPER_EXTENSIONS, IMAGE_EXTENSIONS - -_WATCHED_EXTENSIONS = { - ".py", ".ts", ".js", ".go", ".rs", ".java", ".cpp", ".c", ".rb", ".swift", ".kt", - ".cs", ".scala", ".php", ".cc", ".cxx", ".hpp", ".h", ".kts", - ".md", ".txt", ".rst", ".pdf", - ".png", ".jpg", ".jpeg", ".webp", ".gif", ".svg", -} - -_CODE_EXTENSIONS = { - ".py", ".ts", ".js", ".go", ".rs", ".java", ".cpp", ".c", ".rb", ".swift", ".kt", - ".cs", ".scala", ".php", ".cc", ".cxx", ".hpp", ".h", ".kts", -} +_WATCHED_EXTENSIONS = CODE_EXTENSIONS | DOC_EXTENSIONS | PAPER_EXTENSIONS | IMAGE_EXTENSIONS +_CODE_EXTENSIONS = CODE_EXTENSIONS def _rebuild_code(watch_path: Path, *, follow_symlinks: bool = False) -> bool: diff --git a/tests/test_analyze.py b/tests/test_analyze.py index 0ae2ede54..c6dc82866 100644 --- a/tests/test_analyze.py +++ b/tests/test_analyze.py @@ -137,6 +137,15 @@ def test_file_category(): assert _file_category("flash.pdf") == "paper" assert _file_category("diagram.png") == "image" assert _file_category("notes.md") == "doc" + # Languages that were previously misclassified as "doc" + assert _file_category("main.swift") == "code" + assert _file_category("lib.lua") == "code" + assert _file_category("build.zig") == "code" + assert _file_category("script.ps1") == "code" + assert _file_category("app.ex") == "code" + assert _file_category("view.jsx") == "code" + assert _file_category("solver.jl") == "code" + assert _file_category("bridge.m") == "code" def test_is_concept_node_empty_source():