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
10 changes: 3 additions & 7 deletions src/fastcs/attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,7 @@ def __init__(
)
self._process_callbacks: list[AttrCallback[T]] | None = None
self._write_display_callbacks: list[AttrCallback[T]] | None = None

if handler is not None:
self._setter = handler
else:
self._setter = SimpleAttrHandler()
self._setter = handler

async def process(self, value: T) -> None:
await self.process_without_display_update(value)
Expand Down Expand Up @@ -221,7 +217,7 @@ def add_write_display_callback(self, callback: AttrCallback[T]) -> None:
self._write_display_callbacks.append(callback)

@property
def sender(self) -> AttrHandlerW:
def sender(self) -> AttrHandlerW | None:
return self._setter


Expand All @@ -241,7 +237,7 @@ def __init__(
datatype, # type: ignore
access_mode,
group=group,
handler=handler,
handler=handler if handler else SimpleAttrHandler(),
initial_value=initial_value,
description=description,
)
Expand Down
11 changes: 8 additions & 3 deletions tests/example_p4p_ioc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import numpy as np

from fastcs.attributes import AttrR, AttrRW, AttrW
from fastcs.attributes import AttrHandlerW, AttrR, AttrRW, AttrW
from fastcs.controller import Controller, SubController
from fastcs.datatypes import Bool, Enum, Float, Int, Table, Waveform
from fastcs.launch import FastCS
Expand All @@ -14,6 +14,11 @@
from fastcs.wrappers import command, scan


class SimpleAttributeSetter(AttrHandlerW):
async def put(self, attr, value):
await attr.update_display_without_process(value)


class FEnum(enum.Enum):
A = 0
B = 1
Expand All @@ -25,7 +30,7 @@ class FEnum(enum.Enum):
class ParentController(Controller):
description = "some controller"
a: AttrRW = AttrRW(Int(max=400_000, max_alarm=40_000))
b: AttrW = AttrW(Float(min=-1, min_alarm=-0.5))
b: AttrW = AttrW(Float(min=-1, min_alarm=-0.5), handler=SimpleAttributeSetter())

table: AttrRW = AttrRW(
Table([("A", np.int32), ("B", "i"), ("C", "?"), ("D", np.float64)])
Expand All @@ -34,7 +39,7 @@ class ParentController(Controller):

class ChildController(SubController):
fail_on_next_e = True
c: AttrW = AttrW(Int())
c: AttrW = AttrW(Int(), handler=SimpleAttributeSetter())

@command()
async def d(self):
Expand Down
34 changes: 17 additions & 17 deletions tests/test_attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
import pytest
from pytest_mock import MockerFixture

from fastcs.attributes import AttrHandlerR, AttrHandlerRW, AttrR, AttrRW, AttrW
from fastcs.attributes import (
AttrHandlerR,
AttrHandlerRW,
AttrR,
AttrRW,
AttrW,
)
from fastcs.datatypes import Int, String


Expand Down Expand Up @@ -34,29 +40,23 @@ async def device_add():
assert ui["number"] == 2


@pytest.mark.asyncio
async def test_simple_handler_w(mocker: MockerFixture):
attr = AttrW(Int())
update_display_mock = mocker.patch.object(attr, "update_display_without_process")

# This is called by the transport when it receives a put
await attr.sender.put(attr, 1)

# The callback to update the transport display should be called
update_display_mock.assert_called_once_with(1)


@pytest.mark.asyncio
async def test_simple_handler_rw(mocker: MockerFixture):
attr = AttrRW(Int())
update_display_mock = mocker.patch.object(attr, "update_display_without_process")
set_mock = mocker.patch.object(attr, "set")

attr.update_display_without_process = mocker.MagicMock(
wraps=attr.update_display_without_process
)
attr.set = mocker.MagicMock(wraps=attr.set)

assert attr.sender
# This is called by the transport when it receives a put
await attr.sender.put(attr, 1)

update_display_mock.assert_called_once_with(1)
# The Sender of the attribute should just set the value on the attribute
set_mock.assert_awaited_once_with(1)
attr.update_display_without_process.assert_called_once_with(1)
attr.set.assert_called_once_with(1)
assert attr.get() == 1


class SimpleUpdater(AttrHandlerR):
Expand Down
Loading