screen-locker/screen_locker/_cli.py
Krzysztof kuhy Rudnicki 4b4695e23a
Some checks are pending
pre-commit / pre-commit (push) Waiting to run
Tests / test (3.10) (push) Waiting to run
Tests / test (3.11) (push) Waiting to run
Tests / test (3.12) (push) Waiting to run
Tests / lock-popup-safety (push) Waiting to run
release-apk / release (APK) (push) Waiting to run
Split screen_lock.py under the 250-line cap
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-15 19:01:18 +02:00

61 lines
2.0 KiB
Python

"""Command-line entry points for ``screen_lock.py``.
Split out of ``screen_lock.py`` to keep every file under the 250-line cap.
The argument handling lives here; ``screen_lock.py`` keeps only the
``ScreenLocker`` class and a one-line ``__main__`` delegation, so the module
that every mixin imports stays small.
"""
from __future__ import annotations
import logging
from pathlib import Path
import sys
from typing import TYPE_CHECKING
from screen_locker._status import run_status
if TYPE_CHECKING:
from screen_locker.screen_lock import ScreenLocker
__all__ = ["main"]
_LOG_FILE_NAME = "workout_log.json"
def _headless_locker(locker_cls: type[ScreenLocker]) -> ScreenLocker:
"""A ScreenLocker with ``__init__`` bypassed, for the no-UI subcommands.
``--status`` and ``--sync-only`` touch only ``log_file`` and
``workout_data``; constructing the real object would build a Tk UI and,
in the ``--production`` case, grab the screen.
"""
locker = object.__new__(locker_cls)
locker.log_file = Path(__file__).resolve().parent / _LOG_FILE_NAME
locker.workout_data = {}
return locker
def main(locker_cls: type[ScreenLocker], argv: list[str]) -> None:
"""Dispatch on ``argv`` and run the requested mode."""
if "--status" in argv:
run_status(_headless_locker(locker_cls))
if "--sync-only" in argv:
# Headless sync for the timer unit: pull other devices' workouts and
# apply their credit, with no Tk and no lock screen. Sync used to run
# ONLY at process start, so a workout finished after login was not seen
# until the next login — the timer closes that window.
logging.basicConfig(
level=logging.INFO,
format="%(levelname)s %(name)s: %(message)s",
)
_headless_locker(locker_cls).sync_now()
sys.exit(0)
locker = locker_cls(
demo_mode="--production" not in argv,
verify_only="--verify-workout" in argv,
)
locker.run()