Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions src/fastcs/control_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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()
Expand Down Expand Up @@ -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):
Expand All @@ -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])
Expand Down
4 changes: 2 additions & 2 deletions src/fastcs/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("_")}
Expand All @@ -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]]):
Expand Down
20 changes: 2 additions & 18 deletions src/fastcs/controller_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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"""
Expand All @@ -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] = []
Expand Down
35 changes: 0 additions & 35 deletions src/fastcs/cs_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

Expand Down Expand Up @@ -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
7 changes: 0 additions & 7 deletions src/fastcs/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
Controller_T,
UnboundCommand,
UnboundCommandCallback,
UnboundPut,
UnboundPutCallback,
UnboundScan,
UnboundScanCallback,
)
Expand All @@ -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]]:
Expand Down
1 change: 0 additions & 1 deletion tests/assertable_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
35 changes: 1 addition & 34 deletions tests/test_cs_methods.py
Original file line number Diff line number Diff line change
@@ -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


Expand Down Expand Up @@ -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)