attributes: getter/setter IO rework, remove AttributeIORef/AttributeIO#412
attributes: getter/setter IO rework, remove AttributeIORef/AttributeIO#412coretl wants to merge 2 commits into
Conversation
Per-attribute IO moves from a shared, ref-dispatched AttributeIO/ AttributeIORef pair onto plain getter/setter callables passed straight to AttrR/AttrW/AttrRW. Datatype is now optional on the constructors when it can be inferred from the getter/setter annotation. Runtime surface rename: get() -> .readback / .setpoint properties, no-arg update() -> poll() (does the getter read + caches + returns), update(value) stays as a pure cache-push (now also accepting Update[T]), put() -> set() (caches .setpoint, runs the setter, a non-None return updates .readback - the replacement for the old sync_setpoint-callback mechanism). Scheduling in Controller.create_api_and_tasks now polls getter-bearing attrs directly instead of going through an IO update-callback indirection. Removed: AttributeIO, AttributeIORef, ios=, _connect_attribute_ios, _validate_io, the second Attribute/AttrR/AttrW/AttrRW TypeVar. Migrates the demo composition example and all docs snippets that used the old io_ref= wiring. Deliberately out of scope for this PR (left for a follow-up): the DataType family / *Meta TypedDict replacement and the associated precision/Limits naming pass - the issue's own sizing note allows splitting the getter/setter half from the DataType-removal half. Closes #392
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## refactor #412 +/- ##
============================================
- Coverage 91.25% 91.06% -0.19%
============================================
Files 72 72
Lines 2892 2900 +8
============================================
+ Hits 2639 2641 +2
- Misses 253 259 +6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The docs build failed CI (fail-on-warning) because docs/tutorials/static-drivers.md's
literalinclude emphasize-lines directives pointed at line numbers that no longer existed
after the snippet rewrite. Fixing that surfaced the deeper issue: several tutorial and
how-to pages narrated the removed AttributeIO/AttributeIORef pattern in prose, with code
examples that no longer import.
- Rewrite docs/tutorials/static-drivers.md and dynamic-drivers.md prose + literalinclude
line references to match the getter/setter snippets.
- Give docs/snippets/static15.py's TemperatureProtocol a Tracer base and thread `topic`
through send_query, so the tutorial's per-attribute tracing walkthrough (enable_tracing
on one attribute, see only its queries) still holds - a plain logger.trace call
wouldn't respect per-attribute enable_tracing() at all.
- Rewrite docs/how-to/update-attributes-from-device.md's four patterns (poll via getter,
event-driven updates from a set, batched scan updates, scan-as-cache) for getter/setter.
- Fix remaining AttributeIO/.get()/.put()/update_period mentions in
docs/explanations/{transports,controllers,what-is-fastcs,datatypes}.md and
docs/how-to/{table-waveform-data,wait-methods}.md.
Closes #392
Implements the getter/setter half of #392 (ADR 0014's
AttributeIO/AttributeIORefremoval), scoped per the issue's own "Note on size": theDataType/*MetaTypedDict replacement and the precision/Limitsnaming pass (ADR 0017) are left for a follow-up PR rather than risking an incoherent halfway state in one session — see "Notes" below.Scope
getter/settercallables passed straight toAttrR(getter=...)/AttrW(setter=...)/AttrRW(getter=..., setter=...). Access mode is enforced structurally by which ofgetter/setterare present - there's no moreio=/AttributeIOclass hierarchy orAttributeIORef-keyed dispatch registry.AttrR(getter=get_value)whereget_value() -> float); not inferable ⇒ positional datatype still required, fails fast at construction.Update[T]dataclass (value,timestamp) a getter/setter may return/accept instead of a bare value -update()/poll()unwrap it. (Native persistence of the timestamp, and aseverityfield, are left to AttrW setpoint cache, native timestamps + severity, ControllerRunner #395, which explicitly owns that.)get()→.readback/.setpointread-only properties (AttrRhasreadback,AttrWhassetpoint,AttrRWhas both); no-argupdate()→poll()(does the getter read, caches, returns the value);update(value)stays as a pure cache-push (now also acceptingUpdate[T]);put(value[, sync_setpoint])→set(value)(caches.setpoint, runs the setter; a non-Nonesetter return updates.readbacktoo - the sanctioned replacement for the old private_call_sync_setpoint_callbacks/sync_setpoint=mechanism).AttributeIO,AttributeIORef,ios=,_connect_attribute_ios,_validate_io,_attribute_ref_io_map,set_update_callback/bind_update_callback/set_on_put_callback/_call_sync_setpoint_callbacks/add_sync_setpoint_callback, and the secondAttribute/AttrR/AttrW/AttrRWTypeVar (Attribute[DType_T, AttributeIORefT]→Attribute[DType_T]).Controller.create_api_and_tasksnow schedules polling directly off getter-bearing attributes (poll_period, defaulting toONCEwhen a getter is given) instead of pattern-matching anAttributeIORef.src/fastcs/demo/controllers.py), everydocs/snippets/*.pytutorial snippet that usedio_ref=, and all the tests that constructed attributes the old way (tests/assertable_controller.py,tests/test_attributes.py,tests/test_control_system.py,tests/conftest.py,tests/example_p4p_ioc.py, and the transport test files that built attributes directly)..datatype/DataTypethemselves are untouched in this PR (see Notes).Notes
DataTypefamily → python type +*MetaTypedDict replacement and theprecision/nested-Limitsnaming pass (ADR 0017). The issue's own "Note on size" calls out this split explicitly.attr.datatype/Float/Int/etc. are unchanged.uv run --locked tox -e pre-commit,type-checking, both green in full. For thetestsenv, this sandbox can't rundocs(needs outbound network todiamondlightsource.github.io) or the PVA/p4p-backed tests (RuntimeError: Address family not supported by protocol- no PVA-capable socket family here), the same known limitation noted on prior PRs (demo: use ControllerVector for temperature ramp sub-controllers #409/demo: cut-down Eiger REST sim + introspectable controller example #410/demo: getter/setter-in-init temperature attr example #411) in this epic. Excluding those two paths,pytest src tests --ignore=tests/benchmarkingpasses 314/324, with only the same 10 pre-existing PVA (p4p)/socket-family failures, unrelated to this change. Real CI coversdocsand PVA.tickittemperature-controller simulator (docs/snippets/*.py'stest_docs_snippets.pyalready exercises this - all 16 snippets pass) and confirmedTemperatureController/TemperatureRampControllerconstruct and wire up correctly with the new getter/setter API.Generated by Claude Code