Rework radar system
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
"""Resolved profile bindings, derived from the GUI dataclass field declarations."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, fields, is_dataclass
|
||||
from typing import Iterator
|
||||
|
||||
from python_app.models.gui_profile_schema import GuiStateModel, Scalar, Setting
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class BoundSetting:
|
||||
"""A declaration resolved to its persistent field and processing page."""
|
||||
|
||||
path: tuple[str, ...]
|
||||
spec: Setting
|
||||
mode: str | None
|
||||
|
||||
def read(self, gui: GuiStateModel) -> Scalar:
|
||||
value: object = gui
|
||||
for name in self.path:
|
||||
value = getattr(value, name)
|
||||
if not isinstance(value, (str, int, float)):
|
||||
raise TypeError(f"Setting {'.'.join(self.path)} must be a scalar")
|
||||
return value
|
||||
|
||||
def write(self, gui: GuiStateModel, value: Scalar) -> None:
|
||||
owner = gui
|
||||
for name in self.path[:-1]:
|
||||
owner = getattr(owner, name)
|
||||
setattr(owner, self.path[-1], value)
|
||||
|
||||
|
||||
def _settings(model: object, path: tuple[str, ...] = ()) -> Iterator[BoundSetting]:
|
||||
if not is_dataclass(model) or isinstance(model, type):
|
||||
return
|
||||
for member in fields(model):
|
||||
member_path = (*path, member.name)
|
||||
spec = member.metadata.get("setting")
|
||||
if isinstance(spec, Setting):
|
||||
mode = member_path[1] if member_path[0] == "processing" and len(member_path) == 3 else None
|
||||
yield BoundSetting(member_path, spec, mode)
|
||||
else:
|
||||
yield from _settings(getattr(model, member.name), member_path)
|
||||
|
||||
|
||||
GUI_FIELDS = tuple(_settings(GuiStateModel()))
|
||||
|
||||
|
||||
def active_live_fields(mode: str) -> tuple[BoundSetting, ...]:
|
||||
"""Use the selected page for shared fields; retain other fields' own values."""
|
||||
selected: dict[str, BoundSetting] = {}
|
||||
for binding in GUI_FIELDS:
|
||||
name = binding.spec.live
|
||||
if name and (name not in selected or binding.mode == mode):
|
||||
selected[name] = binding
|
||||
return tuple(selected.values())
|
||||
|
||||
|
||||
def active_web_fields(mode: str) -> tuple[BoundSetting, ...]:
|
||||
"""Expose only settings belonging to the current processing page."""
|
||||
return tuple(binding for binding in GUI_FIELDS
|
||||
if binding.spec.web and binding.mode in (None, mode))
|
||||
Reference in New Issue
Block a user