Skip to content

Add some docs#338

Open
GDYendell wants to merge 5 commits intomainfrom
docs
Open

Add some docs#338
GDYendell wants to merge 5 commits intomainfrom
docs

Conversation

@GDYendell
Copy link
Contributor

@GDYendell GDYendell commented Mar 12, 2026

Summary by CodeRabbit

  • Documentation
    • Added comprehensive guides on datatypes, transports, launch framework, multiple transports, waveform/table data, EPICS screen layout, wait methods, updating attributes from devices, and testing logging; improved many core docstrings for clarity and usage guidance.
  • Tests
    • Added a log-capturing fixture and tests covering attribute logging, validation, and update error handling.
  • Bug Fixes
    • Fixed documentation wording and reference inconsistencies.

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds many new user-facing documentation and how‑to guides, broad docstring expansions across datatypes, transports, logging, attributes, and core modules, a new pytest fixture and tests for capturing loguru attribute logging, and small non-functional docstring/inline-string additions in several source files.

Changes

Cohort / File(s) Summary
Explanation Guides
docs/explanations/datatypes.md, docs/explanations/transports.md
New deep-dive explanation pages for the FastCS datatype system and the Transports architecture, covering datatypes, validation/coercion, transport callbacks, ControllerAPI interaction, and implementation guidance.
How‑To Guides
docs/how-to/arrange-epics-screens.md, docs/how-to/launch-framework.md, docs/how-to/multiple-transports.md, docs/how-to/table-waveform-data.md, docs/how-to/test-logging.md, docs/how-to/wait-methods.md, docs/how-to/update-attributes-from-device.md
New practical how‑to documents: EPICS screen layout, launch framework/YAML, running multiple transports, waveform/table data, testing logging with loguru, wait methods, and attribute update patterns (scans, IO, subscriptions).
Docstrings — Datatypes
src/fastcs/datatypes/_numeric.py, src/fastcs/datatypes/datatype.py, src/fastcs/datatypes/float.py, src/fastcs/datatypes/table.py, src/fastcs/datatypes/waveform.py
Added/expanded inline docstrings for dataclass fields and abstract properties (units, min/max, alarms, dtype, initial_value, prec, structured_dtype, array_dtype, shape). No behavior changes.
Docstrings — Attributes
src/fastcs/attributes/attr_w.py, src/fastcs/attributes/attribute_io.py, src/fastcs/attributes/attribute_io_ref.py
Clarified AttrW.put wording; added detailed docs for AttributeIO.update and AttributeIO.send (invocation context, exception handling); documented update_period description.
Docstrings — Logging
src/fastcs/logging/__init__.py, src/fastcs/logging/_graylog.py, src/fastcs/logging/_logging.py
Converted param sections to Args style, added field docstrings for GraylogEndpoint and LogLevel, and added an __all__ export block.
Docstrings — Core Modules
src/fastcs/control_system.py, src/fastcs/controllers/controller_api.py, src/fastcs/tracer.py
Expanded docstrings for ControlSystem.run/serve, described ControllerAPI fields and immutability for transport view, and updated tracer docs/parameter descriptions.
Docstrings — Transports & Methods
src/fastcs/methods/command.py, src/fastcs/methods/scan.py, src/fastcs/transports/transport.py, src/fastcs/transports/epics/ca/transport.py, src/fastcs/transports/epics/pva/transport.py
Added/clarified docstrings for Transport interface methods, CA/PVA serve/context docs (CA context excludes exit), and Scan/command decorator parameter docs.
Tests & Fixtures
tests/conftest.py, tests/test_attribute_logging.py
Added loguru_caplog pytest fixture to bridge loguru into pytest capture and new tests for attribute logging behavior (trace logs, validation errors, callback failures).

Sequence Diagram(s)

