Skip to content

Commit 7e66f35

Browse files
committed
WIP
1 parent 9bd7793 commit 7e66f35

File tree

6 files changed

+49
-17
lines changed

6 files changed

+49
-17
lines changed

src/fastcs/controller.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ def get_sub_controllers(self) -> dict[str, BaseController]:
4444

4545
def get_attributes(self) -> dict[str, Attribute]:
4646
"""For getting any attributes which aren't defined on the class itself."""
47-
4847
return {}
4948

5049

src/fastcs/mapping.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from collections.abc import Iterator
22
from dataclasses import dataclass
3+
from typing import get_type_hints
34

4-
from .attributes import Attribute
5+
from .attributes import Attribute, AttrR, AttrW, AttrRW
56
from .controller import BaseController, Controller
67
from .cs_methods import Command, Put, Scan
78
from .wrappers import WrappedMethod
@@ -52,11 +53,18 @@ def _get_single_mapping(controller: BaseController) -> SingleMapping:
5253
command_methods[attr_name] = command_method
5354

5455
attributes: dict[str, Attribute] = {}
55-
for name in dir(type(controller)):
56-
if isinstance((attr := getattr(controller, name, None)), Attribute):
56+
for name in set(get_type_hints(type(controller))) | set(dir(controller)):
57+
if (
58+
isinstance(
59+
(attr := getattr(controller, name, None)), AttrRW | AttrR | AttrW
60+
)
61+
and attr.enabled
62+
):
5763
attributes[name] = attr
5864

59-
object_defined_attributes = controller.get_attributes()
65+
object_defined_attributes = {
66+
name: attr for name, attr in controller.get_attributes().items() if attr.enabled
67+
}
6068

6169
if conflicting_keys := {
6270
key

tests/backends/epics/test_ioc.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any
1+
from typing import Any, get_type_hints
22

33
import pytest
44
from pytest_mock import MockerFixture
@@ -401,6 +401,7 @@ def test_long_pv_names_discarded(mocker: MockerFixture):
401401
long_rw_name = "attr_rw_with_a_reallyreally_long_name_that_is_too_long_for_RBV"
402402
assert long_name_controller.attr_rw_short_name.enabled
403403
assert getattr(long_name_controller, long_attr_name).enabled
404+
404405
EpicsIOC(DEVICE, long_name_mapping)
405406
assert long_name_controller.attr_rw_short_name.enabled
406407
assert not getattr(long_name_controller, long_attr_name).enabled

tests/backends/tango/test_dsr.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def tango_context(self, assertable_controller):
1414
yield proxy
1515

1616
def test_list_attributes(self, tango_context):
17-
assert list(tango_context.get_attribute_list()) == [
17+
assert set(tango_context.get_attribute_list()) == {
1818
"BigEnum",
1919
"ReadBool",
2020
"ReadInt",
@@ -26,7 +26,7 @@ def test_list_attributes(self, tango_context):
2626
"SubController02_ReadInt",
2727
"State",
2828
"Status",
29-
]
29+
}
3030

3131
def test_list_commands(self, tango_context):
3232
assert list(tango_context.get_command_list()) == [

tests/conftest.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,6 @@ class TestSubController(SubController):
5757

5858

5959
class TestController(Controller):
60-
def __init__(self) -> None:
61-
super().__init__()
62-
63-
self._sub_controllers: list[TestSubController] = []
64-
for index in range(1, 3):
65-
controller = TestSubController()
66-
self._sub_controllers.append(controller)
67-
self.register_sub_controller(f"SubController{index:02d}", controller)
68-
6960
read_int: AttrR = AttrR(Int(), handler=TestUpdater())
7061
read_write_int: AttrRW = AttrRW(Int(), handler=TestHandler())
7162
read_write_float: AttrRW = AttrRW(Float())
@@ -77,6 +68,15 @@ def __init__(self) -> None:
7768
allowed_values=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
7869
)
7970

71+
def __init__(self) -> None:
72+
super().__init__()
73+
74+
self._sub_controllers: list[TestSubController] = []
75+
for index in range(1, 3):
76+
controller = TestSubController()
77+
self._sub_controllers.append(controller)
78+
self.register_sub_controller(f"SubController{index:02d}", controller)
79+
8080
initialised = False
8181
connected = False
8282
count = 0

tests/test_controller.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import pytest
22

3+
from fastcs.attributes import Attribute, AttrR
34
from fastcs.controller import Controller, SubController
5+
from fastcs.datatypes import Int
46
from fastcs.mapping import _get_single_mapping, _walk_mappings
57

68

@@ -29,3 +31,25 @@ def test_controller_nesting():
2931
ValueError, match=r"SubController is already registered under .*"
3032
):
3133
controller.register_sub_controller("c", sub_controller)
34+
35+
36+
def test_attribute_parsing():
37+
runtime_attribute = AttrR(Int())
38+
39+
class SomeController(Controller):
40+
annotated_attr: AttrR[int]
41+
annotated_attr_not_defined_in_init: AttrR[int]
42+
43+
def get_attributes(self) -> dict[str, Attribute]:
44+
return {"get_attributes_attr": runtime_attribute}
45+
46+
def __init__(self):
47+
self.annotated_attr = AttrR(Int())
48+
super().__init__()
49+
50+
controller = SomeController()
51+
mapping = next(_walk_mappings(controller))
52+
assert mapping.attributes == {
53+
"get_attributes_attr": runtime_attribute,
54+
"annotated_attr": controller.annotated_attr,
55+
}

0 commit comments

Comments
 (0)