41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
"""Everything the node reads from the environment, parsed once at startup.
|
|
|
|
Parsing happens here rather than where each value is used, so an unusable
|
|
setting stops the node before it joins the dataflow instead of surfacing the
|
|
first time somebody picks up the gamepad.
|
|
"""
|
|
|
|
import os
|
|
from dataclasses import dataclass
|
|
|
|
|
|
def env_int(name: str, default: int) -> int:
|
|
"""Read a whole number, naming the variable if it cannot be read as one."""
|
|
value = os.environ.get(name, "").strip()
|
|
if not value:
|
|
return default
|
|
try:
|
|
return int(value)
|
|
except ValueError:
|
|
raise ValueError(f"{name} must be a whole number, not {value!r}") from None
|
|
|
|
|
|
@dataclass
|
|
class Config:
|
|
"""The node's settings.
|
|
|
|
Short on purpose. A deadzone, a response curve and a speed all describe what
|
|
a reading should *do*, and this node does not know — it reads a pad and says
|
|
so. Adding them here would mean two places shaping the same number.
|
|
"""
|
|
|
|
joystick_index: int
|
|
|
|
@classmethod
|
|
def from_env(cls) -> "Config":
|
|
"""Build the configuration from the environment, refusing anything unusable."""
|
|
index = env_int("JOYSTICK_INDEX", 0)
|
|
if index < 0:
|
|
raise ValueError(f"JOYSTICK_INDEX must not be negative, not {index}")
|
|
return cls(joystick_index=index)
|