Skip to content

Commit

Permalink
Attributes can accept kwargs used to populate EPICS records fields
Browse files Browse the repository at this point in the history
  • Loading branch information
jsouter committed Jun 19, 2024
1 parent e324d66 commit 3fc0a70
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 54 deletions.
20 changes: 10 additions & 10 deletions src/fastcs/attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,19 @@ def __init__(
access_mode: AttrMode,
group: str | None = None,
handler: Any = None,
dropdown_mapping: dict[str, T] | None = None,
**kwargs: Any,
) -> None:
assert (
datatype.dtype in ATTRIBUTE_TYPES
), f"Attr type must be one of {ATTRIBUTE_TYPES}, received type {datatype.dtype}"
self._datatype: DataType[T] = datatype
self._access_mode: AttrMode = access_mode
self._group: str | None = group
self._dropdown_mapping: dict[str, T] | None = dropdown_mapping
self._kwargs = kwargs

Check warning on line 62 in src/fastcs/attributes.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/attributes.py#L61-L62

Added lines #L61 - L62 were not covered by tests

@property
def dropdown_mapping(self) -> dict[str, T] | None:
return self._dropdown_mapping
def kwargs(self) -> dict[str, T] | None:
return self._kwargs

Check warning on line 66 in src/fastcs/attributes.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/attributes.py#L66

Added line #L66 was not covered by tests

@property
def datatype(self) -> DataType[T]:
Expand Down Expand Up @@ -91,9 +91,9 @@ def __init__(
access_mode=AttrMode.READ,
group: str | None = None,
handler: Updater | None = None,
dropdown_mapping: dict[str, T] | None = None,
**kwargs: Any,
) -> None:
super().__init__(datatype, access_mode, group, handler, dropdown_mapping) # type: ignore
super().__init__(datatype, access_mode, group, handler, **kwargs) # type: ignore

Check warning on line 96 in src/fastcs/attributes.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/attributes.py#L96

Added line #L96 was not covered by tests
self._value: T = datatype.dtype()
self._update_callback: AttrCallback[T] | None = None
self._updater = handler
Expand Down Expand Up @@ -124,9 +124,9 @@ def __init__(
access_mode=AttrMode.WRITE,
group: str | None = None,
handler: Sender | None = None,
dropdown_mapping: dict[str, T] | None = None,
**kwargs: Any,
) -> None:
super().__init__(datatype, access_mode, group, handler, dropdown_mapping) # type: ignore
super().__init__(datatype, access_mode, group, handler, **kwargs) # type: ignore

Check warning on line 129 in src/fastcs/attributes.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/attributes.py#L129

Added line #L129 was not covered by tests
self._process_callback: AttrCallback[T] | None = None
self._write_display_callback: AttrCallback[T] | None = None
self._sender = handler
Expand Down Expand Up @@ -164,9 +164,9 @@ def __init__(
access_mode=AttrMode.READ_WRITE,
group: str | None = None,
handler: Handler | None = None,
dropdown_mapping: dict[str, T] | None = None,
**kwargs: Any,
) -> None:
super().__init__(datatype, access_mode, group, handler, dropdown_mapping) # type: ignore
super().__init__(datatype, access_mode, group, handler, **kwargs) # type: ignore

Check warning on line 169 in src/fastcs/attributes.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/attributes.py#L169

Added line #L169 was not covered by tests

async def process(self, value: T) -> None:
await self.set(value)
Expand Down
21 changes: 15 additions & 6 deletions src/fastcs/backends/epics/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from fastcs.exceptions import FastCSException
from fastcs.mapping import Mapping, SingleMapping
from fastcs.util import snake_to_pascal
from fastcs.backends.epics.utils import get_mbb_record_fields


class EpicsGUIFormat(Enum):
Expand Down Expand Up @@ -78,13 +79,21 @@ def _get_write_widget(attribute: Attribute) -> WriteWidget:
case Float():
return TextWrite()

