Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds 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
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
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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 |
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (1)
docs/images/attribute-dataflow.excalidraw.pngis excluded by!**/*.png
📒 Files selected for processing (30)
docs/explanations/datatypes.mddocs/explanations/transports.mddocs/how-to/arrange-epics-screens.mddocs/how-to/launch-framework.mddocs/how-to/multiple-transports.mddocs/how-to/table-waveform-data.mddocs/how-to/test-logging.mddocs/how-to/wait-methods.mdsrc/fastcs/attributes/attr_w.pysrc/fastcs/attributes/attribute_io.pysrc/fastcs/attributes/attribute_io_ref.pysrc/fastcs/control_system.pysrc/fastcs/controllers/controller_api.pysrc/fastcs/datatypes/_numeric.pysrc/fastcs/datatypes/datatype.pysrc/fastcs/datatypes/float.pysrc/fastcs/datatypes/table.pysrc/fastcs/datatypes/waveform.pysrc/fastcs/logging/__init__.pysrc/fastcs/logging/_graylog.pysrc/fastcs/logging/_logging.pysrc/fastcs/methods/command.pysrc/fastcs/methods/scan.pysrc/fastcs/tracer.pysrc/fastcs/transports/controller_api.pysrc/fastcs/transports/epics/ca/transport.pysrc/fastcs/transports/epics/pva/transport.pysrc/fastcs/transports/transport.pytests/conftest.pytests/test_attribute_logging.py
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (1)
docs/images/attribute-dataflow.excalidraw.pngis excluded by!**/*.png
📒 Files selected for processing (29)
docs/explanations/datatypes.mddocs/explanations/transports.mddocs/how-to/arrange-epics-screens.mddocs/how-to/launch-framework.mddocs/how-to/multiple-transports.mddocs/how-to/table-waveform-data.mddocs/how-to/test-logging.mddocs/how-to/wait-methods.mdsrc/fastcs/attributes/attr_w.pysrc/fastcs/attributes/attribute_io.pysrc/fastcs/attributes/attribute_io_ref.pysrc/fastcs/control_system.pysrc/fastcs/controllers/controller_api.pysrc/fastcs/datatypes/_numeric.pysrc/fastcs/datatypes/datatype.pysrc/fastcs/datatypes/float.pysrc/fastcs/datatypes/table.pysrc/fastcs/datatypes/waveform.pysrc/fastcs/logging/__init__.pysrc/fastcs/logging/_graylog.pysrc/fastcs/logging/_logging.pysrc/fastcs/methods/command.pysrc/fastcs/methods/scan.pysrc/fastcs/tracer.pysrc/fastcs/transports/epics/ca/transport.pysrc/fastcs/transports/epics/pva/transport.pysrc/fastcs/transports/transport.pytests/conftest.pytests/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
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
tests/test_attribute_logging.py (1)
45-46:⚠️ Potential issue | 🟡 MinorRename the unused callback parameter to keep Ruff green.
This callback needs a single positional argument, but the test never reads it. Renaming it to
_valuekeeps the signature and fixesARG001.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 ifupdate()starts wrapping callback failures in a differentRuntimeError. 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
⛔ Files ignored due to path filters (1)
docs/images/attribute-dataflow.excalidraw.pngis excluded by!**/*.png
📒 Files selected for processing (10)
docs/explanations/datatypes.mddocs/explanations/transports.mddocs/how-to/arrange-epics-screens.mddocs/how-to/launch-framework.mddocs/how-to/multiple-transports.mddocs/how-to/table-waveform-data.mddocs/how-to/test-logging.mddocs/how-to/wait-methods.mdtests/conftest.pytests/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
There was a problem hiding this comment.
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 aDeprecationWarningin Python 3.10+ and may raiseRuntimeErrorin future versions. If users store a reference to the loop or useasyncio.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
📒 Files selected for processing (9)
docs/how-to/arrange-epics-screens.mddocs/how-to/launch-framework.mddocs/how-to/multiple-transports.mddocs/how-to/table-waveform-data.mddocs/how-to/test-logging.mddocs/how-to/update-attributes-from-device.mddocs/how-to/wait-methods.mdtests/conftest.pytests/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
There was a problem hiding this comment.
🧹 Nitpick comments (2)
docs/how-to/update-attributes-from-device.md (1)
276-283: Consider usingasyncio.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 useasyncio.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_loggerexport 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
⛔ Files ignored due to path filters (1)
docs/images/attribute-dataflow.excalidraw.pngis excluded by!**/*.png
📒 Files selected for processing (30)
docs/explanations/datatypes.mddocs/explanations/transports.mddocs/how-to/arrange-epics-screens.mddocs/how-to/launch-framework.mddocs/how-to/multiple-transports.mddocs/how-to/table-waveform-data.mddocs/how-to/test-logging.mddocs/how-to/update-attributes-from-device.mddocs/how-to/wait-methods.mdsrc/fastcs/attributes/attr_w.pysrc/fastcs/attributes/attribute_io.pysrc/fastcs/attributes/attribute_io_ref.pysrc/fastcs/control_system.pysrc/fastcs/controllers/controller_api.pysrc/fastcs/datatypes/_numeric.pysrc/fastcs/datatypes/datatype.pysrc/fastcs/datatypes/float.pysrc/fastcs/datatypes/table.pysrc/fastcs/datatypes/waveform.pysrc/fastcs/logging/__init__.pysrc/fastcs/logging/_graylog.pysrc/fastcs/logging/_logging.pysrc/fastcs/methods/command.pysrc/fastcs/methods/scan.pysrc/fastcs/tracer.pysrc/fastcs/transports/epics/ca/transport.pysrc/fastcs/transports/epics/pva/transport.pysrc/fastcs/transports/transport.pytests/conftest.pytests/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
Summary by CodeRabbit