Skip to content

serializer

serializer #

Flatten a Procedure DAG to the cross-platform wire form.

The wire form is {"schema", "root", "nodes"}:

  • schema is the target Struct's wire form — the a-priori data schema, emitted once, that replaces the runtime manifest.
  • root is the id of the root node; nodes maps id → node.
  • each node records its kind (class name), return_type, label, settings, inputs (field name → id), and substeps (list of ids); falsy entries are omitted. Path/Void return types serialize compactly ({"type": "path"} / {"type": "void"}) since their structure is recoverable from schema plus the access chain.

procedure_to_dict(procedure, target_schema=None) #

Serialize a Procedure DAG to {"schema"?, "root", "nodes"}.

Parameters:

Name Type Description Default
procedure Procedure[CGType]

The root Procedure node to serialize.

required
target_schema type[CGType] | None

The target Struct whose wire form is embedded as "schema" (omitted when not provided).

None

Returns:

Type Description
dict[str, Any]

The serialized procedure graph.

Raises:

Type Description
ValueError

If a ProcedureWhile violates loop invariants.

Source code in capturegraph-lib/capturegraph/procedures/procedure/exporting/serializer.py
def procedure_to_dict(
    procedure: Procedure[CGType],
    target_schema: type[CGType] | None = None,
) -> dict[str, Any]:
    """Serialize a Procedure DAG to ``{"schema"?, "root", "nodes"}``.

    Args:
        procedure: The root Procedure node to serialize.
        target_schema: The target ``Struct`` whose wire form is embedded as
            ``"schema"`` (omitted when not provided).

    Returns:
        The serialized procedure graph.

    Raises:
        ValueError: If a ProcedureWhile violates loop invariants.
    """
    nodes: dict[str, dict[str, Any]] = {}
    uuid_to_proc: dict[str, Procedure[CGType]] = {}

    def flatten(procedure: Procedure[CGType]) -> str:
        if procedure._uuid not in nodes:
            uuid_to_proc[procedure._uuid] = procedure

            node = {
                "kind": procedure.kind.__name__,
                "return_type": _return_type_json(procedure._return_type),
                "label": procedure.label,
                "settings": procedure._settings,
                "inputs": {name: flatten(value) for name, value in procedure._inputs.items()},
                "substeps": [flatten(substep) for substep in procedure._substeps],
            }

            for key in list(node.keys()):
                if key != "return_type" and not node[key]:
                    del node[key]

            nodes[procedure._uuid] = node

        return procedure._uuid

    root_uuid = flatten(procedure)

    _compute_template_nodes(nodes, uuid_to_proc)

    uuid_map: dict[str, str] = {}
    hex_length = len(f"{len(nodes) - 1:X}")
    for index, uuid in enumerate(nodes):
        uuid_map[uuid] = f"{index:X}".zfill(hex_length)

    body = _replace_strings_in_dict({"root": root_uuid, "nodes": nodes}, uuid_map)

    # template_nodes is a set of ids; sort after remapping so identical procedures
    # serialize byte-identically (UUIDs are random per run).
    for node in body["nodes"].values():
        template_nodes = node.get("settings", {}).get("template_nodes")
        if template_nodes is not None:
            node["settings"]["template_nodes"] = sorted(template_nodes)

    result: dict[str, Any] = {}
    if target_schema is not None:
        result["schema"] = schema(target_schema)
    result["root"] = body["root"]
    result["nodes"] = body["nodes"]
    return result

procedure_to_json(procedure, indent=4, target_schema=None, **json_kwargs) #

Serialize a Procedure DAG to a JSON string (see [procedure_to_dict][]).

Source code in capturegraph-lib/capturegraph/procedures/procedure/exporting/serializer.py
def procedure_to_json(
    procedure: Procedure[CGType],
    indent: int = 4,
    target_schema: type[CGType] | None = None,
    **json_kwargs: Unpack[_JSONDumpsKwargs],
) -> str:
    """Serialize a Procedure DAG to a JSON string (see [procedure_to_dict][])."""
    return json.dumps(
        procedure_to_dict(procedure, target_schema=target_schema),
        indent=indent,
        **json_kwargs,
    )