Check warning on line 80 in src/fastcs/backends/epics/gui.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/gui.py#L79-L80

Added lines #L79 - L80 were not covered by tests
case Int():
if attribute.dropdown_mapping is None:
return TextWrite()
return ComboBox(choices=list(attribute.dropdown_mapping.keys()))
if any(
(True for kw in attribute.kwargs if kw in get_mbb_record_fields())

Check warning on line 83 in src/fastcs/backends/epics/gui.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/gui.py#L83

Added line #L83 was not covered by tests
):
choices = [
v
for k, v in attribute.kwargs.items()
if k in get_mbb_record_fields()
]
return ComboBox(choices=choices)

Check warning on line 90 in src/fastcs/backends/epics/gui.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/gui.py#L88-L90

Added lines #L88 - L90 were not covered by tests
return TextWrite()
case String():
if attribute.dropdown_mapping is None:
return TextWrite(format=TextFormat.string)
return ComboBox(choices=list(attribute.dropdown_mapping.values()))
allowed_values = attribute.kwargs.get("allowed_values", None)
if isinstance(allowed_values, list): # is not None
return ComboBox(choices=allowed_values)

Check warning on line 95 in src/fastcs/backends/epics/gui.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/gui.py#L93-L95

Added lines #L93 - L95 were not covered by tests
return TextWrite(format=TextFormat.string)
case _:
raise FastCSException(f"Unsupported type {type(datatype)}: {datatype}")

Expand Down
65 changes: 27 additions & 38 deletions src/fastcs/backends/epics/ioc.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,7 @@
from fastcs.datatypes import Bool, Float, Int, String
from fastcs.exceptions import FastCSException
from fastcs.mapping import Mapping

ENUM_ST_MAPPING = {
0: "ZRST",
1: "ONST",
2: "TWST",
3: "THST",
4: "FRST",
5: "FVST",
6: "SXST",
7: "SVST",
8: "EIST",
9: "NIST",
10: "TEST",
11: "ELST",
12: "TVST",
13: "TTST",
14: "FTST",
15: "FFST",
}
from fastcs.backends.epics.utils import get_mbb_record_fields, get_epics_record_fields


@dataclass
Expand All @@ -39,21 +21,21 @@ class EpicsIOCOptions:

def _get_input_record(pv_name: str, attribute: AttrR) -> RecordWrapper:
datatype = attribute.datatype
epics_kwargs = {

Check warning on line 24 in src/fastcs/backends/epics/ioc.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/ioc.py#L23-L24

Added lines #L23 - L24 were not covered by tests
k: v for k, v in attribute.kwargs.items() if k in get_epics_record_fields()
}
match datatype:
case Bool(znam, onam):
return builder.boolIn(pv_name, ZNAM=znam, ONAM=onam)
return builder.boolIn(pv_name, ZNAM=znam, ONAM=onam, **epics_kwargs)

Check warning on line 29 in src/fastcs/backends/epics/ioc.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/ioc.py#L29

Added line #L29 was not covered by tests
case Int():
if attribute.dropdown_mapping is None:
return builder.longIn(pv_name)
kwargs = {
ENUM_ST_MAPPING[enum_val]: enum_name
for enum_name, enum_val in attribute.dropdown_mapping.items()
}
return builder.mbbIn(pv_name, **kwargs)
# check if we need to use an mbb record
if any((True for kw in attribute.kwargs if kw in get_mbb_record_fields())):
return builder.mbbIn(pv_name, **epics_kwargs)
return builder.longIn(pv_name, **epics_kwargs)

Check warning on line 34 in src/fastcs/backends/epics/ioc.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/ioc.py#L32-L34

Added lines #L32 - L34 were not covered by tests
case Float(prec):
return builder.aIn(pv_name, PREC=prec)
return builder.aIn(pv_name, PREC=prec, **epics_kwargs)

