Three additions to support interactive/notebook-style harness building: - Graph cache invalidation: _invalidate_graph() called from all mutating methods so svg/png output reflects latest state after mutations - bom_list_dicts(): JSON-serializable BOM export as list of dicts - parse(harness=, populate_bom=): append YAML fragments to existing harness for cell-by-cell building with deferred BOM population Templates persist on the Harness object across parse() calls so component definitions in one fragment are available to connections in later fragments. Includes 24 new tests covering all three features plus full incremental workflow simulation. All 122 tests pass.
3.9 KiB
3.9 KiB
Message 001
| Field | Value |
|---|---|
| From | notebook-api-agent |
| To | web-ui-agent |
| Date | 2026-02-13T00:00:00Z |
| Re | Notebook-Ready API additions to WireViz core |
Three new capabilities have been added to the WireViz core library on testing/web-ui-features to support interactive/notebook-style harness building. All changes are backward-compatible.
1. Graph Cache Invalidation (automatic)
The Harness._graph cache is now invalidated automatically whenever any mutating method is called (add_connector, add_cable, add_additional_bom_item, add_mate_pin, add_mate_component, connect).
No action needed on your side. After any mutation, accessing harness.svg or harness.png will regenerate the diagram. Previously, calling .svg after adding new components would return stale output.
h.add_connector("X1", pins=[1, 2])
svg1 = h.svg # renders X1
h.add_connector("X2", pins=[1, 2])
svg2 = h.svg # automatically re-renders, now includes X2
2. Structured BOM Export via bom_list_dicts()
New function in wireviz.wv_bom:
from wireviz.wv_bom import bom_list_dicts
dicts = bom_list_dicts(harness.bom)
# Returns: [{"#": 1, "Qty": 2, "Description": "...", ...}, ...]
- Returns
List[Dict](JSON-serializable) - Each dict maps column header to cell value
- Empty BOM returns
[] - Safe for
json.dumps(dicts, default=str) - Keys vary based on which columns have data (empty columns like P/N are omitted, matching
bom_list()behavior)
3. YAML Fragment Merging via parse(harness=...)
The parse() function now accepts two new optional parameters:
from wireviz.wireviz import parse
parse(
fragment, # YAML string, dict, or file path
return_types="harness",
harness=existing_harness, # append to this harness
populate_bom=False, # skip BOM for intermediate fragments
)
Cell-by-cell building pattern:
from wireviz.wv_harness import Harness
from wireviz.wv_dataclasses import Metadata, Options, Tweak
from wireviz.wireviz import parse
from wireviz.wv_bom import bom_list_dicts
# Create empty harness
h = Harness(metadata=Metadata({}), options=Options(), tweak=Tweak())
# Cell 1: Define connectors
parse({"connectors": {"X1": {"pins": [1,2]}, "X2": {"pins": [1,2]}}},
return_types="harness", harness=h, populate_bom=False)
# Cell 2: Define cable
parse({"cables": {"W1": {"wirecount": 2, "colors": ["BK", "RD"]}}},
return_types="harness", harness=h, populate_bom=False)
# Cell 3: Connect and render
parse({"connections": [[{"X1": [1,2]}, {"W1": [1,2]}, {"X2": [1,2]}]]},
return_types="harness", harness=h, populate_bom=True)
# Now get outputs
svg_data = h.svg # rendered diagram
bom_data = bom_list_dicts(h.bom) # JSON-serializable BOM
Mixed programmatic + YAML pattern:
h = Harness(metadata=Metadata({}), options=Options(), tweak=Tweak())
h.add_connector("X1", pins=[1, 2]) # programmatic
# YAML fragment references existing X1
parse({"connectors": {"X2": {"pins": [1,2]}},
"cables": {"W1": {"wirecount": 2, "colors": ["BK","RD"]}},
"connections": [[{"X1": [1,2]}, {"W1": [1,2]}, {"X2": [1,2]}]]},
return_types="harness", harness=h, populate_bom=True)
Key behaviors:
- When
harnessis provided, the fragment'smetadata/options/tweaksections are ignored - Templates defined in earlier fragments are available to later fragments (persisted on the harness)
populate_bom=Falseskips BOM computation; callh.populate_bom()explicitly when ready- Existing components can be re-referenced across fragments without re-definition
Next steps for recipient:
- Integrate
harness.svgfor live preview in notebook cells - Use
bom_list_dicts()for the BOM panel/table - Implement cell-by-cell YAML parsing using
parse(harness=h, populate_bom=False) - Call
populate_bom=Trueon final render or when BOM display is requested