50 lines
1.7 KiB
Python
Executable File
50 lines
1.7 KiB
Python
Executable File
"""Persisted user defaults (ports, scope IP, save directory).
|
|
|
|
One flat JSON file, one dataclass. ``save()`` always writes every field, so
|
|
a partial UI update can never silently drop another field's saved value
|
|
(which is exactly what the old dict-based writer did to helios_port).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import logging
|
|
from dataclasses import asdict, dataclass, fields
|
|
from pathlib import Path
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
DEFAULTS_PATH = Path(__file__).resolve().parent.parent / "aui_defaults.json"
|
|
|
|
|
|
@dataclass
|
|
class ScanDefaults:
|
|
t3r_port: str = "/dev/ttyUSB0"
|
|
bbd_port: str = "/dev/ttyUSB1"
|
|
oscope_ip: str = "192.168.0.1"
|
|
save_dir: str = str(DEFAULTS_PATH.parent / "scans")
|
|
helios_port: str = "/dev/ttyUSB2"
|
|
burst_mode: bool = False
|
|
strict_rows: bool = False
|
|
|
|
@classmethod
|
|
def load(cls, path: Path = DEFAULTS_PATH) -> "ScanDefaults":
|
|
"""Load defaults, tolerating a missing/corrupt file and unknown keys."""
|
|
if path.exists():
|
|
try:
|
|
with open(path) as f:
|
|
data = json.load(f)
|
|
known = {f.name for f in fields(cls)}
|
|
return cls(**{k: v for k, v in data.items() if k in known})
|
|
except (OSError, ValueError, TypeError) as e:
|
|
logger.warning("Could not load %s (%s); using fallback defaults", path, e)
|
|
inst = cls()
|
|
inst.save(path)
|
|
return inst
|
|
|
|
def save(self, path: Path = DEFAULTS_PATH) -> None:
|
|
try:
|
|
with open(path, "w") as f:
|
|
json.dump(asdict(self), f, indent=2)
|
|
except OSError as e:
|
|
logger.warning("Could not save defaults to %s: %s", path, e)
|