Files

39 lines
1.5 KiB
Python

"""Actionable input validation. Never repair malformed configuration silently."""
import math
from numbers import Real
def number(value, label, minimum, maximum):
if isinstance(value, bool) or not isinstance(value, Real):
raise ValueError(f"{label}: expected a number, received {type(value).__name__}. "
"Check the connected config/reader socket; text is not a numeric setting.")
if not math.isfinite(value) or not minimum <= value <= maximum:
raise ValueError(f"{label}: expected a finite number from {minimum} to {maximum}; got {value!r}.")
return value
def integer(value, label, minimum, maximum):
if isinstance(value, bool) or not isinstance(value, int) or not minimum <= value <= maximum:
raise ValueError(f"{label}: expected an integer from {minimum} to {maximum}; got {value!r}.")
return value
def boolean(value, label):
if not isinstance(value, bool):
raise ValueError(f"{label}: expected a boolean, received {type(value).__name__}.")
return value
def text(value, label):
if not isinstance(value, str):
raise ValueError(f"{label}: expected text, received {type(value).__name__}. "
"Connect a STRING reader, not a FLOAT/INT reader.")
return value
def choice(value, label, choices):
text(value, label)
if value not in choices:
raise ValueError(f"{label}: {value!r} is not supported. Choose one of: {', '.join(choices)}.")
return value