From 2312d037facc3629a94b0720cf3a482102afc3e1 Mon Sep 17 00:00:00 2001 From: Rick Wierenga Date: Wed, 11 Nov 2026 14:26:14 -0800 Subject: [PATCH] docs: require restoring device state after lifecycles and commands --- docs/contributor_guide/device-driver-guide.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/contributor_guide/device-driver-guide.md b/docs/contributor_guide/device-driver-guide.md index 5f425bf2cdc..362526dcc8b 100644 --- a/docs/contributor_guide/device-driver-guide.md +++ b/docs/contributor_guide/device-driver-guide.md @@ -20,6 +20,7 @@ Keep it small and idiomatic to PyLabRobot. - **Stay OS-agnostic:** no OS-specific libraries or DLLs. Running on Windows, Mac, and Linux is what keeps experiments portable and reproducible. - **Use `pylabrobot.io` for all device communication.** Use the appropriate PyLabRobot transport (`USB`, `Serial`, `FTDI`, `HID`, `Socket`, etc.) instead of calling PyUSB, pyserial, hidapi, raw sockets, vendor DLLs, or OS APIs directly from a device driver. If a required transport capability is missing, add it to `pylabrobot.io` rather than bypassing the abstraction. - **Async `setup()` / `stop()`** plus public operation methods over those `pylabrobot.io` transport primitives. +- **Leave the device in the state you found it at each lifecycle boundary.** Restore changes made for a `setup()` / `stop()` lifecycle in `stop()`, and restore per-command changes before the command finishes. If the driver needs to modify device memory, registers, or configuration, read and save the original values first and restore those exact values at the end of the relevant scope, not assumed defaults. Ensure cleanup also runs on errors and cancellation, including partial setup failures. - **Log important device events.** Define a module logger with `logger = logging.getLogger(__name__)` and use it for meaningful lifecycle events, operations, state changes, recoveries, and faults. Use the appropriate log level and structured `%`-style arguments; don't use `print()` for runtime status. - **Prefer string `Literal[...]` over enums**, especially anything user-facing. A `Literal["standard", "head", "pump"]` argument plus an internal dict mapping to wire codes reads better at the call site than an enum import. `IntEnum` is fine in narrow internal cases (e.g. a fixed set of wire/register codes never exposed to callers). - **API docs:** add `docs/api/pylabrobot..rst` plus a line in `docs/api/pylabrobot.rst`.