from abc import ABC, abstractmethod from typing import Callable class AlarmStyle(ABC): """A pluggable alarm behaviour. A style decides *when* the alarm stops and what the LED does while it rings. It never touches hardware directly: ``set_led`` is injected by the runner, so styles stay import-safe in the API process (no GPIO/pygame). Lifecycle: construct once with ``set_led``, then call ``update`` every tick. Return ``False`` from ``update`` to stop the alarm. """ def __init__(self, set_led: Callable[[bool], None]): self.set_led = set_led @abstractmethod def update(self, now: float, is_pressed: bool) -> bool: """Advance the style by one tick. Args: now: current time (``time.time()`` from the runner). is_pressed: whether the button is currently held down. Returns: True to keep ringing, False to stop. """