Check warning on line 36 in src/fastcs/backends/epics/ioc.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/ioc.py#L36

Added line #L36 was not covered by tests
case String():
return builder.longStringIn(pv_name)
return builder.longStringIn(pv_name, **epics_kwargs)

Check warning on line 38 in src/fastcs/backends/epics/ioc.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/ioc.py#L38

Added line #L38 was not covered by tests
case _:
raise FastCSException(f"Unsupported type {type(datatype)}: {datatype}")

Expand All @@ -69,6 +51,9 @@ async def async_wrapper(v):

def _get_output_record(pv_name: str, attribute: AttrW, on_update: Callable) -> Any:
datatype = attribute.datatype
epics_kwargs = {

Check warning on line 54 in src/fastcs/backends/epics/ioc.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/ioc.py#L53-L54

Added lines #L53 - L54 were not covered by tests
k: v for k, v in attribute.kwargs.items() if k in get_epics_record_fields()
}
match datatype:
case Bool(znam, onam):
return builder.boolOut(
Expand All @@ -77,24 +62,28 @@ def _get_output_record(pv_name: str, attribute: AttrW, on_update: Callable) -> A
ONAM=onam,
always_update=True,
on_update=on_update,
**epics_kwargs,
)
case Int():
# check if we need to use an mbb record
if any((True for kw in attribute.kwargs if kw in get_mbb_record_fields())):
return builder.mbbOut(

Check warning on line 70 in src/fastcs/backends/epics/ioc.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/ioc.py#L69-L70

Added lines #L69 - L70 were not covered by tests
pv_name, always_update=True, on_update=on_update, **epics_kwargs
)
return builder.longIn(pv_name, **epics_kwargs)

Check warning on line 73 in src/fastcs/backends/epics/ioc.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/ioc.py#L73

Added line #L73 was not covered by tests
if attribute.dropdown_mapping is None:
return builder.longOut(pv_name, always_update=True, on_update=on_update)
kwargs = {
ENUM_ST_MAPPING[enum_val]: enum_name
for enum_name, enum_val in attribute.dropdown_mapping.items()
}
return builder.mbbOut(
pv_name, always_update=True, on_update=on_update, **kwargs
)
case Float(prec):
return builder.aOut(
pv_name, always_update=True, on_update=on_update, PREC=prec
pv_name,
always_update=True,
on_update=on_update,
PREC=prec,
**epics_kwargs,
)
case String():
return builder.longStringOut(
pv_name, always_update=True, on_update=on_update
pv_name, always_update=True, on_update=on_update, **epics_kwargs
)
case _:
raise FastCSException(f"Unsupported type {type(datatype)}: {datatype}")
Expand Down
42 changes: 42 additions & 0 deletions src/fastcs/backends/epics/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
def get_common_record_fields():
return [

Check warning on line 2 in src/fastcs/backends/epics/utils.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/utils.py#L2

Added line #L2 was not covered by tests
"SCAN",
"PINI",
"PHAS",
"EVNT",
"PRIO",
"DISV",
"DISA",
"SDIS",
"PROC",
"DISS",
"LSET",
"LCNT",
"PACT",
"FLNK",
]


def get_mbb_record_fields():
return [

Check warning on line 21 in src/fastcs/backends/epics/utils.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/utils.py#L21

Added line #L21 was not covered by tests
"ZRST",
"ONST",
"TWST",
"THST",
"FRST",
"FVST",
"SXST",
"SVST",
"EIST",
"NIST",
"TEST",
"ELST",
"TVST",
"TTST",
"FTST",
"FFST",
]


def get_epics_record_fields():
return get_common_record_fields() + get_mbb_record_fields()

Check warning on line 42 in src/fastcs/backends/epics/utils.py

View check run for this annotation

Codecov / codecov/patch

src/fastcs/backends/epics/utils.py#L42

Added line #L42 was not covered by tests

0 comments on commit 3fc0a70

Please sign in to comment.