docs: update AGENTS.md to clarify Qt module import rules and threading guidelines

This commit is contained in:
2026-08-24 15:09:25 +02:00
committed by wakonig_k
parent 2655f307c1
commit 9014417b84
2 changed files with 10 additions and 33 deletions
+8 -4
View File
@@ -10,14 +10,16 @@ This file is an agent-oriented operating manual. User-facing documentation lives
## Core Rules
- Import Qt modules from `qtpy`, not `PySide6`.
- Import Qt modules from `qtpy`, not `PySide6` — CI greps for `from PySide6.` and fails the build;
only `PySide6.QtDesigner` and `PySide6.scripts` are exempt.
- Do not hand-edit generated RPC or Designer files; regenerate them with `bw-generate-cli`.
- If a widget exposes `USER_ACCESS` or is available in Qt Designer, treat its generated CLI and plugin
stubs as part of the change.
- Inherit `BECWidget` first, then the Qt base class.
- Use `MessageEndpoints`, `BECDispatcher`, `SafeSlot`, and existing local widget patterns before
introducing a new abstraction.
- Do not block the Qt event loop with slow I/O, RPC, or heavy computation.
- Do not block the Qt event loop with slow I/O, RPC, or heavy computation. Run slow work off the GUI
thread and deliver results back through signals — never touch widgets from another thread.
- Clean up dispatcher subscriptions, timers, and long-lived resources in `cleanup()`.
- Beamline-specific widgets usually belong in a plugin repository, not core `bec_widgets`.
- Keep diffs focused. Avoid unrelated refactors while fixing a specific issue.
@@ -153,8 +155,10 @@ Run the smallest relevant test target first. For substantial UI plumbing changes
changes, or work that affects many widgets, run the broader affected package suite before finishing.
Unit tests are the default. CI runs them with `--random-order`, so local validation should do the same
when practical. Create widgets with `create_widget(...)` from `tests/unit_tests/conftest.py` so
registration and teardown stay consistent. Before adding a new fixture, check for reusable fixtures in
when practical. Create widgets with `create_widget(...)` from `tests/unit_tests/conftest.py`. It
registers the widget with `qtbot` so it is closed at test end; the autouse conftest fixtures handle the
rest of the teardown (dispatcher disconnect, singleton resets) and fail the test if any top-level
widget is left open. Before adding a new fixture, check for reusable fixtures in
`tests/unit_tests/conftest.py` and helpers in `bec_widgets/tests/utils.py`.
Mock BEC, Redis, and hardware in unit tests. Reuse existing helpers such as `FakeDevice`,
+2 -29
View File
@@ -2,32 +2,5 @@
@AGENTS.md
The guidelines above are imported from [`AGENTS.md`](AGENTS.md) (single source of
truth). The points that matter most in day-to-day work:
- **Check for `AGENTS_PERSONAL.md` first.** If it exists, it extends `AGENTS.md` with
machine-specific environment setup and takes precedence over the generic venv/pip instructions there.
It is untracked and personal — never commit it, and never assume it exists.
- **Import from `qtpy`, never `PySide6.*`.** CI greps for `from PySide6.` and fails the build (only
`PySide6.QtDesigner` and `PySide6.scripts` are exempt).
- **`bec_widgets/cli/client.py` and the Designer plugin files are generated — never hand-edit them.**
Regenerate with `bw-generate-cli --target bec_widgets` whenever a widget's RPC API changes
(`USER_ACCESS` entries or an exposed signature) or a new widget with RPC access or a Qt Designer
plugin is added; CI runs the same command and `git diff --exit-code`. For a beamline plugin repo,
`--target` is that repository's importable package name (`bw-generate-cli --target my_plugin_repo`).
- **Widget pattern**: inherit `BECWidget` first, then the Qt class; declare `USER_ACCESS`; subscribe via
`BECDispatcher` + `MessageEndpoints`; decorate slots with `@SafeSlot`; reach BEC through
`self.get_bec_shortcuts()`. Disconnect subscriptions and stop timers in `cleanup()`, and never block
the Qt event loop.
- **Tests**: `python -m pytest --random-order tests/unit_tests/`. Build widgets with
`create_widget(qtbot, WidgetClass, ...)` from `tests/unit_tests/conftest.py` so `qtbot` owns teardown;
reuse `FakeDevice`/`FakePositioner`/`DMMock` from `bec_widgets/tests/utils.py`. Headless runs need
`QT_QPA_PLATFORM=offscreen`.
- **Format before finishing**: `black --line-length=100 --skip-magic-trailing-comma .` and
`isort --line-length=100 --profile=black --multi-line=3 --trailing-comma .`.
- **Beamline-specific widgets belong in a plugin repo**, discovered via the `bec.widgets.user_widgets`
entry-point group — not in this repository.
- **Do not commit or push unless explicitly asked, and never open a pull request.** If you do commit,
write a single Conventional Commits line — it is parsed into the published changelog. Opening the PR
is the human's step; leave them the summary, test output, and a screenshot or GIF of any visible GUI
change.
All guidelines are imported from [`AGENTS.md`](AGENTS.md), the single source of truth — start with
its Core Rules and honor the `AGENTS_PERSONAL.md` local overlay if present. Nothing here overrides it.