Skip to content

Commit f24a40f

Browse files
committed
cleaned up after rebase
1 parent 4f675eb commit f24a40f

File tree

9 files changed

+44
-101
lines changed

9 files changed

+44
-101
lines changed

src/fastcs/transport/epics/gui.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def _get_attribute_component(
8585
case AttrRW():
8686
read_widget = self._get_read_widget(attribute)
8787
write_widget = self._get_write_widget(attribute)
88-
if write_widget is None or write_widget is None:
88+
if write_widget is None or read_widget is None:
8989
return None
9090
return SignalRW(
9191
name=name,

src/fastcs/transport/epics/ioc.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import asyncio
2-
import warnings
32
from collections.abc import Callable
43
from types import MethodType
54
from typing import Any, Literal
@@ -13,8 +12,8 @@
1312
from fastcs.datatypes import DataType, T
1413
from fastcs.transport.epics.util import (
1514
builder_callable_from_attribute,
16-
get_callable_from_epics_type,
17-
get_callable_to_epics_type,
15+
cast_from_epics_type,
16+
cast_to_epics_type,
1817
record_metadata_from_attribute,
1918
record_metadata_from_datatype,
2019
)
@@ -154,10 +153,8 @@ def _create_and_link_attribute_pvs(pv_prefix: str, controller: Controller) -> No
154153
def _create_and_link_read_pv(
155154
pv_prefix: str, pv_name: str, attr_name: str, attribute: AttrR[T]
156155
) -> None:
157-
cast_to_epics_type = get_callable_to_epics_type(attribute.datatype)
158-
159156
async def async_record_set(value: T):
160-
record.set(cast_to_epics_type(value))
157+
record.set(cast_to_epics_type(attribute.datatype, value))
161158

162159
record = _make_record(f"{pv_prefix}:{pv_name}", attribute)
163160
_add_attr_pvi_info(record, pv_prefix, attr_name, "r")
@@ -191,14 +188,13 @@ def datatype_updater(datatype: DataType):
191188
def _create_and_link_write_pv(
192189
pv_prefix: str, pv_name: str, attr_name: str, attribute: AttrW[T]
193190
) -> None:
194-
cast_from_epics_type = get_callable_from_epics_type(attribute.datatype)
195-
cast_to_epics_type = get_callable_to_epics_type(attribute.datatype)
196-
197191
async def on_update(value):
198-
await attribute.process_without_display_update(cast_from_epics_type(value))
192+
await attribute.process_without_display_update(
193+
cast_from_epics_type(attribute.datatype, value)
194+
)
199195

200196
async def async_write_display(value: T):
201-
record.set(cast_to_epics_type(value), process=False)
197+
record.set(cast_to_epics_type(attribute.datatype, value), process=False)
202198

203199
record = _make_record(f"{pv_prefix}:{pv_name}", attribute, on_update=on_update)
204200

src/fastcs/transport/epics/util.py

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from collections.abc import Callable
21
from dataclasses import asdict
32

43
from softioc import builder
@@ -78,35 +77,24 @@ def record_metadata_from_datatype(datatype: DataType[T]) -> dict[str, str]:
7877
return arguments
7978

8079

81-
def get_callable_from_epics_type(datatype: DataType[T]) -> Callable[[object], T]:
80+
def cast_from_epics_type(datatype: DataType[T], value: object) -> T:
8281
match datatype:
8382
case Enum():
84-
85-
def cast_from_epics_type(value: object) -> T:
86-
return datatype.validate(datatype.members[value])
87-
83+
return datatype.validate(datatype.members[value])
8884
case datatype if issubclass(type(datatype), EPICS_ALLOWED_DATATYPES):
89-
90-
def cast_from_epics_type(value) -> T:
91-
return datatype.validate(value)
85+
return datatype.validate(value) # type: ignore
9286
case _:
9387
raise ValueError(f"Unsupported datatype {datatype}")
94-
return cast_from_epics_type
9588

9689

97-
def get_callable_to_epics_type(datatype: DataType[T]) -> Callable[[T], object]:
90+
def cast_to_epics_type(datatype: DataType[T], value: T) -> object:
9891
match datatype:
9992
case Enum():
100-
101-
def cast_to_epics_type(value) -> object:
102-
return datatype.index_of(datatype.validate(value))
93+
return datatype.index_of(datatype.validate(value))
10394
case datatype if issubclass(type(datatype), EPICS_ALLOWED_DATATYPES):
104-
105-
def cast_to_epics_type(value) -> object:
106-
return datatype.validate(value)
95+
return datatype.validate(value)
10796
case _:
10897
raise ValueError(f"Unsupported datatype {datatype}")
109-
return cast_to_epics_type
11098

11199

112100
def builder_callable_from_attribute(

src/fastcs/transport/rest/rest.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010

1111
from .options import RestServerOptions
1212
from .util import (
13+
cast_from_rest_type,
14+
cast_to_rest_type,
1315
convert_datatype,
14-
get_cast_method_from_rest_type,
15-
get_cast_method_to_rest_type,
1616
)
1717

1818

@@ -58,10 +58,8 @@ def _put_request_body(attribute: AttrW[T]):
5858
def _wrap_attr_put(
5959
attribute: AttrW[T],
6060
) -> Callable[[T], Coroutine[Any, Any, None]]:
61-
cast_method = get_cast_method_from_rest_type(attribute.datatype)
62-
6361
async def attr_set(request):
64-
await attribute.process(cast_method(request.value))
62+
await attribute.process(cast_from_rest_type(attribute.datatype, request.value))
6563

6664
# Fast api uses type annotations for validation, schema, conversions
6765
attr_set.__annotations__["request"] = _put_request_body(attribute)
@@ -86,11 +84,9 @@ def _get_response_body(attribute: AttrR[T]):
8684
def _wrap_attr_get(
8785
attribute: AttrR[T],
8886
) -> Callable[[], Coroutine[Any, Any, Any]]:
89-
cast_method = get_cast_method_to_rest_type(attribute.datatype)
90-
9187
async def attr_get() -> Any: # Must be any as response_model is set
9288
value = attribute.get() # type: ignore
93-
return {"value": cast_method(value)}
89+
return {"value": cast_to_rest_type(attribute.datatype, value)}
9490

9591
return attr_get
9692

src/fastcs/transport/rest/util.py

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from collections.abc import Callable
21

32
import numpy as np
43

@@ -15,33 +14,21 @@ def convert_datatype(datatype: DataType[T]) -> type:
1514
return datatype.dtype
1615

1716

18-
def get_cast_method_to_rest_type(datatype: DataType[T]) -> Callable[[T], object]:
17+
def cast_to_rest_type(datatype: DataType[T], value: T) -> object:
1918
match datatype:
2019
case WaveForm():
21-
22-
def cast_to_rest_type(value) -> list:
23-
return value.tolist()
20+
return value.tolist()
2421
case datatype if issubclass(type(datatype), REST_ALLOWED_DATATYPES):
25-
26-
def cast_to_rest_type(value):
27-
return datatype.validate(value)
22+
return datatype.validate(value)
2823
case _:
2924
raise ValueError(f"Unsupported datatype {datatype}")
3025

31-
return cast_to_rest_type
32-
3326

34-
def get_cast_method_from_rest_type(datatype: DataType[T]) -> Callable[[object], T]:
27+
def cast_from_rest_type(datatype: DataType[T], value: object) -> T:
3528
match datatype:
3629
case WaveForm():
37-
38-
def cast_from_rest_type(value) -> T:
39-
return datatype.validate(np.array(value, dtype=datatype.array_dtype))
30+
return datatype.validate(np.array(value, dtype=datatype.array_dtype))
4031
case datatype if issubclass(type(datatype), REST_ALLOWED_DATATYPES):
41-
42-
def cast_from_rest_type(value) -> T:
43-
return datatype.validate(value)
32+
return datatype.validate(value) # type: ignore
4433
case _:
4534
raise ValueError(f"Unsupported datatype {datatype}")
46-
47-
return cast_from_rest_type

src/fastcs/transport/tango/dsr.py

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111

1212
from .options import TangoDSROptions
1313
from .util import (
14-
get_cast_method_from_tango_type,
15-
get_cast_method_to_tango_type,
14+
cast_from_tango_type,
15+
cast_to_tango_type,
1616
get_server_metadata_from_attribute,
1717
get_server_metadata_from_datatype,
1818
)
@@ -23,23 +23,13 @@ def _wrap_updater_fget(
2323
attribute: AttrR,
2424
controller: BaseController,
2525
) -> Callable[[Any], Any]:
26-
cast_method = get_cast_method_to_tango_type(attribute.datatype)
27-
2826
async def fget(tango_device: Device):
2927
tango_device.info_stream(f"called fget method: {attr_name}")
30-
return cast_method(attribute.get())
28+
return cast_to_tango_type(attribute.datatype, attribute.get())
3129

3230
return fget
3331

3432

35-
def _tango_display_format(attribute: Attribute) -> str:
36-
match attribute.datatype:
37-
case Float(prec):
38-
return f"%.{prec}"
39-
40-
return "6.2f" # `tango.server.attribute` default for `format`
41-
42-
4333
async def _run_threadsafe_blocking(
4434
coro: Coroutine[Any, Any, Any], loop: asyncio.AbstractEventLoop
4535
) -> None:
@@ -57,11 +47,9 @@ def _wrap_updater_fset(
5747
controller: BaseController,
5848
loop: asyncio.AbstractEventLoop,
5949
) -> Callable[[Any, Any], Any]:
60-
cast_method = get_cast_method_from_tango_type(attribute.datatype)
61-
62-
async def fset(tango_device: Device, val):
50+
async def fset(tango_device: Device, value):
6351
tango_device.info_stream(f"called fset method: {attr_name}")
64-
coro = attribute.process(val)
52+
coro = attribute.process(cast_from_tango_type(attribute.datatype, value))
6553
await _run_threadsafe_blocking(coro, loop)
6654

6755
return fset

src/fastcs/transport/tango/util.py

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from collections.abc import Callable
21
from dataclasses import asdict
32
from typing import Any
43

@@ -61,33 +60,21 @@ def get_server_metadata_from_datatype(datatype: DataType[T]) -> dict[str, str]:
6160
return arguments
6261

6362

64-
def get_cast_method_to_tango_type(datatype: DataType[T]) -> Callable[[T], object]:
63+
def cast_to_tango_type(datatype: DataType[T], value: T) -> object:
6564
match datatype:
6665
case Enum():
67-
68-
def cast_to_tango_type(value) -> int:
69-
return datatype.index_of(datatype.validate(value))
66+
return datatype.index_of(datatype.validate(value))
7067
case datatype if issubclass(type(datatype), TANGO_ALLOWED_DATATYPES):
71-
72-
def cast_to_tango_type(value) -> object:
73-
return datatype.validate(value)
68+
return datatype.validate(value)
7469
case _:
7570
raise ValueError(f"Unsupported datatype {datatype}")
76-
return cast_to_tango_type
7771

7872

79-
def get_cast_method_from_tango_type(datatype: DataType[T]) -> Callable[[object], T]:
73+
def cast_from_tango_type(datatype: DataType[T], value: object) -> T:
8074
match datatype:
8175
case Enum():
82-
83-
def cast_from_tango_type(value: object) -> T:
84-
return datatype.validate(datatype.members[value])
85-
76+
return datatype.validate(datatype.members[value])
8677
case datatype if issubclass(type(datatype), TANGO_ALLOWED_DATATYPES):
87-
88-
def cast_from_tango_type(value) -> T:
89-
return datatype.validate(value)
78+
return datatype.validate(value) # type: ignore
9079
case _:
9180
raise ValueError(f"Unsupported datatype {datatype}")
92-
93-
return cast_from_tango_type

tests/conftest.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,9 @@
1010
import pytest
1111
from aioca import purge_channel_caches
1212

13-
from fastcs.attributes import AttrR, AttrRW, AttrW, Handler, Sender, Updater
14-
from fastcs.controller import Controller, SubController
15-
from fastcs.datatypes import Bool, Float, Int, String
16-
from fastcs.transport.tango.dsr import register_dev
17-
from fastcs.datatypes import Bool, Enum, Float, Int, String, WaveForm
18-
from fastcs.wrappers import command, scan
1913
from fastcs.attributes import AttrR, AttrRW, AttrW
2014
from fastcs.datatypes import Bool, Float, Int, String
15+
from fastcs.transport.tango.dsr import register_dev
2116
from tests.assertable_controller import (
2217
TestController,
2318
TestHandler,

tests/transport/tango/test_dsr.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import asyncio
2-
from unittest import mock
3-
42
import enum
3+
from unittest import mock
54

65
import numpy as np
76
import pytest
@@ -22,6 +21,8 @@
2221

2322
async def patch_run_threadsafe_blocking(coro, loop):
2423
await coro
24+
25+
2526
class TangoAssertableController(AssertableController):
2627
read_int = AttrR(Int(), handler=TestUpdater())
2728
read_write_int = AttrRW(Int(), handler=TestHandler())
@@ -34,6 +35,11 @@ class TangoAssertableController(AssertableController):
3435
two_d_waveform = AttrRW(WaveForm(np.int32, (10, 10)))
3536

3637

38+
@pytest.fixture(scope="class")
39+
def assertable_controller(class_mocker: MockerFixture):
40+
return TangoAssertableController(class_mocker)
41+
42+
3743
class TestTangoDevice:
3844
@pytest.fixture(scope="class")
3945
def tango_context(self, assertable_controller):

0 commit comments

Comments
 (0)