Run the fit check as a module, so it works where nothing is installed
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

CI caught what a developer machine cannot: the hook died with "No module
named" its own package. The package is pip-installed locally, so running the
script by path found it anyway; a fresh checkout has no install, and
`python3 scripts/x.py` puts only `scripts/` on sys.path.
`python3 -m scripts.verify_screen_fits` puts the repo root there instead,
which is the checkout in CI and locally alike. The xvfb re-exec runs the same
way, with an explicit cwd so the child does not depend on where the parent was
invoked from.

pylint had the same blind spot for the same reason: it infers sys.path from
the files it is handed, so a script outside the package resolved its imports
only when a package file happened to be in the same batch -- passing or
failing by what else was staged. An init-hook puts the repo root on the path
unconditionally.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXnTHyuuCUZsqetTaajcF
This commit is contained in:
Krzysztof Rudnicki 2026-08-03 16:37:02 +02:00
parent fea60814c2
commit f878d48f11
3 changed files with 16 additions and 3 deletions

View File

@ -141,7 +141,7 @@ repos:
types: [shell]
- id: screens-fit
name: Every lock screen fits 1366x768 (no scrolling required)
entry: python3 scripts/verify_screen_fits.py
entry: python3 -m scripts.verify_screen_fits
language: system
files: '^wake_alarm/.*\.py$'
pass_filenames: false

View File

@ -95,6 +95,12 @@ color_output = true
exclude = [".venv/"]
[tool.pylint.main]
# The repo root on the path, so a file outside the package (scripts/) can be
# linted on its own. pylint otherwise infers the path from the files it is
# given, so a script resolved its package imports only when a package file
# happened to be in the same batch -- passing or failing by what else was
# staged.
init-hook = "import sys; sys.path.insert(0, '.')"
analyse-fallback-blocks = true
persistent = true
jobs = 0

View File

@ -12,7 +12,12 @@ Runs the real builders against a real (throwaway) X display, because widget
heights come from the font engine and nothing short of rendering can answer
this honestly:
python3 ~/wake-alarm/scripts/verify_screen_fits.py
cd ~/wake-alarm && python3 -m scripts.verify_screen_fits
Run as a *module*, not a path: ``-m`` puts the repo root on
``sys.path`` so ``wake_alarm`` resolves from the checkout. Running it as a
path only works where the package happens to be pip-installed, which is
why it passed locally and died in CI.
"""
from __future__ import annotations
@ -71,9 +76,11 @@ def reexec_under_xvfb() -> int:
"-s",
"-screen 0 1600x1200x24",
sys.executable,
str(Path(__file__).resolve()),
"-m",
"scripts.verify_screen_fits",
],
check=False,
cwd=Path(__file__).resolve().parent.parent,
env=env,
).returncode