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:
co-authored by
Claude
parent
e56eeef8f0
commit
0b20f53cf8
@@ -366,6 +366,31 @@ class Inverter:
|
||||
def batt_invert(self) -> bool:
|
||||
return bool(getattr(self.driver, "batt_invert", False))
|
||||
|
||||
# Assigning one writes through to the driver, as the attributes did before
|
||||
# SMA-2 (nothing in the repo assigns them today; this keeps it working).
|
||||
# A driver that has no such field refuses, rather than losing the value.
|
||||
def _set_driver_field(self, name, value):
|
||||
if not hasattr(self.driver, name):
|
||||
raise AttributeError(
|
||||
f"{type(self.driver).__name__} has no {name}")
|
||||
setattr(self.driver, name, value)
|
||||
|
||||
@setpoint_entity.setter
|
||||
def setpoint_entity(self, v):
|
||||
self._set_driver_field("setpoint_entity", str(v or ""))
|
||||
|
||||
@soc_entity.setter
|
||||
def soc_entity(self, v):
|
||||
self._set_driver_field("soc_entity", str(v or ""))
|
||||
|
||||
@batt_entity.setter
|
||||
def batt_entity(self, v):
|
||||
self._set_driver_field("batt_entity", str(v or ""))
|
||||
|
||||
@batt_invert.setter
|
||||
def batt_invert(self, v):
|
||||
self._set_driver_field("batt_invert", bool(v))
|
||||
|
||||
# -- store ---------------------------------------------------------------
|
||||
def key(self, name: str) -> str:
|
||||
"""This unit's namespaced Store key for `name`. See store.unit_key()."""
|
||||
|
||||
@@ -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]:
|
||||
|
||||
Reference in New Issue
Block a user