mirror of
https://github.com/safishamsi/graphify.git
synced 2026-09-15 18:15:44 +00:00
fix: silence "invalid file_type 'None'" warning on legacy graphs (#660)
Users running `graphify update .` against a graph that contains nodes preserved from older graphify versions see the warning: [graphify] Extraction warning (31 issues): Node 1661 (id='telepathy_app') has invalid file_type 'None' - must be one of [...] The cause: `_rebuild_code` in watch.py preserves nodes from the existing graph.json that aren't in the new AST output. Some of those nodes (stubs, semantic concepts created before file_type was always populated) have file_type=null in the on-disk JSON, which becomes Python None on load. The validator in validate.py:33 then flags every such node. Add a normalization step in `build_from_json` next to the existing `source` -> `source_file` legacy canonicalization: if a node's file_type is None or empty, default it to "concept" before validation. This silences the false positive while keeping the validator strict for genuinely invalid values like "weird_type".
This commit is contained in:
+9
-1
@@ -51,7 +51,9 @@ def build_from_json(extraction: dict, *, directed: bool = False) -> nx.Graph:
|
||||
|
||||
# Canonicalize legacy node/edge schema before validation.
|
||||
for node in extraction.get("nodes", []):
|
||||
if isinstance(node, dict) and "source" in node and "source_file" not in node:
|
||||
if not isinstance(node, dict):
|
||||
continue
|
||||
if "source" in node and "source_file" not in node:
|
||||
# Count edges that reference this node so the warning is actionable (#479)
|
||||
node_id = node.get("id", "?")
|
||||
affected_edges = sum(
|
||||
@@ -65,6 +67,12 @@ def build_from_json(extraction: dict, *, directed: bool = False) -> nx.Graph:
|
||||
file=sys.stderr,
|
||||
)
|
||||
node["source_file"] = node.pop("source")
|
||||
# Default missing/None file_type to "concept" so legacy graph.json
|
||||
# entries (and stub nodes preserved by `_rebuild_code` from older
|
||||
# graphify versions that didn't always populate file_type) don't
|
||||
# trigger spurious "invalid file_type 'None'" validator warnings (#660).
|
||||
if node.get("file_type") in (None, ""):
|
||||
node["file_type"] = "concept"
|
||||
|
||||
errors = validate_extraction(extraction)
|
||||
# Dangling edges (stdlib/external imports) are expected - only warn about real schema errors.
|
||||
|
||||
@@ -60,3 +60,56 @@ def test_build_merges_multiple_extractions():
|
||||
G = build([ext1, ext2])
|
||||
assert G.number_of_nodes() == 2
|
||||
assert G.number_of_edges() == 1
|
||||
|
||||
|
||||
def test_none_file_type_defaults_to_concept(capsys):
|
||||
"""Legacy nodes with file_type=None (e.g. preserved from older graph.json
|
||||
by `_rebuild_code`) must not trigger 'invalid file_type None' warnings (#660)."""
|
||||
ext = {
|
||||
"nodes": [
|
||||
{"id": "n1", "label": "Stub", "file_type": None, "source_file": "a.py"},
|
||||
{"id": "n2", "label": "Real", "file_type": "code", "source_file": "b.py"},
|
||||
],
|
||||
"edges": [],
|
||||
"input_tokens": 0,
|
||||
"output_tokens": 0,
|
||||
}
|
||||
G = build_from_json(ext)
|
||||
err = capsys.readouterr().err
|
||||
assert "invalid file_type" not in err
|
||||
# The legacy node still exists in the graph and has been canonicalized
|
||||
assert G.nodes["n1"]["file_type"] == "concept"
|
||||
assert G.nodes["n2"]["file_type"] == "code"
|
||||
|
||||
|
||||
def test_missing_file_type_defaults_to_concept(capsys):
|
||||
"""Nodes missing file_type entirely should also be canonicalized to 'concept'."""
|
||||
ext = {
|
||||
"nodes": [
|
||||
{"id": "n1", "label": "Bare", "source_file": "a.py"},
|
||||
],
|
||||
"edges": [],
|
||||
"input_tokens": 0,
|
||||
"output_tokens": 0,
|
||||
}
|
||||
G = build_from_json(ext)
|
||||
err = capsys.readouterr().err
|
||||
assert "invalid file_type" not in err
|
||||
assert "missing required field 'file_type'" not in err
|
||||
assert G.nodes["n1"]["file_type"] == "concept"
|
||||
|
||||
|
||||
def test_real_invalid_file_type_still_warns(capsys):
|
||||
"""Truly invalid file_type values (not None, not empty) must still warn."""
|
||||
ext = {
|
||||
"nodes": [
|
||||
{"id": "n1", "label": "Bad", "file_type": "weird_type", "source_file": "a.py"},
|
||||
],
|
||||
"edges": [],
|
||||
"input_tokens": 0,
|
||||
"output_tokens": 0,
|
||||
}
|
||||
build_from_json(ext)
|
||||
err = capsys.readouterr().err
|
||||
assert "invalid file_type" in err
|
||||
assert "weird_type" in err
|
||||
|
||||
Reference in New Issue
Block a user