some fixes
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from typing import Any
|
||||
|
||||
from python_app.models.run_config_schema import (
|
||||
@@ -38,9 +39,67 @@ def _read_str(payload: dict[str, Any], key: str, default: str) -> str:
|
||||
value = payload.get(key, default)
|
||||
if value is None:
|
||||
return default
|
||||
# A JSON array/object reaching a scalar field is a config error, not a
|
||||
# str() fallback; surface it as ValueError to keep the error contract uniform.
|
||||
if isinstance(value, (dict, list)):
|
||||
raise ValueError(f"{key} must be a JSON string")
|
||||
return str(value)
|
||||
|
||||
|
||||
def _read_int(payload: dict[str, Any], key: str, default: int) -> int:
|
||||
"""Return payload integer, treating an explicit JSON `null` as 'use default'.
|
||||
|
||||
Without this, `int(payload.get(key, default))` raises TypeError on an
|
||||
explicit `null`. JSON arrays/objects (and other non-numeric scalars) are
|
||||
rejected as ValueError so malformed types share the config-error contract.
|
||||
"""
|
||||
value = payload.get(key, default)
|
||||
if value is None:
|
||||
return default
|
||||
if isinstance(value, bool) or not isinstance(value, (int, float, str)):
|
||||
raise ValueError(f"{key} must be a JSON integer")
|
||||
try:
|
||||
return int(value)
|
||||
except (TypeError, ValueError) as exc:
|
||||
raise ValueError(f"{key} must be a JSON integer") from exc
|
||||
|
||||
|
||||
def _read_float(payload: dict[str, Any], key: str, default: float) -> float:
|
||||
"""Return payload float, treating an explicit JSON `null` as 'use default'.
|
||||
|
||||
Rejects JSON arrays/objects (and other non-numeric scalars) as ValueError,
|
||||
and rejects non-finite values (NaN/Infinity) at decode time so the C++
|
||||
pipeline never receives a value it cannot honor.
|
||||
"""
|
||||
value = payload.get(key, default)
|
||||
if value is None:
|
||||
return default
|
||||
if isinstance(value, bool) or not isinstance(value, (int, float, str)):
|
||||
raise ValueError(f"{key} must be a JSON number")
|
||||
try:
|
||||
result = float(value)
|
||||
except (TypeError, ValueError) as exc:
|
||||
raise ValueError(f"{key} must be a JSON number") from exc
|
||||
if not math.isfinite(result):
|
||||
raise ValueError(f"{key} must be a finite number")
|
||||
return result
|
||||
|
||||
|
||||
def _read_bool(payload: dict[str, Any], key: str, default: bool) -> bool:
|
||||
"""Return payload boolean, treating an explicit JSON `null` as 'use default'.
|
||||
|
||||
Plain `bool(payload.get(key, default))` would silently flip the default to
|
||||
`False` on an explicit `null`; here `null` keeps the default instead.
|
||||
Non-boolean JSON types are rejected as ValueError.
|
||||
"""
|
||||
value = payload.get(key, default)
|
||||
if value is None:
|
||||
return default
|
||||
if not isinstance(value, bool):
|
||||
raise ValueError(f"{key} must be a JSON boolean")
|
||||
return value
|
||||
|
||||
|
||||
def _load_preprocess_asset(payload: dict[str, Any], target: PreprocessAssetModel) -> None:
|
||||
"""Load preprocess asset fields into target model."""
|
||||
target.set_name = _read_str(payload, "set_name", target.set_name)
|
||||
@@ -105,21 +164,21 @@ def run_config_from_dict(payload: dict[str, Any]) -> RunConfigModel:
|
||||
kamil_adc_payload = _as_dict(radar_payload.get("kamil_adc"), "radar.kamil_adc")
|
||||
laser_control_payload = _as_dict(radar_payload.get("laser_control"), "radar.laser_control")
|
||||
|
||||
model.radar.model = str(radar_payload.get("model", model.radar.model))
|
||||
model.radar.serial = str(radar_payload.get("serial", model.radar.serial))
|
||||
model.radar.remote_host = str(radar_payload.get("remote_host", model.radar.remote_host))
|
||||
model.radar.remote_port = int(radar_payload.get("remote_port", model.radar.remote_port))
|
||||
model.radar.driver_mode = str(radar_payload.get("driver_mode", model.radar.driver_mode))
|
||||
model.radar.mock_signal_hz = float(radar_payload.get("mock_signal_hz", model.radar.mock_signal_hz))
|
||||
model.radar.visa_library = str(radar_payload.get("visa_library", model.radar.visa_library))
|
||||
model.radar.model = _read_str(radar_payload, "model", model.radar.model)
|
||||
model.radar.serial = _read_str(radar_payload, "serial", model.radar.serial)
|
||||
model.radar.remote_host = _read_str(radar_payload, "remote_host", model.radar.remote_host)
|
||||
model.radar.remote_port = _read_int(radar_payload, "remote_port", model.radar.remote_port)
|
||||
model.radar.driver_mode = _read_str(radar_payload, "driver_mode", model.radar.driver_mode)
|
||||
model.radar.mock_signal_hz = _read_float(radar_payload, "mock_signal_hz", model.radar.mock_signal_hz)
|
||||
model.radar.visa_library = _read_str(radar_payload, "visa_library", model.radar.visa_library)
|
||||
|
||||
model.radar.sweep.start_hz = float(sweep_payload.get("start_hz", model.radar.sweep.start_hz))
|
||||
model.radar.sweep.stop_hz = float(sweep_payload.get("stop_hz", model.radar.sweep.stop_hz))
|
||||
model.radar.sweep.points = int(sweep_payload.get("points", model.radar.sweep.points))
|
||||
model.radar.sweep.if_bandwidth_hz = float(
|
||||
sweep_payload.get("if_bandwidth_hz", model.radar.sweep.if_bandwidth_hz)
|
||||
model.radar.sweep.start_hz = _read_float(sweep_payload, "start_hz", model.radar.sweep.start_hz)
|
||||
model.radar.sweep.stop_hz = _read_float(sweep_payload, "stop_hz", model.radar.sweep.stop_hz)
|
||||
model.radar.sweep.points = _read_int(sweep_payload, "points", model.radar.sweep.points)
|
||||
model.radar.sweep.if_bandwidth_hz = _read_float(
|
||||
sweep_payload, "if_bandwidth_hz", model.radar.sweep.if_bandwidth_hz
|
||||
)
|
||||
model.radar.sweep.power_dbm = float(sweep_payload.get("stimulus_power_dbm", model.radar.sweep.power_dbm))
|
||||
model.radar.sweep.power_dbm = _read_float(sweep_payload, "stimulus_power_dbm", model.radar.sweep.power_dbm)
|
||||
slave_serials_payload = multi_device_payload.get(
|
||||
"slave_serials",
|
||||
multi_device_payload.get("slave_serial_numbers", model.radar.multi_device.slave_serials),
|
||||
@@ -132,121 +191,114 @@ def run_config_from_dict(payload: dict[str, Any]) -> RunConfigModel:
|
||||
for value in slave_serials_payload.split(",")
|
||||
if value.strip()
|
||||
]
|
||||
model.radar.multi_device.force_external_reference = bool(
|
||||
multi_device_payload.get(
|
||||
"force_external_reference",
|
||||
model.radar.multi_device.force_external_reference,
|
||||
)
|
||||
model.radar.multi_device.force_external_reference = _read_bool(
|
||||
multi_device_payload,
|
||||
"force_external_reference",
|
||||
model.radar.multi_device.force_external_reference,
|
||||
)
|
||||
model.radar.multi_device.recovery_attempts = int(
|
||||
multi_device_payload.get(
|
||||
"recovery_attempts",
|
||||
model.radar.multi_device.recovery_attempts,
|
||||
)
|
||||
model.radar.multi_device.recovery_attempts = _read_int(
|
||||
multi_device_payload,
|
||||
"recovery_attempts",
|
||||
model.radar.multi_device.recovery_attempts,
|
||||
)
|
||||
model.radar.kamil_adc.project_dir = str(
|
||||
kamil_adc_payload.get("project_dir", model.radar.kamil_adc.project_dir)
|
||||
model.radar.kamil_adc.project_dir = _read_str(
|
||||
kamil_adc_payload, "project_dir", model.radar.kamil_adc.project_dir
|
||||
)
|
||||
model.radar.kamil_adc.executable_path = str(
|
||||
kamil_adc_payload.get("executable_path", model.radar.kamil_adc.executable_path)
|
||||
model.radar.kamil_adc.executable_path = _read_str(
|
||||
kamil_adc_payload, "executable_path", model.radar.kamil_adc.executable_path
|
||||
)
|
||||
model.radar.kamil_adc.tty_path = str(
|
||||
kamil_adc_payload.get("tty_path", model.radar.kamil_adc.tty_path)
|
||||
model.radar.kamil_adc.tty_path = _read_str(
|
||||
kamil_adc_payload, "tty_path", model.radar.kamil_adc.tty_path
|
||||
)
|
||||
model.radar.kamil_adc.args = _load_string_list(kamil_adc_payload, "args", "radar.kamil_adc")
|
||||
model.radar.kamil_adc.env = _load_string_dict(kamil_adc_payload, "env", "radar.kamil_adc")
|
||||
model.radar.kamil_adc.startup_timeout_s = float(
|
||||
kamil_adc_payload.get("startup_timeout_s", model.radar.kamil_adc.startup_timeout_s)
|
||||
model.radar.kamil_adc.startup_timeout_s = _read_float(
|
||||
kamil_adc_payload, "startup_timeout_s", model.radar.kamil_adc.startup_timeout_s
|
||||
)
|
||||
model.radar.kamil_adc.sweep_timeout_s = float(
|
||||
kamil_adc_payload.get("sweep_timeout_s", model.radar.kamil_adc.sweep_timeout_s)
|
||||
model.radar.kamil_adc.sweep_timeout_s = _read_float(
|
||||
kamil_adc_payload, "sweep_timeout_s", model.radar.kamil_adc.sweep_timeout_s
|
||||
)
|
||||
model.radar.kamil_adc.stop_timeout_s = float(
|
||||
kamil_adc_payload.get("stop_timeout_s", model.radar.kamil_adc.stop_timeout_s)
|
||||
model.radar.kamil_adc.stop_timeout_s = _read_float(
|
||||
kamil_adc_payload, "stop_timeout_s", model.radar.kamil_adc.stop_timeout_s
|
||||
)
|
||||
|
||||
model.radar.laser_control.enabled = bool(
|
||||
laser_control_payload.get("enabled", model.radar.laser_control.enabled)
|
||||
model.radar.laser_control.enabled = _read_bool(
|
||||
laser_control_payload, "enabled", model.radar.laser_control.enabled
|
||||
)
|
||||
model.radar.laser_control.port = str(
|
||||
laser_control_payload.get("port", model.radar.laser_control.port)
|
||||
model.radar.laser_control.port = _read_str(
|
||||
laser_control_payload, "port", model.radar.laser_control.port
|
||||
)
|
||||
model.radar.laser_control.mode = str(
|
||||
laser_control_payload.get("mode", model.radar.laser_control.mode)
|
||||
model.radar.laser_control.mode = _read_str(
|
||||
laser_control_payload, "mode", model.radar.laser_control.mode
|
||||
)
|
||||
model.radar.laser_control.pi_coeff1_p = int(
|
||||
laser_control_payload.get("pi_coeff1_p", model.radar.laser_control.pi_coeff1_p)
|
||||
model.radar.laser_control.pi_coeff1_p = _read_int(
|
||||
laser_control_payload, "pi_coeff1_p", model.radar.laser_control.pi_coeff1_p
|
||||
)
|
||||
model.radar.laser_control.pi_coeff1_i = int(
|
||||
laser_control_payload.get("pi_coeff1_i", model.radar.laser_control.pi_coeff1_i)
|
||||
model.radar.laser_control.pi_coeff1_i = _read_int(
|
||||
laser_control_payload, "pi_coeff1_i", model.radar.laser_control.pi_coeff1_i
|
||||
)
|
||||
model.radar.laser_control.pi_coeff2_p = int(
|
||||
laser_control_payload.get("pi_coeff2_p", model.radar.laser_control.pi_coeff2_p)
|
||||
model.radar.laser_control.pi_coeff2_p = _read_int(
|
||||
laser_control_payload, "pi_coeff2_p", model.radar.laser_control.pi_coeff2_p
|
||||
)
|
||||
model.radar.laser_control.pi_coeff2_i = int(
|
||||
laser_control_payload.get("pi_coeff2_i", model.radar.laser_control.pi_coeff2_i)
|
||||
model.radar.laser_control.pi_coeff2_i = _read_int(
|
||||
laser_control_payload, "pi_coeff2_i", model.radar.laser_control.pi_coeff2_i
|
||||
)
|
||||
laser_manual_payload = _as_dict(laser_control_payload.get("manual"), "radar.laser_control.manual")
|
||||
model.radar.laser_control.manual.temp1 = float(
|
||||
laser_manual_payload.get("temp1", model.radar.laser_control.manual.temp1)
|
||||
model.radar.laser_control.manual.temp1 = _read_float(
|
||||
laser_manual_payload, "temp1", model.radar.laser_control.manual.temp1
|
||||
)
|
||||
model.radar.laser_control.manual.temp2 = float(
|
||||
laser_manual_payload.get("temp2", model.radar.laser_control.manual.temp2)
|
||||
model.radar.laser_control.manual.temp2 = _read_float(
|
||||
laser_manual_payload, "temp2", model.radar.laser_control.manual.temp2
|
||||
)
|
||||
model.radar.laser_control.manual.current1 = float(
|
||||
laser_manual_payload.get("current1", model.radar.laser_control.manual.current1)
|
||||
model.radar.laser_control.manual.current1 = _read_float(
|
||||
laser_manual_payload, "current1", model.radar.laser_control.manual.current1
|
||||
)
|
||||
model.radar.laser_control.manual.current2 = float(
|
||||
laser_manual_payload.get("current2", model.radar.laser_control.manual.current2)
|
||||
model.radar.laser_control.manual.current2 = _read_float(
|
||||
laser_manual_payload, "current2", model.radar.laser_control.manual.current2
|
||||
)
|
||||
laser_variation_payload = _as_dict(
|
||||
laser_control_payload.get("variation"),
|
||||
"radar.laser_control.variation",
|
||||
)
|
||||
model.radar.laser_control.variation.variation_type = str(
|
||||
laser_variation_payload.get(
|
||||
"variation_type",
|
||||
model.radar.laser_control.variation.variation_type,
|
||||
)
|
||||
model.radar.laser_control.variation.variation_type = _read_str(
|
||||
laser_variation_payload,
|
||||
"variation_type",
|
||||
model.radar.laser_control.variation.variation_type,
|
||||
)
|
||||
model.radar.laser_control.variation.static_temp1 = float(
|
||||
laser_variation_payload.get(
|
||||
"static_temp1",
|
||||
model.radar.laser_control.variation.static_temp1,
|
||||
)
|
||||
model.radar.laser_control.variation.static_temp1 = _read_float(
|
||||
laser_variation_payload,
|
||||
"static_temp1",
|
||||
model.radar.laser_control.variation.static_temp1,
|
||||
)
|
||||
model.radar.laser_control.variation.static_temp2 = float(
|
||||
laser_variation_payload.get(
|
||||
"static_temp2",
|
||||
model.radar.laser_control.variation.static_temp2,
|
||||
)
|
||||
model.radar.laser_control.variation.static_temp2 = _read_float(
|
||||
laser_variation_payload,
|
||||
"static_temp2",
|
||||
model.radar.laser_control.variation.static_temp2,
|
||||
)
|
||||
model.radar.laser_control.variation.static_current1 = float(
|
||||
laser_variation_payload.get(
|
||||
"static_current1",
|
||||
model.radar.laser_control.variation.static_current1,
|
||||
)
|
||||
model.radar.laser_control.variation.static_current1 = _read_float(
|
||||
laser_variation_payload,
|
||||
"static_current1",
|
||||
model.radar.laser_control.variation.static_current1,
|
||||
)
|
||||
model.radar.laser_control.variation.static_current2 = float(
|
||||
laser_variation_payload.get(
|
||||
"static_current2",
|
||||
model.radar.laser_control.variation.static_current2,
|
||||
)
|
||||
model.radar.laser_control.variation.static_current2 = _read_float(
|
||||
laser_variation_payload,
|
||||
"static_current2",
|
||||
model.radar.laser_control.variation.static_current2,
|
||||
)
|
||||
model.radar.laser_control.variation.min_value = float(
|
||||
laser_variation_payload.get("min_value", model.radar.laser_control.variation.min_value)
|
||||
model.radar.laser_control.variation.min_value = _read_float(
|
||||
laser_variation_payload, "min_value", model.radar.laser_control.variation.min_value
|
||||
)
|
||||
model.radar.laser_control.variation.max_value = float(
|
||||
laser_variation_payload.get("max_value", model.radar.laser_control.variation.max_value)
|
||||
model.radar.laser_control.variation.max_value = _read_float(
|
||||
laser_variation_payload, "max_value", model.radar.laser_control.variation.max_value
|
||||
)
|
||||
model.radar.laser_control.variation.step = float(
|
||||
laser_variation_payload.get("step", model.radar.laser_control.variation.step)
|
||||
model.radar.laser_control.variation.step = _read_float(
|
||||
laser_variation_payload, "step", model.radar.laser_control.variation.step
|
||||
)
|
||||
model.radar.laser_control.variation.time_step = int(
|
||||
laser_variation_payload.get("time_step", model.radar.laser_control.variation.time_step)
|
||||
model.radar.laser_control.variation.time_step = _read_int(
|
||||
laser_variation_payload, "time_step", model.radar.laser_control.variation.time_step
|
||||
)
|
||||
model.radar.laser_control.variation.delay_time = int(
|
||||
laser_variation_payload.get("delay_time", model.radar.laser_control.variation.delay_time)
|
||||
model.radar.laser_control.variation.delay_time = _read_int(
|
||||
laser_variation_payload, "delay_time", model.radar.laser_control.variation.delay_time
|
||||
)
|
||||
|
||||
load_switch_payload(port1_payload, model.output_switch)
|
||||
|
||||
Reference in New Issue
Block a user