From ef4bc011ab89d309f99a90dc95fdf0d4a756a0a7 Mon Sep 17 00:00:00 2001 From: Dawn Date: Wed, 19 Aug 2026 13:28:27 +0200 Subject: [PATCH] chore: do not use the special red tooltip, stay consistent --- CLAUDE.md | 31 +++++++++++++++++++++++++++++++ src/aare/gui/styles.py | 11 +---------- uv.lock | 8 ++++---- 3 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..e48f2f9e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,31 @@ +# AareDAQ project notes + +## CI gates — run locally BEFORE every commit/push + +CI enforces more than `ruff check` + green tests. Two extra gates diff +against `origin/main`, so they fail on changed lines that a plain lint or +full-suite pass never inspects (`git fetch origin main` first): + +1. `uv run ruff check` and `uv run ruff format --check` +2. Typecheck the diff (part of the lint job; ONE new basedpyright + violation on a changed line fails CI): + `uv run diff-quality --violations=basedpyright --fail-under=100 --compare-branch=origin/main` +3. Diff coverage >= 80% (coverage-analysis job): + `QT_QPA_PLATFORM=offscreen uv run pytest --cov=aare --cov-config=./pyproject.toml --cov-branch --cov-report=xml --no-cov-on-fail ./tests/unit` + `uv run diff-cover coverage.xml --compare-branch=origin/main --fail-under=80` + +A pre-push hook in the shared `.git/hooks` runs all of the above; bypass +only deliberately with `git push --no-verify`. + +Gotchas learned the hard way: +- The `diff-quality` basedpyright plugin is an editable install from + `~/repos/aare_suite/diff_quality_basedpyright` (gitea + mx/diff_quality_basedpyright). On ModuleNotFoundError reinstall with + `uv pip install -e ~/repos/aare_suite/diff_quality_basedpyright`. +- basedpyright rejects lazily created instance attributes — initialize in + `__init__`, no `hasattr` patterns. +- Every new branch needs a test that executes it or diff coverage sinks. +- Run GUI tests with `QT_QPA_PLATFORM=offscreen`; a blocking popup (e.g. a + real `QMenu.exec()`) otherwise freezes the suite on macOS. PySide method + lookup ignores class-attribute monkeypatches — patch by swapping in a + Python subclass instead. diff --git a/src/aare/gui/styles.py b/src/aare/gui/styles.py index 7cdd5d56..ec5ec8cb 100644 --- a/src/aare/gui/styles.py +++ b/src/aare/gui/styles.py @@ -559,22 +559,13 @@ TOOLTIP_FG = "#263043" DARK_TOOLTIP_BG = "#0e1728" # dusk panel2 — deepest opaque (menus/tooltips) DARK_TOOLTIP_FG = "#e9edf4" # dusk text -# "Needs admin/staff" warning tips: same passive QToolTip, on a Catppuccin -# red wash — a denial reads as a warning without a click-to-close dialog. -ADMIN_TIP_BG = "#d20f39" # latte red -ADMIN_TIP_FG = "#ffffff" -DARK_ADMIN_TIP_BG = "#f38ba8" # mocha red -DARK_ADMIN_TIP_FG = "#11111b" # mocha crust - def admin_tip_qss(theme: str) -> str: """QToolTip rule for admin-only warning tips. Set it on the widget the tip is shown for, never app-wide — QToolTip inherits QSS from that widget, and an app-wide rule would turn every tooltip red.""" bg, fg = ( - (DARK_ADMIN_TIP_BG, DARK_ADMIN_TIP_FG) - if theme == THEME_SUNSET - else (ADMIN_TIP_BG, ADMIN_TIP_FG) + (DARK_TOOLTIP_BG, DARK_TOOLTIP_FG) if theme == THEME_SUNSET else (TOOLTIP_BG, TOOLTIP_FG) ) # Transparent border required, same as the app-wide QToolTip rule. return ( diff --git a/uv.lock b/uv.lock index 72a73a21..f9e5bff9 100644 --- a/uv.lock +++ b/uv.lock @@ -31,7 +31,7 @@ wheels = [ [[package]] name = "aaredaq" -version = "0.8.3" +version = "0.11.0" source = { editable = "." } dependencies = [ { name = "aarecommon" }, @@ -330,7 +330,7 @@ name = "cffi" version = "2.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pycparser", marker = "implementation_name != 'PyPy'" }, + { name = "pycparser" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z" } wheels = [ @@ -2601,7 +2601,7 @@ resolution-markers = [ "python_full_version < '3.12'", ] dependencies = [ - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" } }, ] sdist = { url = "https://files.pythonhosted.org/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0", size = 30573822, upload-time = "2026-02-23T00:26:24.851Z" } wheels = [ @@ -2675,7 +2675,7 @@ resolution-markers = [ "python_full_version >= '3.12'", ] dependencies = [ - { name = "numpy", version = "2.5.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "numpy", version = "2.5.2", source = { registry = "https://pypi.org/simple" } }, ] sdist = { url = "https://files.pythonhosted.org/packages/a7/25/c2700dfaf6442b4effaa91af24ebce5dc9d31bb4a69706313aae70d72cd0/scipy-1.18.0.tar.gz", hash = "sha256:67b2ad2ad54c72ca6d04975a9b2df8c3638c34ddd5b28738e94fc2b57929d378", size = 30774447, upload-time = "2026-06-19T15:01:43.456Z" } wheels = [