Skip to content

Commit b099d41

Browse files
committed
Mapping -> Controller
1 parent 6f1beac commit b099d41

File tree

18 files changed

+129
-172
lines changed

18 files changed

+129
-172
lines changed

src/fastcs/backend.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77
from fastcs.util import AsyncioDispatcher
88

99
from .attributes import AttrR, AttrW, Sender, Updater
10-
from .controller import Controller
10+
from .controller import Controller, SingleMapping
1111
from .exceptions import FastCSException
12-
from .mapping import Mapping, SingleMapping
1312

1413

1514
class Backend:
@@ -29,17 +28,10 @@ def __init__(
2928
self._controller.initialise(), self._loop
3029
).result()
3130

32-
self.mapping = Mapping(self._controller)
3331
self._link_process_tasks()
3432

35-
self.context = {
36-
"dispatcher": self.dispatcher,
37-
"controller": self._controller,
38-
"mapping": self.mapping,
39-
}
40-
4133
def _link_process_tasks(self):
42-
for single_mapping in self.mapping.get_controller_mappings():
34+
for single_mapping in self._controller.get_controller_mappings():
4335
_link_single_controller_put_tasks(single_mapping)
4436
_link_attribute_sender_class(single_mapping)
4537

@@ -58,7 +50,7 @@ def _run_initial_futures(self):
5850
def start_scan_futures(self):
5951
self._scan_futures = {
6052
asyncio.run_coroutine_threadsafe(coro(), self._loop)
61-
for coro in _get_scan_coros(self.mapping)
53+
for coro in _get_scan_coros(self._controller)
6254
}
6355

6456
def stop_scan_futures(self):
@@ -106,10 +98,10 @@ async def callback(value):
10698
return callback
10799

108100

109-
def _get_scan_coros(mapping: Mapping) -> list[Callable]:
101+
def _get_scan_coros(controller: Controller) -> list[Callable]:
110102
scan_dict: dict[float, list[Callable]] = defaultdict(list)
111103

112-
for single_mapping in mapping.get_controller_mappings():
104+
for single_mapping in controller.get_controller_mappings():
113105
_add_scan_method_tasks(scan_dict, single_mapping)
114106
_add_attribute_updater_tasks(scan_dict, single_mapping)
115107

src/fastcs/controller.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
from __future__ import annotations
22

3+
from collections.abc import Iterator
34
from copy import copy
5+
from dataclasses import dataclass
46

57
from .attributes import Attribute
8+
from .cs_methods import Command, Put, Scan
9+
from .wrappers import WrappedMethod
10+
11+
12+
@dataclass
13+
class SingleMapping:
14+
controller: BaseController
15+
scan_methods: dict[str, Scan]
16+
put_methods: dict[str, Put]
17+
command_methods: dict[str, Command]
18+
attributes: dict[str, Attribute]
619

720

821
class BaseController:
@@ -42,6 +55,37 @@ def register_sub_controller(self, name: str, sub_controller: SubController):
4255
def get_sub_controllers(self) -> dict[str, BaseController]:
4356
return self.__sub_controller_tree
4457

58+
def get_controller_mappings(self) -> list[SingleMapping]:
59+
return list(_walk_mappings(self))
60+
61+
62+
def _walk_mappings(controller: BaseController) -> Iterator[SingleMapping]:
63+
yield _get_single_mapping(controller)
64+
for sub_controller in controller.get_sub_controllers().values():
65+
yield from _walk_mappings(sub_controller)
66+
67+
68+
def _get_single_mapping(controller: BaseController) -> SingleMapping:
69+
scan_methods: dict[str, Scan] = {}
70+
put_methods: dict[str, Put] = {}
71+
command_methods: dict[str, Command] = {}
72+
attributes: dict[str, Attribute] = {}
73+
for attr_name in dir(controller):
74+
attr = getattr(controller, attr_name)
75+
match attr:
76+
case WrappedMethod(fastcs_method=Put(enabled=True) as put_method):
77+
put_methods[attr_name] = put_method
78+
case WrappedMethod(fastcs_method=Scan(enabled=True) as scan_method):
79+
scan_methods[attr_name] = scan_method
80+
case WrappedMethod(fastcs_method=Command(enabled=True) as command_method):
81+
command_methods[attr_name] = command_method
82+
case Attribute(enabled=True):
83+
attributes[attr_name] = attr
84+
85+
return SingleMapping(
86+
controller, scan_methods, put_methods, command_methods, attributes
87+
)
88+
4589

