mirror of
https://github.com/kuhyx/wake-alarm.git
synced 2026-11-10 18:07:05 +01:00
All PC enforcement (fallback ring, RTC self-wake, trigger, workday penalty write/retract, audit) now asks sickdays.stands_down(LOCKER_ALARM, day) via _sick.alarm_stands_down instead of is_sick_day, so a sick day that keeps the alarm behaves exactly as a normal stick day. Bump sickdays pin to v0.2.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PAhbNszs5JKdtnD4uBi3xp
63 lines
2.3 KiB
Python
63 lines
2.3 KiB
Python
"""Sick days: the one place wake_alarm asks the shared ``sickdays`` pool.
|
|
|
|
A sick day (``~/src/utils/sickdays``) is not a free day -- a separate pool,
|
|
no cap, no reason -- but on the PC it stands down the same things: no
|
|
fallback ring, no RTC self-wake, no workday penalty, no morning routine.
|
|
|
|
All of that is **one switch**: the ``alarm`` locker. A sick day may *keep*
|
|
the alarm (``sickdays`` 0.2.0), and then every piece above behaves exactly as
|
|
on a normal day, so the question this module answers is
|
|
``stands_down(LOCKER_ALARM, day)``, never plain ``is_sick_day``.
|
|
|
|
Two rules this module exists to keep in one spot:
|
|
|
|
* **Fail closed.** ``sickdays.stands_down`` never raises and reads a corrupt
|
|
pool as "not sick". The import is guarded as well: these jobs run under
|
|
``/usr/bin/python``, and a package that failed to install must leave
|
|
enforcement *on* (not standing down), never crash the per-minute tick -- a crashed
|
|
tick rings nothing.
|
|
* **Sync only where something is about to happen, never in a read-only
|
|
mode.** ``sync_quietly`` rewrites the local pool, so ``--dry-run`` and
|
|
``--show`` never call it. The sickdays timer alone is not enough: it is a
|
|
monotonic 15-minute timer, which pauses during hibernate and has no
|
|
``Persistent`` catch-up, so right after the RTC resume the pool can be a
|
|
whole interval stale -- exactly when a day marked sick from bed matters.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import TYPE_CHECKING
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
try:
|
|
import sickdays
|
|
|
|
_AVAILABLE = True
|
|
except ImportError:
|
|
_AVAILABLE = False
|
|
_logger.warning("sickdays is not installed; no day counts as sick")
|
|
|
|
if TYPE_CHECKING:
|
|
from datetime import date
|
|
|
|
|
|
def alarm_stands_down(day: date) -> bool:
|
|
"""Whether the alarm is switched off on ``day``; local file, never raises.
|
|
|
|
True iff ``day`` is sick and its keep set does not hold the alarm.
|
|
"""
|
|
return _AVAILABLE and sickdays.stands_down(sickdays.LOCKER_ALARM, day)
|
|
|
|
|
|
def sync() -> bool:
|
|
"""Pull the pool from Firebase now; False when it could not (silently)."""
|
|
return _AVAILABLE and sickdays.sync_quietly()
|
|
|
|
|
|
def alarm_stands_down_synced(day: date) -> bool:
|
|
""":func:`alarm_stands_down` after a fresh :func:`sync` -- act modes only."""
|
|
sync()
|
|
return alarm_stands_down(day)
|