89 lines
2.6 KiB
Python
89 lines
2.6 KiB
Python
"""Module dataclasses and JSON round-trip helpers.
|
|
|
|
Each module type is a separate dataclass with a ``type`` literal tag. The
|
|
discriminated union ``Module`` widens as new types land (wildcard, combine,
|
|
constraint, derivation — follow-up specs).
|
|
"""
|
|
|
|
from dataclasses import asdict, dataclass, field
|
|
from typing import Any, Literal, TypeAlias
|
|
|
|
|
|
@dataclass
|
|
class ModuleMeta:
|
|
"""Shared metadata on every module. SPA library uses these for listing."""
|
|
|
|
name: str = ""
|
|
description: str = ""
|
|
category: str = ""
|
|
tags: list[str] = field(default_factory=list)
|
|
|
|
|
|
@dataclass
|
|
class FixedValueEntry:
|
|
"""One literal assignment inside a fixed_values module."""
|
|
|
|
variable_name: str
|
|
value: str
|
|
|
|
|
|
@dataclass
|
|
class FixedValueModule:
|
|
"""Module type: sets one or more variables to literal strings."""
|
|
|
|
id: str
|
|
type: Literal["fixed_values"] = "fixed_values"
|
|
enabled: bool = True
|
|
meta: ModuleMeta = field(default_factory=ModuleMeta)
|
|
entries: list[FixedValueEntry] = field(default_factory=list)
|
|
|
|
|
|
# Discriminated union of all module types. Currently a single member; widens
|
|
# as new module types (wildcard, combine, constraint, derivation) land.
|
|
Module: TypeAlias = FixedValueModule
|
|
|
|
|
|
def module_to_dict(module: Module) -> dict[str, Any]:
|
|
"""Serialize a module dataclass to a plain dict (widget payload shape)."""
|
|
return asdict(module)
|
|
|
|
|
|
def module_from_dict(data: dict[str, Any]) -> Module:
|
|
"""Deserialize a plain dict (widget payload shape) into a module dataclass.
|
|
|
|
Raises ``ValueError`` for missing ``id``, missing ``type``, or unknown type.
|
|
"""
|
|
if "type" not in data:
|
|
raise ValueError(f"missing 'type' in module data: {data!r}")
|
|
if "id" not in data:
|
|
raise ValueError(f"missing 'id' in module data: {data!r}")
|
|
|
|
type_tag = data["type"]
|
|
if type_tag == "fixed_values":
|
|
return _fixed_value_from_dict(data)
|
|
|
|
raise ValueError(f"Unknown module type: {type_tag!r}")
|
|
|
|
|
|
def _fixed_value_from_dict(data: dict[str, Any]) -> FixedValueModule:
|
|
meta_data = data.get("meta", {}) or {}
|
|
meta = ModuleMeta(
|
|
name=meta_data.get("name", ""),
|
|
description=meta_data.get("description", ""),
|
|
category=meta_data.get("category", ""),
|
|
tags=list(meta_data.get("tags", []) or []),
|
|
)
|
|
entries = [
|
|
FixedValueEntry(
|
|
variable_name=entry.get("variable_name", ""),
|
|
value=entry.get("value", ""),
|
|
)
|
|
for entry in (data.get("entries") or [])
|
|
]
|
|
return FixedValueModule(
|
|
id=data["id"],
|
|
enabled=bool(data.get("enabled", True)),
|
|
meta=meta,
|
|
entries=entries,
|
|
)
|