4690
class Controller(BaseController):
4791
"""Top-level controller for a device.

src/fastcs/main.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,22 @@ def __init__(
3232
from .transport.epics.adapter import EpicsTransport
3333

3434
self._transport = EpicsTransport(
35-
self._backend.mapping,
36-
self._backend.context,
35+
controller,
3736
self._backend.dispatcher,
3837
transport_options,
3938
)
4039
case TangoOptions():
4140
from .transport.tango.adapter import TangoTransport
4241

4342
self._transport = TangoTransport(
44-
self._backend.mapping,
43+
controller,
4544
transport_options,
4645
)
4746
case RestOptions():
4847
from .transport.rest.adapter import RestTransport
4948

5049
self._transport = RestTransport(
51-
self._backend.mapping,
50+
controller,
5251
transport_options,
5352
)
5453

src/fastcs/mapping.py

Lines changed: 0 additions & 59 deletions
This file was deleted.

src/fastcs/transport/epics/adapter.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from softioc.asyncio_dispatcher import AsyncioDispatcher as Dispatcher
44

5-
from fastcs.mapping import Mapping
5+
from fastcs.controller import Controller
66
from fastcs.transport.adapter import TransportAdapter
77
from fastcs.util import AsyncioDispatcher
88

@@ -15,26 +15,23 @@
1515
class EpicsTransport(TransportAdapter):
1616
def __init__(
1717
self,
18-
mapping: Mapping,
19-
context: dict,
18+
controller: Controller,
2019
dispatcher: AsyncioDispatcher,
2120
options: EpicsOptions | None = None,
2221
) -> None:
2322
self.options = options or EpicsOptions()
24-
self._mapping = mapping
25-
self._context = context
23+
self._controller = controller
2624
self._dispatcher = dispatcher
2725
self._pv_prefix = self.options.ioc.pv_prefix
28-
self._ioc = EpicsIOC(self.options.ioc.pv_prefix, self._mapping)
26+
self._ioc = EpicsIOC(self.options.ioc.pv_prefix, controller)
2927

3028
def create_docs(self) -> None:
31-
EpicsDocs(self._mapping).create_docs(self.options.docs)
29+
EpicsDocs(self._controller).create_docs(self.options.docs)
3230

3331
def create_gui(self) -> None:
34-
EpicsGUI(self._mapping, self._pv_prefix).create_gui(self.options.gui)
32+
EpicsGUI(self._controller, self._pv_prefix).create_gui(self.options.gui)
3533

3634
def run(self):
3735
self._ioc.run(
3836
cast(Dispatcher, self._dispatcher),
39-
self._context,
4037
)

src/fastcs/transport/epics/docs.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
from fastcs.mapping import Mapping
1+
from fastcs.controller import Controller
22

33
from .options import EpicsDocsOptions
44

55

66
class EpicsDocs:
7-
def __init__(self, mapping: Mapping) -> None:
8-
self._mapping = mapping
7+
def __init__(self, controller: Controller) -> None:
8+
self._controller = controller
99

1010
def create_docs(self, options: EpicsDocsOptions | None = None) -> None:
1111
if options is None:

src/fastcs/transport/epics/gui.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@
2323
from pydantic import ValidationError
2424

2525
from fastcs.attributes import Attribute, AttrR, AttrRW, AttrW
26+
from fastcs.controller import Controller, SingleMapping, _get_single_mapping
2627
from fastcs.cs_methods import Command
2728
from fastcs.datatypes import Bool, Float, Int, String
2829
from fastcs.exceptions import FastCSException
29-
from fastcs.mapping import Mapping, SingleMapping, _get_single_mapping
3030
from fastcs.util import snake_to_pascal
3131

3232
from .options import EpicsGUIFormat, EpicsGUIOptions
3333

3434

3535
class EpicsGUI:
36-
def __init__(self, mapping: Mapping, pv_prefix: str) -> None:
37-
self._mapping = mapping
36+
def __init__(self, controller: Controller, pv_prefix: str) -> None:
37+
self._controller = controller
3838
self._pv_prefix = pv_prefix
3939

4040
def _get_pv(self, attr_path: list[str], name: str):
@@ -117,7 +117,7 @@ def create_gui(self, options: EpicsGUIOptions | None = None) -> None:
117117

118118
assert options.output_path.suffix == options.file_format.value
119119

120-
controller_mapping = self._mapping.get_controller_mappings()[0]
120+
controller_mapping = self._controller.get_controller_mappings()[0]
121121
components = self.extract_mapping_components(controller_mapping)
122122
device = Device(label=options.title, children=components)
123123

src/fastcs/transport/epics/ioc.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88
from softioc.pythonSoftIoc import RecordWrapper
99

1010
from fastcs.attributes import AttrR, AttrRW, AttrW
11-
from fastcs.controller import BaseController
11+
from fastcs.controller import BaseController, Controller
1212
from fastcs.datatypes import Bool, DataType, Float, Int, String, T
1313
from fastcs.exceptions import FastCSException
14-
from fastcs.mapping import Mapping
1514
from fastcs.transport.epics.util import (
1615
MBB_STATE_FIELDS,
1716
attr_is_enum,
@@ -46,24 +45,31 @@ def datatype_to_epics_fields(datatype: DataType) -> dict[str, Any]:
4645

4746
class EpicsIOC:
4847
def __init__(
49-
self, pv_prefix: str, mapping: Mapping, options: EpicsIOCOptions | None = None
48+
self,
49+
pv_prefix: str,
50+
controller: Controller,
51+
options: EpicsIOCOptions | None = None,
5052
):
5153
self.options = options or EpicsIOCOptions()
54+
self._controller = controller
5255
_add_pvi_info(f"{pv_prefix}:PVI")
53-
_add_sub_controller_pvi_info(pv_prefix, mapping.controller)
56+
_add_sub_controller_pvi_info(pv_prefix, controller)
5457

55-
_create_and_link_attribute_pvs(pv_prefix, mapping)
56-
_create_and_link_command_pvs(pv_prefix, mapping)
58+
_create_and_link_attribute_pvs(pv_prefix, controller)
59+
_create_and_link_command_pvs(pv_prefix, controller)
5760

5861
def run(
5962
self,
6063
dispatcher: AsyncioDispatcher,
61-
context: dict[str, Any],
6264
) -> None:
6365
builder.LoadDatabase()
6466
softioc.iocInit(dispatcher)
6567

6668
if self.options.terminal:
69+
context = {
70+
"dispatcher": dispatcher,
71+
"controller": self._controller,
72+
}
6773
softioc.interactive_ioc(context)
6874

6975

@@ -131,8 +137,8 @@ def _add_sub_controller_pvi_info(pv_prefix: str, parent: BaseController):
131137
_add_sub_controller_pvi_info(pv_prefix, child)
132138

133139

134-
def _create_and_link_attribute_pvs(pv_prefix: str, mapping: Mapping) -> None:
135-
for single_mapping in mapping.get_controller_mappings():
140+
def _create_and_link_attribute_pvs(pv_prefix: str, controller: Controller) -> None:
141+
for single_mapping in controller.get_controller_mappings():
136142
path = single_mapping.controller.path
137143
for attr_name, attribute in single_mapping.attributes.items():
138144
pv_name = attr_name.title().replace("_", "")
@@ -322,8 +328,8 @@ def datatype_updater(datatype: DataType):
322328
return record
323329

324330

325-
def _create_and_link_command_pvs(pv_prefix: str, mapping: Mapping) -> None:
326-
for single_mapping in mapping.get_controller_mappings():
331+
def _create_and_link_command_pvs(pv_prefix: str, controller: Controller) -> None:
332+
for single_mapping in controller.get_controller_mappings():
327333
path = single_mapping.controller.path
328334
for attr_name, method in single_mapping.command_methods.items():
329335
pv_name = attr_name.title().replace("_", "")

src/fastcs/transport/rest/adapter.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from fastcs.mapping import Mapping
1+
from fastcs.controller import Controller
22
from fastcs.transport.adapter import TransportAdapter
33

44
from .options import RestOptions
@@ -8,12 +8,11 @@
88
class RestTransport(TransportAdapter):
99
def __init__(
1010
self,
11-
mapping: Mapping,
11+
controller: Controller,
1212
options: RestOptions | None = None,
1313
):
1414
self.options = options or RestOptions()
15-
self._mapping = mapping
16-
self._server = RestServer(self._mapping)
15+
self._server = RestServer(controller)
1716

1817
def create_docs(self) -> None:
1918
raise NotImplementedError

src/fastcs/transport/rest/backend.py

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)