Skip to content

Commit b051a17

Browse files
committed
Proposal API
1 parent bdab4fa commit b051a17

File tree

14 files changed

+203
-60
lines changed

14 files changed

+203
-60
lines changed

src/fastcs/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
"""
88

99
from ._version import __version__
10+
from .main import FastCS as FastCS
1011

1112
__all__ = ["__version__"]

src/fastcs/backend.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import asyncio
2+
from abc import ABC, abstractmethod
23
from collections import defaultdict
34
from collections.abc import Callable
45
from concurrent.futures import Future
56
from types import MethodType
67

7-
from softioc.asyncio_dispatcher import AsyncioDispatcher
8+
from fastcs.util import AsyncioDispatcher
89

910
from .attributes import AttrR, AttrW, Sender, Updater
1011
from .controller import Controller
1112
from .exceptions import FastCSException
1213
from .mapping import Mapping, SingleMapping
1314

1415

15-
class Backend:
16+
class Backend(ABC):
1617
def __init__(
1718
self, controller: Controller, loop: asyncio.AbstractEventLoop | None = None
1819
):
@@ -47,6 +48,12 @@ def run(self):
4748

4849
self._run()
4950

51+
def create_docs(self) -> None:
52+
self._create_docs()
53+
54+
def create_gui(self) -> None:
55+
self._create_gui()
56+
5057
def _run_initial_tasks(self):
5158
for task in self._initial_tasks:
5259
future = asyncio.run_coroutine_threadsafe(task(), self._loop)
@@ -58,8 +65,17 @@ def _start_scan_tasks(self):
5865
for task in scan_tasks:
5966
asyncio.run_coroutine_threadsafe(task(), self._loop)
6067

61-
def _run(self):
62-
raise NotImplementedError("Specific Backend must implement _run")
68+
@abstractmethod
69+
def _run(self) -> None:
70+
pass
71+
72+
@abstractmethod
73+
def _create_docs(self) -> None:
74+
pass
75+
76+
@abstractmethod
77+
def _create_gui(self) -> None:
78+
pass
6379

6480

6581
def _link_single_controller_put_tasks(single_mapping: SingleMapping) -> None:

src/fastcs/backends/__init__.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
from .asyncio_backend import AsyncioBackend
2-
from .epics.backend import EpicsBackend
3-
from .tango.backend import TangoBackend
1+
from .epics.options import EpicsDocsOptions as EpicsDocsOptions
2+
from .epics.options import EpicsGUIOptions as EpicsGUIOptions
3+
from .epics.options import EpicsIOCOptions as EpicsIOCOptions
4+
from .epics.options import EpicsOptions as EpicsOptions
5+
from .tango.options import TangoDSROptions as TangoDSROptions
6+
from .tango.options import TangoOptions as TangoOptions
47

5-
__all__ = ["EpicsBackend", "AsyncioBackend", "TangoBackend"]
8+
__all__ = ["EpicsOptions", "TangoOptions"]
Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,37 @@
1+
from typing import cast
2+
3+
from softioc.asyncio_dispatcher import AsyncioDispatcher
4+
15
from fastcs.backend import Backend
26
from fastcs.controller import Controller
37

4-
from .docs import EpicsDocs, EpicsDocsOptions
5-
from .gui import EpicsGUI, EpicsGUIOptions
6-
from .ioc import EpicsIOC, EpicsIOCOptions
8+
from .docs import EpicsDocs
9+
from .gui import EpicsGUI
10+
from .ioc import EpicsIOC
11+
from .options import EpicsOptions
712

813

914
class EpicsBackend(Backend):
10-
def __init__(self, controller: Controller, pv_prefix: str = "MY-DEVICE-PREFIX"):
15+
def __init__(
16+
self, controller: Controller, options: EpicsOptions | None = None
17+
) -> None:
1118
super().__init__(controller)
1219

13-
self._pv_prefix = pv_prefix
14-
self._ioc = EpicsIOC(pv_prefix, self._mapping)
20+
if options is None:
21+
self.options = EpicsOptions()
22+
else:
23+
self.options = options
24+
25+
self._pv_prefix = self.options.ioc.pv_prefix
26+
self._ioc = EpicsIOC(self.options.ioc.pv_prefix, self._mapping)
1527

16-
def create_docs(self, options: EpicsDocsOptions | None = None) -> None:
17-
EpicsDocs(self._mapping).create_docs(options)
28+
def _create_docs(self) -> None:
29+
EpicsDocs(self._mapping).create_docs(self.options.docs)
1830

19-
def create_gui(self, options: EpicsGUIOptions | None = None) -> None:
20-
EpicsGUI(self._mapping, self._pv_prefix).create_gui(options)
31+
def _create_gui(self) -> None:
32+
EpicsGUI(self._mapping, self._pv_prefix).create_gui(self.options.gui)
2133

22-
def _run(self, options: EpicsIOCOptions | None = None):
23-
self._ioc.run(self._dispatcher, self._context, options)
34+
def _run(self):
35+
self._ioc.run(
36+
cast(AsyncioDispatcher, self._dispatcher), self._context, self.options.ioc
37+
)

src/fastcs/backends/epics/docs.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
1-
from dataclasses import dataclass
2-
from pathlib import Path
3-
41
from fastcs.mapping import Mapping
52

6-
7-
@dataclass
8-
class EpicsDocsOptions:
9-
path: Path = Path.cwd()
10-
depth: int | None = None
3+
from .options import EpicsDocsOptions
114

125

136
class EpicsDocs:

src/fastcs/backends/epics/gui.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
from dataclasses import dataclass
2-
from enum import Enum
3-
from pathlib import Path
4-
51
from pvi._format.dls import DLSFormatter
62
from pvi.device import (
73
LED,
@@ -33,17 +29,7 @@
3329
from fastcs.mapping import Mapping, SingleMapping, _get_single_mapping
3430
from fastcs.util import snake_to_pascal
3531

36-
37-
class EpicsGUIFormat(Enum):
38-
bob = ".bob"
39-
edl = ".edl"
40-
41-
42-
@dataclass
43-
class EpicsGUIOptions:
44-
output_path: Path = Path.cwd() / "output.bob"
45-
file_format: EpicsGUIFormat = EpicsGUIFormat.bob
46-
title: str = "Simple Device"
32+
from .options import EpicsGUIFormat, EpicsGUIOptions
4733

4834

4935
class EpicsGUI:

src/fastcs/backends/epics/ioc.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from collections.abc import Callable
2-
from dataclasses import dataclass
32
from types import MethodType
43
from typing import Any, Literal
54

@@ -19,12 +18,9 @@
1918
from fastcs.exceptions import FastCSException
2019
from fastcs.mapping import Mapping
2120

22-
EPICS_MAX_NAME_LENGTH = 60
23-
21+
from .options import EpicsIOCOptions
2422

25-
@dataclass
26-
class EpicsIOCOptions:
27-
terminal: bool = True
23+
EPICS_MAX_NAME_LENGTH = 60
2824

2925

3026
class EpicsIOC:
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from dataclasses import dataclass, field
2+
from enum import Enum
3+
from pathlib import Path
4+
5+
6+
@dataclass
7+
class EpicsDocsOptions:
8+
path: Path = Path.cwd()
9+
depth: int | None = None
10+
11+
12+
class EpicsGUIFormat(Enum):
13+
bob = ".bob"
14+
edl = ".edl"
15+
16+
17+
@dataclass
18+
class EpicsGUIOptions:
19+
output_path: Path = Path.cwd() / "output.bob"
20+
file_format: EpicsGUIFormat = EpicsGUIFormat.bob
21+
title: str = "Simple Device"
22+
23+
24+
@dataclass
25+
class EpicsIOCOptions:
26+
terminal: bool = True
27+
pv_prefix: str = "MY-DEVICE-PREFIX"
28+
29+
30+
@dataclass
31+
class EpicsOptions:
32+
docs: EpicsDocsOptions = field(default_factory=EpicsDocsOptions)
33+
gui: EpicsGUIOptions = field(default_factory=EpicsGUIOptions)
34+
ioc: EpicsIOCOptions = field(default_factory=EpicsIOCOptions)

src/fastcs/backends/tango/backend.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,25 @@
22
from fastcs.controller import Controller
33

44
from .dsr import TangoDSR
5+
from .options import TangoOptions
56

67

78
class TangoBackend(Backend):
8-
def __init__(self, controller: Controller):
9+
def __init__(self, controller: Controller, options: TangoOptions | None = None):
910
super().__init__(controller)
1011

12+
if options is None:
13+
self.options = TangoOptions()
14+
else:
15+
self.options = options
16+
1117
self._dsr = TangoDSR(self._mapping)
1218

13-
def _run(self):
14-
self._dsr.run()
19+
def _create_docs(self) -> None:
20+
raise NotImplementedError
21+
22+
def _create_gui(self) -> None:
23+
raise NotImplementedError
24+
25+
def _run(self) -> None:
26+
self._dsr.run(self.options.dsr)

src/fastcs/backends/tango/dsr.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from collections.abc import Awaitable, Callable
2-
from dataclasses import dataclass
32
from types import MethodType
43
from typing import Any
54

@@ -12,13 +11,7 @@
1211
from fastcs.datatypes import Float
1312
from fastcs.mapping import Mapping
1413

15-
16-
@dataclass
17-
class TangoDSROptions:
18-
dev_name: str = "MY/DEVICE/NAME"
19-
dev_class: str = "FAST_CS_DEVICE"
20-
dsr_instance: str = "MY_SERVER_INSTANCE"
21-
debug: bool = False
14+
from .options import TangoDSROptions
2215

2316

2417
def _wrap_updater_fget(

0 commit comments

Comments
 (0)