How the Zig-backed instance graph works (GraphView/NodeReference/EdgeReference), the real Python API surface, and the invariants around allocation, attributes, and cleanup.
The faebryk.core.graph module is a thin Python wrapper around the Zig graph implementation.
Source-of-truth for behavior is:
src/faebryk/core/zig/src/graph/graph.zigsrc/faebryk/core/zig/src/python/graph/graph_py.zigsrc/faebryk/core/zig/gen/graph/graph.pyifrom faebryk.core.graph import GraphView
g = GraphView.create()
try:
_ = g.create_and_insert_node()
finally:
g.destroy()
src/faebryk/core/graph.pysrc/faebryk/core/zig/src/graph/graph.zigsrc/faebryk/core/zig/src/python/graph/graph_py.zigsrc/faebryk/core/zig/gen/graph/graph.pyisrc/faebryk/core/node.py (FabLL: nodes/traits are graph-backed)src/atopile/compiler/gentypegraph.py (compiler constructs typegraphs/instances via graph APIs)src/faebryk/core/graph_render.py (graph visualization)NodeReference / EdgeReference: value-like handles (UUIDs) into global backing storage in Zig.GraphView: a membership + adjacency view over those references (per-view arena + maps + bitsets).BoundNode / BoundEdge: “reference + owning GraphView pointer” wrappers used for traversal helpers.GraphView(), NodeReference(), EdgeReference() are not meant to be called; use the exposed factory methods.GraphView.create()NodeReference.create(**attrs)EdgeReference.create(source=..., target=..., edge_type=..., **attrs)GraphView.create() allocates a Zig-side graph on the C allocator; it is freed only by GraphView.destroy().u8 in Zig; treat them as 0..255 in Python (hashing/modulo happens on the Zig side).GraphView.init inserts a self_node; counts include it.src/faebryk/core/zig/gen/graph/graph.pyi)from faebryk.core.graph import GraphView, Node, Edge
g = GraphView.create()
try:
n1 = g.create_and_insert_node() # -> BoundNode
n2 = Node.create(name="n2") # -> NodeReference (not inserted yet)
bn2 = g.insert_node(node=n2) # -> BoundNode
e = Edge.create(source=n1.node(), target=bn2.node(), edge_type=7, name="link")
_be = g.insert_edge(edge=e) # -> BoundEdge
finally:
g.destroy()
GraphView.__repr__() prints GraphView(id=..., |V|=..., |E|=...) from Zig.python -m faebryk.core.graph (runs test_graph_garbage_collection).src/faebryk/core/zig/src/graph/*.ato dev compile (imports faebryk.core.zig, which compiles in editable installs).src/faebryk/core/zig/src/python/graph/graph_py.zig and ensure stubs regenerate.Key test entrypoints:
python -m faebryk.core.graphzig test src/faebryk/core/zig/src/graph/graph.zig