Source code for jamb.storage.graph_builder

"""Build TraceabilityGraph from native storage layer."""

import fnmatch

from jamb.core.models import Item, TraceabilityGraph
from jamb.storage.document_dag import DocumentDAG
from jamb.storage.items import read_document_items


[docs] def build_traceability_graph( dag: DocumentDAG, document_prefixes: list[str] | None = None, include_inactive: bool = False, exclude_patterns: list[str] | None = None, ) -> TraceabilityGraph: """Build a TraceabilityGraph from the native storage layer. Args: dag: The document DAG with discovered documents. document_prefixes: Optional list of prefixes to include. If None, includes all documents. include_inactive: Whether to include inactive items. exclude_patterns: Optional glob patterns to exclude documents (by prefix) and items (by UID) from the graph. Returns: TraceabilityGraph populated with items and document relationships. """ graph = TraceabilityGraph() if document_prefixes is not None: prefixes_to_load = document_prefixes else: prefixes_to_load = list(dag.documents.keys()) # Filter out excluded document prefixes if exclude_patterns: prefixes_to_load = [p for p in prefixes_to_load if not any(fnmatch.fnmatch(p, pat) for pat in exclude_patterns)] for prefix in prefixes_to_load: if prefix not in dag.documents: continue config = dag.documents[prefix] doc_path = dag.document_paths.get(prefix) # Set document parents (DAG: multiple parents) graph.set_document_parents(prefix, config.parents) if doc_path is None: continue # Read items from disk raw_items = read_document_items(doc_path, prefix, include_inactive, sep=config.sep) for raw in raw_items: item = Item( uid=raw["uid"], text=raw["text"], document_prefix=raw["document_prefix"], active=raw["active"], type=raw["type"], header=raw["header"] or None, level=raw.get("level"), links=raw["links"], reviewed=raw["reviewed"], derived=raw["derived"], testable=raw.get("testable", True), custom_attributes=raw.get("custom_attributes", {}), ) # Filter out excluded items by UID if exclude_patterns and any(fnmatch.fnmatch(item.uid, pat) for pat in exclude_patterns): continue graph.add_item(item) return graph