diff --git a/graph/graph.py b/graph/graph.py index 9532224..40c63ae 100644 --- a/graph/graph.py +++ b/graph/graph.py @@ -106,87 +106,87 @@ class LocalGraph: f.write(toon_text) return path - def _parse_node_id(self, node_id: str): - """ - Parse node_id into components and return a dict of canonical attributes. + def _parse_node_id(self, node_id: str): + """ + Parse node_id into components and return a dict of canonical attributes. - Supported formats: - 1) lang::node_type::file_path::name (full chunk/file tied) - 2) lang::node_type::name (file-less canonical form - Option B) - 3) file:: (file nodes) - otherwise -> fallback to Symbol - """ - attrs = { - "type": "Symbol", - "name": node_id, - "lang": "", - "file": "" - } - if not isinstance(node_id, str): - return attrs - parts = node_id.split("::") - if len(parts) == 4: - lang, node_type, file_path, name = parts - attrs["type"] = node_type - attrs["name"] = name - attrs["lang"] = lang - attrs["file"] = file_path - elif len(parts) == 3: - # Option B canonical file-less representation: lang::kind::entity_name - lang, node_type, name = parts - attrs["type"] = node_type - attrs["name"] = name - attrs["lang"] = lang - attrs["file"] = "" - elif len(parts) == 2 and parts[0] == "file": - # file:: - attrs["type"] = "File" - attrs["name"] = parts[1] - attrs["file"] = parts[1] - attrs["lang"] = "" - else: - # fallback: try to be helpful by guessing the name - if len(parts) >= 1: - attrs["name"] = parts[-1] - return attrs + Supported formats: + 1) lang::node_type::file_path::name (full chunk/file tied) + 2) lang::node_type::name (file-less canonical form - Option B) + 3) file:: (file nodes) + otherwise -> fallback to Symbol + """ + attrs = { + "type": "Symbol", + "name": node_id, + "lang": "", + "file": "" + } + if not isinstance(node_id, str): + return attrs + parts = node_id.split("::") + if len(parts) == 4: + lang, node_type, file_path, name = parts + attrs["type"] = node_type + attrs["name"] = name + attrs["lang"] = lang + attrs["file"] = file_path + elif len(parts) == 3: + # Option B canonical file-less representation: lang::kind::entity_name + lang, node_type, name = parts + attrs["type"] = node_type + attrs["name"] = name + attrs["lang"] = lang + attrs["file"] = "" + elif len(parts) == 2 and parts[0] == "file": + # file:: + attrs["type"] = "File" + attrs["name"] = parts[1] + attrs["file"] = parts[1] + attrs["lang"] = "" + else: + # fallback: try to be helpful by guessing the name + if len(parts) >= 1: + attrs["name"] = parts[-1] + return attrs - def _ensure_node_exists(self, node_id: str): - """ - Ensure a node with node_id exists in the graph. - If it doesn't, create it using sensible attributes derived from the node_id format. - """ - if node_id in self.graph.nodes: - return - parsed = self._parse_node_id(node_id) - # Use add_node (keeps behaviour consistent) - self.add_node(node_id, **{ - "type": parsed.get("type", "Symbol"), - "name": parsed.get("name", node_id), - "lang": parsed.get("lang", ""), - "file": parsed.get("file", "") - }) + def _ensure_node_exists(self, node_id: str): + """ + Ensure a node with node_id exists in the graph. + If it doesn't, create it using sensible attributes derived from the node_id format. + """ + if node_id in self.graph.nodes: + return + parsed = self._parse_node_id(node_id) + # Use add_node (keeps behaviour consistent) + self.add_node(node_id, **{ + "type": parsed.get("type", "Symbol"), + "name": parsed.get("name", node_id), + "lang": parsed.get("lang", ""), + "file": parsed.get("file", "") + }) - def add_edge(self, src: str, dst: str, edge_type: str, **attrs): - """ - Add an edge but first ensure both source and destination nodes exist and have basic attributes. - This prevents the creation of attribute-less nodes and makes semantic edges meaningful. - """ - try: - # Ensure source node exists (create minimal entry if missing) - if src not in self.graph.nodes: - self._ensure_node_exists(src) + def add_edge(self, src: str, dst: str, edge_type: str, **attrs): + """ + Add an edge but first ensure both source and destination nodes exist and have basic attributes. + This prevents the creation of attribute-less nodes and makes semantic edges meaningful. + """ + try: + # Ensure source node exists (create minimal entry if missing) + if src not in self.graph.nodes: + self._ensure_node_exists(src) - # Ensure destination node exists (create minimal entry if missing) - if dst not in self.graph.nodes: - self._ensure_node_exists(dst) + # Ensure destination node exists (create minimal entry if missing) + if dst not in self.graph.nodes: + self._ensure_node_exists(dst) - # Finally add the edge with type and any extra attrs - self.graph.add_edge(src, dst, type=edge_type, **attrs) - except Exception: - # Keep behaviour non-fatal for indexing runs - log if you have a logger available - # fallback: still attempt to add the edge - try: - self.graph.add_edge(src, dst, type=edge_type, **attrs) - except Exception: - # swallow; graph should remain usable - pass + # Finally add the edge with type and any extra attrs + self.graph.add_edge(src, dst, type=edge_type, **attrs) + except Exception: + # Keep behaviour non-fatal for indexing runs - log if you have a logger available + # fallback: still attempt to add the edge + try: + self.graph.add_edge(src, dst, type=edge_type, **attrs) + except Exception: + # swallow; graph should remain usable + pass