SMA-2 round 2: census keeps ACTUATOR_WRITE_KEYS, setters, NaN/inf port refused, tests

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
glenn schrooyen
2026-11-07 12:20:56 +01:00
co-authored by Claude
parent e56eeef8f0
commit 0b20f53cf8
5 changed files with 185 additions and 9 deletions
+15 -2
View File
@@ -328,6 +328,7 @@ WHAT IS DELIBERATELY *NOT* REFUSED, because it is untidy rather than unsafe:
"""
import logging
import math
import re
from typing import NamedTuple
@@ -466,6 +467,15 @@ def _collect_writers(node, path: str, out: list) -> None:
cls = drivers.driver_class(node)
for k, v in node.items():
here = f"{path}.{k}" if path else str(k)
# Every key in ACTUATOR_WRITE_KEYS declares a writer, as before
# SMA-2 and whatever the entry's driver; PLUS the entry driver's
# own writer key. The second is added to the first, never in place
# of it (census parity with 23ff9d0 is graded in test_sma2_driver).
if k in ACTUATOR_WRITE_KEYS:
entity = str(v or "").strip()
if entity:
out.append((here, entity))
continue
if k == cls.writer_key:
actuator = cls.actuator_id_of(node)
if actuator:
@@ -793,9 +803,12 @@ def _whole(raw, lo: int, hi: int):
return None
try:
val = float(raw)
except (TypeError, ValueError):
# NaN and infinity: int() raises on them, so refuse them first.
if not math.isfinite(val) or val != int(val):
return None
except (TypeError, ValueError, OverflowError):
return None
return int(val) if val == int(val) and lo <= val <= hi else None
return int(val) if lo <= val <= hi else None
def _driver_problems(entry: dict, who: str) -> list[str]: