Files

101 lines
3.2 KiB
Python

from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any
SEMANTIC_SCENE_SCHEMA: dict[str, Any] = {
"type": "object",
"additionalProperties": False,
"required": ["page", "intents", "widgets"],
"properties": {
"page": {
"type": "string",
"minLength": 1,
},
"intents": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
},
},
"widgets": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": False,
"required": ["element_id", "purpose"],
"properties": {
"element_id": {
"type": "string",
"minLength": 1,
},
"purpose": {
"type": "string",
"minLength": 1,
},
},
},
},
},
}
@dataclass(frozen=True)
class SemanticWidget:
element_id: str
purpose: str
def to_dict(self) -> dict[str, str]:
return {
"element_id": self.element_id,
"purpose": self.purpose,
}
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "SemanticWidget":
if not isinstance(data, dict):
raise TypeError("semantic widget must be a mapping")
element_id = data.get("element_id")
purpose = data.get("purpose")
if not isinstance(element_id, str) or not element_id.strip():
raise ValueError("semantic widget element_id must be a non-empty string")
if not isinstance(purpose, str) or not purpose.strip():
raise ValueError("semantic widget purpose must be a non-empty string")
return cls(element_id=element_id, purpose=purpose)
@dataclass(frozen=True)
class SemanticScene:
page: str
intents: list[str] = field(default_factory=list)
widgets: list[SemanticWidget] = field(default_factory=list)
def to_dict(self) -> dict[str, Any]:
return {
"page": self.page,
"intents": list(self.intents),
"widgets": [widget.to_dict() for widget in self.widgets],
}
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "SemanticScene":
if not isinstance(data, dict):
raise TypeError("semantic scene must be a mapping")
page = data.get("page")
intents = data.get("intents")
widgets = data.get("widgets")
if not isinstance(page, str) or not page.strip():
raise ValueError("semantic scene page must be a non-empty string")
if not isinstance(intents, list) or not all(
isinstance(intent, str) and intent.strip() for intent in intents
):
raise ValueError("semantic scene intents must be non-empty strings")
if not isinstance(widgets, list):
raise ValueError("semantic scene widgets must be a list")
return cls(
page=page,
intents=list(intents),
widgets=[SemanticWidget.from_dict(widget) for widget in widgets],
)