feat: implement slot_error_boundary decorator and add unit tests for session and device controllers

This commit is contained in:
jack
2026-06-18 21:01:37 -07:00
parent 5514653b94
commit 7206334a27
6 changed files with 353 additions and 1 deletions
@@ -12,6 +12,7 @@ from PySide6.QtCore import Property, QObject, Qt, Signal, Slot
from pygui.backend.controllers.session_controller import SessionController
from pygui.backend.data.local_settings import LocalSettings
from pygui.backend.models.data_model import TemperatureTableModel
from pygui.backend.utils import slot_error_boundary
from pygui.backend.visualization.graph_view import GraphView
from pygui.serialcomm.data_parser import (
convert_to_temperatures,
@@ -116,6 +117,7 @@ class DeviceController(QObject):
return self._save_data_dir
@Slot(str)
@slot_error_boundary
def setSaveDataDir(self, path: str) -> None:
"""Set the directory for saving parsed CSV data files."""
self._save_data_dir = path
@@ -128,6 +130,7 @@ class DeviceController(QObject):
return self._selected_port
@Slot(str)
@slot_error_boundary
def setSelectedPort(self, port: str) -> None:
"""Set the active serial port from the port selector."""
self._selected_port = port
@@ -170,6 +173,7 @@ class DeviceController(QObject):
return self._graph_view
@Slot(result=object)
@slot_error_boundary
def getChartData(self) -> dict[str, Any]:
"""Extract chart-ready data from the current model.
@@ -208,6 +212,7 @@ class DeviceController(QObject):
self.activityLogUpdated.emit("\n".join(self._activity_log))
@Slot()
@slot_error_boundary
def clearActivityLog(self) -> None:
"""Clear the activity log."""
self._activity_log.clear()
@@ -215,6 +220,7 @@ class DeviceController(QObject):
self._save_status()
@Slot()
@slot_error_boundary
def clearSession(self) -> None:
"""Clear the current session state, allowing a clean detect."""
self._connection_status = "Disconnected"
@@ -242,6 +248,7 @@ class DeviceController(QObject):
# ---- Public Slots ----
@Slot()
@slot_error_boundary
def refreshPorts(self) -> None:
"""Scan for available serial ports and emit updated list."""
ports = self._service.enumerate_ports()
@@ -251,6 +258,7 @@ class DeviceController(QObject):
self._save_status()
@Slot()
@slot_error_boundary
def detectWafer(self) -> None:
"""Scan all serial ports for a wafer (runs in background thread).
@@ -280,6 +288,7 @@ class DeviceController(QObject):
self._detectFinished.emit(port, info)
@Slot(object, object)
@slot_error_boundary
def _handle_detect_finished(
self, port: Optional[str], info: Optional[WaferInfo]
) -> None:
@@ -304,6 +313,7 @@ class DeviceController(QObject):
self._set_operation_progress(False)
@Slot()
@slot_error_boundary
def readMemoryAsync(self) -> None:
"""Read wafer memory in a background thread.
@@ -346,6 +356,7 @@ class DeviceController(QObject):
self._readFinished.emit(port, family_code, data)
@Slot(str, str, object)
@slot_error_boundary
def _handle_read_finished(
self, port: str, family_code: str, data: Optional[bytes]
) -> None:
@@ -367,6 +378,7 @@ class DeviceController(QObject):
self._save_status()
@Slot(str)
@slot_error_boundary
def eraseMemory(self, port: str) -> None:
"""Send p1 erase command."""
self._set_operation_progress(True)
@@ -385,6 +397,7 @@ class DeviceController(QObject):
self._set_operation_progress(False)
@Slot(str)
@slot_error_boundary
def readDebug(self, port: str) -> None:
"""Read both D1 (sensor) and F1 (debug/cold-junction) data.
@@ -428,6 +441,7 @@ class DeviceController(QObject):
self._set_operation_progress(False)
@Slot(str, str)
@slot_error_boundary
def parseAndSaveData(self, family_code: str = "", port: str = "") -> None:
"""Parse raw bytes into temperatures and save to CSV.