"""Plain Python values <-> the wire's Value message. The daemon owns all SECS-II knowledge (it converts to each variable's declared wire format); this layer only maps Python types onto the Value oneof. Order matters in to_value: bool is checked before int because isinstance(True, int) is True in Python. """ from __future__ import annotations from ._proto import equipment_pb2 as pb def to_value(v) -> pb.Value: if isinstance(v, pb.Value): return v if isinstance(v, bool): return pb.Value(boolean=v) if isinstance(v, int): return pb.Value(integer=v) if isinstance(v, float): return pb.Value(real=v) if isinstance(v, str): return pb.Value(text=v) if isinstance(v, (bytes, bytearray)): return pb.Value(binary=bytes(v)) if isinstance(v, (list, tuple)): return pb.Value(list=pb.List(items=[to_value(e) for e in v])) raise TypeError(f"cannot convert {type(v).__name__} to a SECS value") def from_value(v: pb.Value): kind = v.WhichOneof("kind") if kind == "text": return v.text if kind == "integer": return v.integer if kind == "real": return v.real if kind == "boolean": return v.boolean if kind == "binary": return v.binary if kind == "list": return [from_value(e) for e in v.list.items] return None # unset