from __future__ import annotations from dataclasses import dataclass import json from pathlib import Path @dataclass(frozen=True) class QueryForm: intent: str prefix: tuple[str, ...] relation: str = "" relation_mode: str = "fixed" subject_mode: str = "tail" subject_start: int = 0 subject_end_anchor: str = "" object_start_anchor: str = "" object_mode: str = "none" requires: tuple[str, ...] = () class NativeQueryFormSet: DEFAULT_PATH = Path(__file__).resolve().parents[1] / "data" / "native" / "query" / "aethon_query_forms_v1.json" def __init__(self, path: str | Path | None = None, payload: list[dict[str, object]] | None = None) -> None: self.path = Path(path) if path is not None else self.DEFAULT_PATH self.forms = self._load_forms(payload) def _load_forms(self, payload: list[dict[str, object]] | None) -> tuple[QueryForm, ...]: if payload is not None: return tuple(self._row_to_form(row) for row in payload) if not self.path.exists(): return () data = json.loads(self.path.read_text(encoding="utf-8")) return tuple(self._row_to_form(row) for row in data) @staticmethod def _row_to_form(row: dict[str, object]) -> QueryForm: return QueryForm( intent=str(row["intent"]).strip(), prefix=tuple(str(item).strip() for item in row.get("prefix", [])), relation=str(row.get("relation", "")).strip(), relation_mode=str(row.get("relation_mode", "fixed")).strip(), subject_mode=str(row.get("subject_mode", "tail")).strip(), subject_start=int(row.get("subject_start", 0)), subject_end_anchor=str(row.get("subject_end_anchor", "")).strip(), object_start_anchor=str(row.get("object_start_anchor", "")).strip(), object_mode=str(row.get("object_mode", "none")).strip(), requires=tuple(str(item).strip() for item in row.get("requires", [])), ) def to_payload(self) -> list[dict[str, object]]: return [ { "intent": form.intent, "prefix": list(form.prefix), "relation": form.relation, "relation_mode": form.relation_mode, "subject_mode": form.subject_mode, "subject_start": form.subject_start, "subject_end_anchor": form.subject_end_anchor, "object_start_anchor": form.object_start_anchor, "object_mode": form.object_mode, "requires": list(form.requires), } for form in self.forms ]