From 8bdc49f45bf3c6759b7cecf6c94758aa9d7b4cd2 Mon Sep 17 00:00:00 2001 From: Gary Yendell Date: Mon, 27 Oct 2025 09:34:16 +0000 Subject: [PATCH] Remove Put methods --- src/fastcs/control_system.py | 11 +---------- src/fastcs/controller.py | 4 ++-- src/fastcs/controller_api.py | 20 ++----------------- src/fastcs/cs_methods.py | 35 ---------------------------------- src/fastcs/wrappers.py | 7 ------- tests/assertable_controller.py | 1 - tests/test_cs_methods.py | 35 +--------------------------------- 7 files changed, 6 insertions(+), 107 deletions(-) diff --git a/src/fastcs/control_system.py b/src/fastcs/control_system.py index 673748108..e0d4b0334 100644 --- a/src/fastcs/control_system.py +++ b/src/fastcs/control_system.py @@ -8,7 +8,7 @@ from fastcs.controller import BaseController, Controller from fastcs.controller_api import ControllerAPI -from fastcs.cs_methods import Command, Put, Scan +from fastcs.cs_methods import Command, Scan from fastcs.exceptions import FastCSError from fastcs.logging import logger as _fastcs_logger from fastcs.tracer import Tracer @@ -46,7 +46,6 @@ def __init__( self._loop.run_until_complete(controller.attribute_initialise()) validate_hinted_attributes(controller) self.controller_api = build_controller_api(controller) - self._link_process_tasks() self._scan_coros, self._initial_coros = ( self.controller_api.get_scan_and_initial_coros() @@ -72,10 +71,6 @@ def run(self): self._loop.add_signal_handler(signal.SIGTERM, serve.cancel) self._loop.run_until_complete(serve) - def _link_process_tasks(self): - for controller_api in self.controller_api.walk_api(): - controller_api.link_put_tasks() - async def _run_initial_coros(self): for coro in self._initial_coros: await coro() @@ -181,13 +176,10 @@ def build_controller_api(controller: Controller) -> ControllerAPI: def _build_controller_api(controller: BaseController, path: list[str]) -> ControllerAPI: scan_methods: dict[str, Scan] = {} - put_methods: dict[str, Put] = {} command_methods: dict[str, Command] = {} for attr_name in dir(controller): attr = getattr(controller, attr_name) match attr: - case Put(enabled=True): - put_methods[attr_name] = attr case Scan(enabled=True): scan_methods[attr_name] = attr case Command(enabled=True): @@ -199,7 +191,6 @@ def _build_controller_api(controller: BaseController, path: list[str]) -> Contro path=path, attributes=controller.attributes, scan_methods=scan_methods, - put_methods=put_methods, command_methods=command_methods, sub_apis={ name: _build_controller_api(sub_controller, path + [name]) diff --git a/src/fastcs/controller.py b/src/fastcs/controller.py index f6e9dc8a2..9d58f9de7 100755 --- a/src/fastcs/controller.py +++ b/src/fastcs/controller.py @@ -100,7 +100,7 @@ class method and a controller instance, so that it can be called from any """ # Lazy import to avoid circular references - from fastcs.cs_methods import UnboundCommand, UnboundPut, UnboundScan + from fastcs.cs_methods import UnboundCommand, UnboundScan # Using a dictionary instead of a set to maintain order. class_dir = {key: None for key in dir(type(self)) if not key.startswith("_")} @@ -117,7 +117,7 @@ class method and a controller instance, so that it can be called from any attr = getattr(self, attr_name, None) if isinstance(attr, Attribute): setattr(self, attr_name, deepcopy(attr)) - elif isinstance(attr, UnboundPut | UnboundScan | UnboundCommand): + elif isinstance(attr, UnboundScan | UnboundCommand): setattr(self, attr_name, attr.bind(self)) def _validate_io(self, ios: Sequence[AttributeIO[T, AttributeIORefT]]): diff --git a/src/fastcs/controller_api.py b/src/fastcs/controller_api.py index 1deb99dd5..1bc3a3023 100644 --- a/src/fastcs/controller_api.py +++ b/src/fastcs/controller_api.py @@ -4,9 +4,8 @@ from dataclasses import dataclass, field from fastcs.attribute_io_ref import AttributeIORef -from fastcs.attributes import ONCE, Attribute, AttrR, AttrW -from fastcs.cs_methods import Command, Put, Scan -from fastcs.exceptions import FastCSError +from fastcs.attributes import ONCE, Attribute, AttrR +from fastcs.cs_methods import Command, Scan from fastcs.logging import logger as _fastcs_logger from fastcs.tracer import Tracer @@ -22,7 +21,6 @@ class ControllerAPI: """Path within controller tree (empty if this is the root)""" attributes: dict[str, Attribute] = field(default_factory=dict) command_methods: dict[str, Command] = field(default_factory=dict) - put_methods: dict[str, Put] = field(default_factory=dict) scan_methods: dict[str, Scan] = field(default_factory=dict) sub_apis: dict[str, "ControllerAPI"] = field(default_factory=dict) """APIs of the sub controllers of the `Controller` this API was built from""" @@ -44,20 +42,6 @@ def __repr__(self): ControllerAPI(path={self.path}, sub_apis=[{", ".join(self.sub_apis.keys())}])\ """ - def link_put_tasks(self) -> None: - for name, method in self.put_methods.items(): - name = name.removeprefix("put_") - - attribute = self.attributes[name] - match attribute: - case AttrW(): - attribute.set_on_put_callback(method.fn) - case _: - raise FastCSError( - f"Attribute type {type(attribute)} does not" - f"support put operations for {name}" - ) - def get_scan_and_initial_coros(self) -> tuple[list[Callable], list[Callable]]: scan_dict: dict[float, list[Callable]] = defaultdict(list) initial_coros: list[Callable] = [] diff --git a/src/fastcs/cs_methods.py b/src/fastcs/cs_methods.py index 96dad990b..05f143934 100644 --- a/src/fastcs/cs_methods.py +++ b/src/fastcs/cs_methods.py @@ -125,22 +125,6 @@ async def __call__(self): return await self._fn() -class Put(Method[BaseController]): - """Why don't know what this is for.""" - - def __init__(self, fn: PutCallback): - super().__init__(fn) - - def _validate(self, fn: PutCallback) -> None: - super()._validate(fn) - - if not len(self.parameters) == 1: - raise FastCSError("Put method can only take one argument") - - async def __call__(self, value: Any): - return await self._fn(value) - - class UnboundCommand(Method[Controller_T]): """A wrapper of an unbound `Controller` method to be bound into a `Command`. @@ -201,22 +185,3 @@ def bind(self, controller: Controller_T) -> Scan: def __call__(self): raise method_not_bound_error - - -class UnboundPut(Method[Controller_T]): - """Unbound version of `Put`.""" - - def __init__(self, fn: UnboundPutCallback[Controller_T]) -> None: - super().__init__(fn) - - def _validate(self, fn: UnboundPutCallback[Controller_T]) -> None: - super()._validate(fn) - - if not len(self.parameters) == 2: - raise FastCSError("Put method can only take one argument") - - def bind(self, controller: Controller_T) -> Put: - return Put(MethodType(self.fn, controller)) - - def __call__(self): - raise method_not_bound_error diff --git a/src/fastcs/wrappers.py b/src/fastcs/wrappers.py index 1f5903715..c86985a01 100644 --- a/src/fastcs/wrappers.py +++ b/src/fastcs/wrappers.py @@ -4,8 +4,6 @@ Controller_T, UnboundCommand, UnboundCommandCallback, - UnboundPut, - UnboundPutCallback, UnboundScan, UnboundScanCallback, ) @@ -26,11 +24,6 @@ def wrapper(fn: UnboundScanCallback[Controller_T]) -> UnboundScan[Controller_T]: return wrapper -def put(fn: UnboundPutCallback[Controller_T]) -> UnboundPut[Controller_T]: - """Sets up a put over the wrapped method.""" - return UnboundPut(fn) - - def command( *, group: str | None = None ) -> Callable[[UnboundCommandCallback[Controller_T]], UnboundCommand[Controller_T]]: diff --git a/tests/assertable_controller.py b/tests/assertable_controller.py index efded9f02..a19aa5248 100644 --- a/tests/assertable_controller.py +++ b/tests/assertable_controller.py @@ -82,7 +82,6 @@ def __init__(self, controller: Controller, mocker: MockerFixture) -> None: # Copy its fields self.attributes = controller_api.attributes self.command_methods = controller_api.command_methods - self.put_methods = controller_api.put_methods self.scan_methods = controller_api.scan_methods self.sub_apis = controller_api.sub_apis diff --git a/tests/test_cs_methods.py b/tests/test_cs_methods.py index 24e139c2a..e3f1ad2ce 100644 --- a/tests/test_cs_methods.py +++ b/tests/test_cs_methods.py @@ -1,15 +1,7 @@ import pytest from fastcs.controller import Controller -from fastcs.cs_methods import ( - Command, - Method, - Put, - Scan, - UnboundCommand, - UnboundPut, - UnboundScan, -) +from fastcs.cs_methods import Command, Method, Scan, UnboundCommand, UnboundScan from fastcs.exceptions import FastCSError @@ -90,28 +82,3 @@ async def update_nothing_with_arg(self, arg): assert scan.period == 1.0 await scan() - - -@pytest.mark.asyncio -async def test_unbound_put(): - class TestController(Controller): - async def put_value(self, value): - pass - - async def put_no_value(self): - pass - - unbound_put = UnboundPut(TestController.put_value) - - with pytest.raises(NotImplementedError): - await unbound_put() - - with pytest.raises(FastCSError): - UnboundPut(TestController.put_no_value) # type: ignore - - with pytest.raises(FastCSError): - Put(TestController().put_no_value) # type: ignore - - put = unbound_put.bind(TestController()) - - await put(1)