(Skipped — changes are documentation, docstring additions, and tests; no new multi-component control flow introduced.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through docs both wide and deep,
I nudged the docstrings from their sleep,
Tests now listen to loguru's song,
Guides and how‑tos bundled long,
A rabbit cheers — the code feels neat!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.94% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Add some docs' is vague and does not convey specific information about the primary changes in the changeset. Replace the vague title with a more specific summary of the main documentation additions, such as 'Add comprehensive documentation for datatypes, transports, and usage patterns' or similar.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch docs
📝 Coding Plan
  • Generate coding plan for human review comments

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/explanations/datatypes.md`:
- Around line 36-38: The description of the String datatype is misleading about
String.length; update the wording for the String type to state that the optional
length field is only a transport/display hint (used by some transports to
truncate output) and does not enforce or validate value length at the datatype
level. Mention the exact symbol String.length and clarify that it does not
participate in validation and that consumers should use explicit validation
(e.g., schema or validators) when they require guaranteed enforcement of length.

In `@docs/explanations/transports.md`:
- Around line 63-75: The example iterates controller_api.commands but
ControllerAPI exposes command_methods; update the loop that currently reads "for
name, command in controller_api.commands.items()" to iterate over
controller_api.command_methods (preserving usage of
protocol.create_command(name, command)); ensure any surrounding context
referencing controller_api.commands is replaced with
controller_api.command_methods so create_command is called with the actual
command objects returned by ControllerAPI.command_methods when walking the API
via controller_api.walk_api().
- Around line 18-56: The example is not runnable because it imports
ControllerAPI from fastcs.transports.controller_api and uses Any without
importing it; update the imports so ControllerAPI comes from the correct public
module (e.g., fastcs.controller_api) and add "from typing import Any" (or
appropriate typing import) at the top, then ensure the MyTransport class
(connect, serve, context) references those corrected imports so the example can
be copy-pasted and executed.

In `@docs/how-to/launch-framework.md`:
- Around line 27-30: The docs currently present using a dataclass or Pydantic
model for controller config as a strict requirement, but launch() only validates
the __init__ signature and that a config parameter is type-hinted (it does not
reject other hinted types); update the "Adding Configuration Options" section
(and the later similar section) to change wording from mandatory to
recommended—state that dataclasses/Pydantic are recommended for clarity and
validation, then accurately describe launch() behavior: it checks __init__ shape
and presence of a type hint for the config parameter but does not enforce a
specific type, and provide a short note suggesting how to use other types if
desired.

In `@docs/how-to/table-waveform-data.md`:
- Around line 101-120: The example uses the wrong attribute name—replace the
update call to use the table attribute defined earlier (results) instead of
controller.channel_data; locate the example where the numpy structured array is
created and change the update invocation to await
controller.results.update(data) so it matches the earlier table definition and
avoids referencing a nonexistent attribute.
- Around line 46-50: The example uses the decorator scan but never imports it,
causing a copy-paste failure; add an import for scan (e.g., from fastcs.methods
import scan) at the top of the snippet so the `@scan`(period=0.1) decorator on
SpectrumController works; update the doc example that defines
SpectrumController, Controller, AttrR and Waveform to include that import.

In `@src/fastcs/attributes/attribute_io.py`:
- Around line 34-43: The docstring for the AttrR update method contains typos
and formatting issues; edit the string in attribute_io.py (the docstring used by
AttrR.update) to remove the doubled space after "Update", change "targetted" to
"targeted", remove the stray "ff", and fix the trailing double period so it ends
"handled by FastCS."; apply the same cleanups to the second similar docstring
block (the one covering lines 47-56) so both docstrings are consistent and free
of typographical errors.

In `@src/fastcs/controllers/controller_api.py`:
- Around line 10-28: The class-level docstring for ControllerAPI overstates
immutability — ControllerAPI currently exposes mutable list/dict fields (path,
attributes, command_methods, scan_methods, sub_apis). Fix by either: (A)
weakening the docstring to say "immutable view" -> "snapshot/readonly view" or
"provides an external API surface (not a deep immutable guarantee)", or (B) make
the object effectively immutable by converting mutable fields into
immutable/read-only types (e.g. store path as a tuple, wrap dicts with
types.MappingProxyType or similar, and/or mark the dataclass frozen and perform
wrapping in __post_init__). Update the docstring or implement the conversion in
ControllerAPI so callers cannot mutate path, attributes, command_methods,
scan_methods, or sub_apis directly.

In `@src/fastcs/logging/__init__.py`:
- Around line 109-116: The __all__ list exports bind_logger but this module
doesn't define or import it; either add a real bind_logger function (e.g., a
thin wrapper that calls logger.bind and mirrors its signature) or remove
bind_logger from __all__; after the change, re-sort the __all__ entries
alphabetically to satisfy Ruff and ensure the public exports (logger,
configure_logging, GraylogEndpoint, intercept_std_logger, etc.) match actual
symbols in the module.

In `@src/fastcs/methods/scan.py`:
- Around line 21-25: The docstring for the Scan method mentions ONCE but doesn't
tell readers where to find it; update the docstrings (both occurrences) to make
ONCE discoverable by either: (a) qualifying it with the module that defines it
(e.g., "ONCE (from fastcs.constants)" or similar), or (b) importing and exposing
ONCE in this module and adding a short cross-reference like "See
fastcs.<module>.ONCE" so API docs show where to import ONCE; adjust the top of
the file to import/export ONCE if you choose option (b) and ensure the first
mention of ONCE includes the qualification.

In `@src/fastcs/transports/controller_api.py`:
- Around line 16-68: The patch introduced a transport-local ControllerAPI
dataclass and duplicate scan/attribute task collection logic, which diverges
from the canonical fastcs.controllers.ControllerAPI used by
BaseController._build_api() and consumed by Transport.connect(); to fix this,
remove the forked dataclass or merge it by moving get_scan_and_initial_coros
(and its helpers _add_scan_method_tasks, _add_attribute_update_tasks,
_get_periodic_scan_coros) onto the existing fastcs.controllers.ControllerAPI API
surface, or alternatively implement those helpers as standalone functions that
accept the original ControllerAPI type and update call-sites
(Transport.connect(), BaseController._build_api(),
Controller.create_api_and_tasks()) to use the single shared implementation so
there is only one source of truth for creating scan_coros and initial_coros.

In `@tests/test_attribute_logging.py`:
- Around line 45-46: The test coroutine failing_callback currently defines an
unused parameter named value which triggers Ruff ARG001; rename the parameter to
_value (i.e., change async def failing_callback(value: int): to async def
failing_callback(_value: int):) so the unused-argument lint is satisfied while
preserving the required single-argument signature.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6851914c-c283-4e63-822d-a4ebc4109bf7

📥 Commits

Reviewing files that changed from the base of the PR and between afcbf45 and a447131.

⛔ Files ignored due to path filters (1)
  • docs/images/attribute-dataflow.excalidraw.png is excluded by !**/*.png
📒 Files selected for processing (30)
  • docs/explanations/datatypes.md
  • docs/explanations/transports.md
  • docs/how-to/arrange-epics-screens.md
  • docs/how-to/launch-framework.md
  • docs/how-to/multiple-transports.md
  • docs/how-to/table-waveform-data.md
  • docs/how-to/test-logging.md
  • docs/how-to/wait-methods.md
  • src/fastcs/attributes/attr_w.py
  • src/fastcs/attributes/attribute_io.py
  • src/fastcs/attributes/attribute_io_ref.py
  • src/fastcs/control_system.py
  • src/fastcs/controllers/controller_api.py
  • src/fastcs/datatypes/_numeric.py
  • src/fastcs/datatypes/datatype.py
  • src/fastcs/datatypes/float.py
  • src/fastcs/datatypes/table.py
  • src/fastcs/datatypes/waveform.py
  • src/fastcs/logging/__init__.py
  • src/fastcs/logging/_graylog.py
  • src/fastcs/logging/_logging.py
  • src/fastcs/methods/command.py
  • src/fastcs/methods/scan.py
  • src/fastcs/tracer.py
  • src/fastcs/transports/controller_api.py
  • src/fastcs/transports/epics/ca/transport.py
  • src/fastcs/transports/epics/pva/transport.py
  • src/fastcs/transports/transport.py
  • tests/conftest.py
  • tests/test_attribute_logging.py

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/how-to/multiple-transports.md`:
- Around line 131-151: The example uses Path(".") but does not import it,
causing NameError; fix by adding the missing import for Path (from pathlib
import Path) at the top of the snippet so the example using FastCS,
EpicsCATransport, EpicsGUIOptions, EpicsIOCOptions, and EpicsPVATransport can
run as-is.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a93aa2fb-14ab-49ef-8bd6-b01bd9120b31

📥 Commits

Reviewing files that changed from the base of the PR and between a447131 and e4876e0.

⛔ Files ignored due to path filters (1)
  • docs/images/attribute-dataflow.excalidraw.png is excluded by !**/*.png
📒 Files selected for processing (29)
  • docs/explanations/datatypes.md
  • docs/explanations/transports.md
  • docs/how-to/arrange-epics-screens.md
  • docs/how-to/launch-framework.md
  • docs/how-to/multiple-transports.md
  • docs/how-to/table-waveform-data.md
  • docs/how-to/test-logging.md
  • docs/how-to/wait-methods.md
  • src/fastcs/attributes/attr_w.py
  • src/fastcs/attributes/attribute_io.py
  • src/fastcs/attributes/attribute_io_ref.py
  • src/fastcs/control_system.py
  • src/fastcs/controllers/controller_api.py
  • src/fastcs/datatypes/_numeric.py
  • src/fastcs/datatypes/datatype.py
  • src/fastcs/datatypes/float.py
  • src/fastcs/datatypes/table.py
  • src/fastcs/datatypes/waveform.py
  • src/fastcs/logging/__init__.py
  • src/fastcs/logging/_graylog.py
  • src/fastcs/logging/_logging.py
  • src/fastcs/methods/command.py
  • src/fastcs/methods/scan.py
  • src/fastcs/tracer.py
  • src/fastcs/transports/epics/ca/transport.py
  • src/fastcs/transports/epics/pva/transport.py
  • src/fastcs/transports/transport.py
  • tests/conftest.py
  • tests/test_attribute_logging.py
✅ Files skipped from review due to trivial changes (4)
  • docs/how-to/test-logging.md
  • docs/explanations/datatypes.md
  • src/fastcs/datatypes/float.py
  • docs/how-to/arrange-epics-screens.md
🚧 Files skipped from review as they are similar to previous changes (15)
  • src/fastcs/datatypes/table.py
  • src/fastcs/attributes/attribute_io_ref.py
  • src/fastcs/transports/transport.py
  • src/fastcs/methods/command.py
  • src/fastcs/logging/_logging.py
  • docs/explanations/transports.md
  • src/fastcs/datatypes/datatype.py
  • src/fastcs/control_system.py
  • src/fastcs/tracer.py
  • src/fastcs/attributes/attr_w.py
  • docs/how-to/table-waveform-data.md
  • src/fastcs/datatypes/_numeric.py
  • src/fastcs/datatypes/waveform.py
  • src/fastcs/logging/_graylog.py
  • docs/how-to/wait-methods.md

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
tests/test_attribute_logging.py (1)

45-46: ⚠️ Potential issue | 🟡 Minor

Rename the unused callback parameter to keep Ruff green.

This callback needs a single positional argument, but the test never reads it. Renaming it to _value keeps the signature and fixes ARG001.

Proposed fix
-    async def failing_callback(value: int):
+    async def failing_callback(_value: int):
         raise RuntimeError("callback failed")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_attribute_logging.py` around lines 45 - 46, The test defines async
def failing_callback(value: int) but never uses the parameter, triggering
ARG001; rename the parameter to _value (i.e., async def failing_callback(_value:
int):) to preserve the required single positional argument while marking it as
intentionally unused; update any references (there are none) and run the
tests/linter to confirm the warning is gone.
🧹 Nitpick comments (1)
tests/test_attribute_logging.py (1)

50-51: Assert the callback message so this test proves the original error is re-raised.

pytest.raises(RuntimeError) will also pass if update() starts wrapping callback failures in a different RuntimeError. Matching the message makes the contract explicit.

Proposed fix
-    with pytest.raises(RuntimeError):
+    with pytest.raises(RuntimeError, match="callback failed"):
         await attr.update(42)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_attribute_logging.py` around lines 50 - 51, Capture the raised
exception from await attr.update(42) using pytest.raises(...) as excinfo and
assert that excinfo.value contains the original callback error message (compare
str(excinfo.value) or excinfo.value.args[0] to the expected callback error
string used in the test) so the test explicitly verifies the original
RuntimeError message is re-raised by attr.update.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/explanations/datatypes.md`:
- Around line 72-76: Remove the invalid dict-based example using Enum({...}) and
replace it with a supported pattern: explain that fastcs.datatypes.Enum expects
an enum.Enum subclass (referencing fastcs.datatypes.Enum and the enum.py
issubclass check) and show how to define a proper enum (e.g., a subclass named
DetectorStatus with members like RUN_FINISHED = "RUN_FINISHED" and IN_PROGRESS =
"IN_PROGRESS") and then document separately how to map UI labels with spaces to
those enum members (or mention the UI-label mechanism) so readers do not copy
the unsupported dict pattern.

---

Duplicate comments:
In `@tests/test_attribute_logging.py`:
- Around line 45-46: The test defines async def failing_callback(value: int) but
never uses the parameter, triggering ARG001; rename the parameter to _value
(i.e., async def failing_callback(_value: int):) to preserve the required single
positional argument while marking it as intentionally unused; update any
references (there are none) and run the tests/linter to confirm the warning is
gone.

---

Nitpick comments:
In `@tests/test_attribute_logging.py`:
- Around line 50-51: Capture the raised exception from await attr.update(42)
using pytest.raises(...) as excinfo and assert that excinfo.value contains the
original callback error message (compare str(excinfo.value) or
excinfo.value.args[0] to the expected callback error string used in the test) so
the test explicitly verifies the original RuntimeError message is re-raised by
attr.update.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 47194623-0e05-4fde-b13a-ee819cae3bf8

📥 Commits

Reviewing files that changed from the base of the PR and between e4876e0 and 71a3c1f.

⛔ Files ignored due to path filters (1)
  • docs/images/attribute-dataflow.excalidraw.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • docs/explanations/datatypes.md
  • docs/explanations/transports.md
  • docs/how-to/arrange-epics-screens.md
  • docs/how-to/launch-framework.md
  • docs/how-to/multiple-transports.md
  • docs/how-to/table-waveform-data.md
  • docs/how-to/test-logging.md
  • docs/how-to/wait-methods.md
  • tests/conftest.py
  • tests/test_attribute_logging.py
✅ Files skipped from review due to trivial changes (1)
  • docs/how-to/launch-framework.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • docs/how-to/arrange-epics-screens.md
  • docs/how-to/table-waveform-data.md
  • docs/how-to/wait-methods.md
  • docs/explanations/transports.md
  • docs/how-to/multiple-transports.md

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
docs/how-to/update-attributes-from-device.md (1)

276-282: Consider documenting the modern alternative for threaded callbacks.

asyncio.get_event_loop() called from a non-async context emits a DeprecationWarning in Python 3.10+ and may raise RuntimeError in future versions. If users store a reference to the loop or use asyncio.get_running_loop() from the async context, the pattern becomes more robust.

📝 Alternative pattern
# Store loop reference during async setup
self._loop = asyncio.get_running_loop()

def on_temperature_change_sync(value: float) -> None:
    self._loop.call_soon_threadsafe(
        asyncio.create_task, self.temperature.update(value)
    )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/how-to/update-attributes-from-device.md` around lines 276 - 282, The
snippet uses asyncio.get_event_loop() from a non-async context which is
deprecated; instead capture the running loop during async setup (e.g., assign
asyncio.get_running_loop() to self._loop) and update the threaded callback to
call self._loop.call_soon_threadsafe with asyncio.create_task and the coroutine
self.temperature.update(value); change the callback function name
on_temperature_change_sync accordingly and keep the subscription call
self._client.subscribe("temperature", on_temperature_change_sync) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/how-to/update-attributes-from-device.md`:
- Around line 79-88: Move the "from collections.abc import Awaitable, Callable"
import (and the dataclass KW_ONLY import used by MyDeviceIORef) to the top of
the code block so all imports precede the class definition; ensure MyDeviceIORef
(class name) remains unchanged and that PutResponseCallback (type alias) stays
after the imports and continues to use Callable/Awaitable; optionally
consolidate with other module imports suggested in the comment so imports are
grouped at the top of the snippet.

In `@docs/how-to/wait-methods.md`:
- Around line 87-104: The example in MultiAxisController uses Float and AttrR
types but the snippet only imports asyncio and command; update the imports to
include Float and AttrR (and any typing generics used) so symbols like Float(),
AttrR, and AttrR[float] resolve; ensure the top of the example imports these
from fastcs.methods or the correct module where Float and AttrR are defined so
move_all_and_wait's calls to self.x_position.wait_for_value(...) compile.

---

Nitpick comments:
In `@docs/how-to/update-attributes-from-device.md`:
- Around line 276-282: The snippet uses asyncio.get_event_loop() from a
non-async context which is deprecated; instead capture the running loop during
async setup (e.g., assign asyncio.get_running_loop() to self._loop) and update
the threaded callback to call self._loop.call_soon_threadsafe with
asyncio.create_task and the coroutine self.temperature.update(value); change the
callback function name on_temperature_change_sync accordingly and keep the
subscription call self._client.subscribe("temperature",
on_temperature_change_sync) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 71281acc-e39b-4523-a64e-5cd7230df3fd

📥 Commits

Reviewing files that changed from the base of the PR and between 71a3c1f and 8aff9ee.

📒 Files selected for processing (9)
  • docs/how-to/arrange-epics-screens.md
  • docs/how-to/launch-framework.md
  • docs/how-to/multiple-transports.md
  • docs/how-to/table-waveform-data.md
  • docs/how-to/test-logging.md
  • docs/how-to/update-attributes-from-device.md
  • docs/how-to/wait-methods.md
  • tests/conftest.py
  • tests/test_attribute_logging.py
✅ Files skipped from review due to trivial changes (2)
  • docs/how-to/test-logging.md
  • docs/how-to/launch-framework.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • docs/how-to/table-waveform-data.md
  • docs/how-to/multiple-transports.md
  • tests/test_attribute_logging.py

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
docs/how-to/update-attributes-from-device.md (1)

276-283: Consider using asyncio.get_running_loop() in the sync callback example.

asyncio.get_event_loop() is deprecated when called from a coroutine context in Python 3.10+. While this works for the specific use case (sync callback from another thread), consider updating to use asyncio.get_running_loop() or passing the loop explicitly for clarity.

Suggested alternative
 def on_temperature_change_sync(value: float) -> None:
-    asyncio.get_event_loop().call_soon_threadsafe(
+    asyncio.get_running_loop().call_soon_threadsafe(
         asyncio.ensure_future, self.temperature.update(value)
     )

Or capture the loop at registration time:

loop = asyncio.get_running_loop()

def on_temperature_change_sync(value: float) -> None:
    loop.call_soon_threadsafe(
        asyncio.ensure_future, self.temperature.update(value)
    )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/how-to/update-attributes-from-device.md` around lines 276 - 283, The
example uses asyncio.get_event_loop() inside the sync callback
on_temperature_change_sync which is deprecated in coroutine contexts; capture
the running loop at registration time using asyncio.get_running_loop() (or
accept a loop param) and call loop.call_soon_threadsafe(asyncio.ensure_future,
self.temperature.update(value)) instead; update the example around
on_temperature_change_sync, the loop capture, and the subscribe call to
reference the captured loop so the code no longer relies on
asyncio.get_event_loop().
src/fastcs/logging/__init__.py (1)

109-115: Consider sorting __all__ alphabetically.

The previous issue with the non-existent bind_logger export has been resolved—all symbols now exist in the module. However, Ruff flags that __all__ is not sorted (RUF022).

♻️ Proposed fix to sort alphabetically
 # For sphinx autodoc to find things import from private modules
 __all__ = [
+    "GraylogEndpoint",
+    "configure_logging",
+    "intercept_std_logger",
     "logger",
-    "configure_logging",
-    "intercept_std_logger",
-    "GraylogEndpoint",
 ]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/fastcs/logging/__init__.py` around lines 109 - 115, The __all__ export
list is not alphabetically sorted, which triggers Ruff RUF022; reorder the
strings in the __all__ list so they are in alphabetical order (e.g.,
"configure_logging", "GraylogEndpoint", "intercept_std_logger", "logger") to
satisfy the linter and keep exports predictable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/how-to/update-attributes-from-device.md`:
- Around line 276-283: The example uses asyncio.get_event_loop() inside the sync
callback on_temperature_change_sync which is deprecated in coroutine contexts;
capture the running loop at registration time using asyncio.get_running_loop()
(or accept a loop param) and call
loop.call_soon_threadsafe(asyncio.ensure_future, self.temperature.update(value))
instead; update the example around on_temperature_change_sync, the loop capture,
and the subscribe call to reference the captured loop so the code no longer
relies on asyncio.get_event_loop().

In `@src/fastcs/logging/__init__.py`:
- Around line 109-115: The __all__ export list is not alphabetically sorted,
which triggers Ruff RUF022; reorder the strings in the __all__ list so they are
in alphabetical order (e.g., "configure_logging", "GraylogEndpoint",
"intercept_std_logger", "logger") to satisfy the linter and keep exports
predictable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d00ca3cf-b84c-42b6-88fc-326445a778db

📥 Commits

Reviewing files that changed from the base of the PR and between 8aff9ee and 5f7467c.

⛔ Files ignored due to path filters (1)
  • docs/images/attribute-dataflow.excalidraw.png is excluded by !**/*.png
📒 Files selected for processing (30)
  • docs/explanations/datatypes.md
  • docs/explanations/transports.md
  • docs/how-to/arrange-epics-screens.md
  • docs/how-to/launch-framework.md
  • docs/how-to/multiple-transports.md
  • docs/how-to/table-waveform-data.md
  • docs/how-to/test-logging.md
  • docs/how-to/update-attributes-from-device.md
  • docs/how-to/wait-methods.md
  • src/fastcs/attributes/attr_w.py
  • src/fastcs/attributes/attribute_io.py
  • src/fastcs/attributes/attribute_io_ref.py
  • src/fastcs/control_system.py
  • src/fastcs/controllers/controller_api.py
  • src/fastcs/datatypes/_numeric.py
  • src/fastcs/datatypes/datatype.py
  • src/fastcs/datatypes/float.py
  • src/fastcs/datatypes/table.py
  • src/fastcs/datatypes/waveform.py
  • src/fastcs/logging/__init__.py
  • src/fastcs/logging/_graylog.py
  • src/fastcs/logging/_logging.py
  • src/fastcs/methods/command.py
  • src/fastcs/methods/scan.py
  • src/fastcs/tracer.py
  • src/fastcs/transports/epics/ca/transport.py
  • src/fastcs/transports/epics/pva/transport.py
  • src/fastcs/transports/transport.py
  • tests/conftest.py
  • tests/test_attribute_logging.py
✅ Files skipped from review due to trivial changes (3)
  • src/fastcs/datatypes/_numeric.py
  • src/fastcs/methods/scan.py
  • src/fastcs/methods/command.py
🚧 Files skipped from review as they are similar to previous changes (15)
  • docs/how-to/test-logging.md
  • docs/how-to/table-waveform-data.md
  • docs/how-to/launch-framework.md
  • docs/how-to/multiple-transports.md
  • src/fastcs/attributes/attribute_io.py
  • src/fastcs/datatypes/waveform.py
  • src/fastcs/logging/_graylog.py
  • docs/explanations/transports.md
  • src/fastcs/transports/transport.py
  • src/fastcs/datatypes/table.py
  • src/fastcs/datatypes/datatype.py
  • src/fastcs/transports/epics/ca/transport.py
  • docs/explanations/datatypes.md
  • src/fastcs/controllers/controller_api.py
  • src/fastcs/transports/epics/pva/transport.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant