Skip to content

Commit

Permalink
Merge pull request #125 from epics-containers/convert-template
Browse files Browse the repository at this point in the history
Add option to convert templates to Device without header
  • Loading branch information
GDYendell authored Aug 9, 2024
2 parents a8e884c + 013be18 commit 9648c5b
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 8 deletions.
48 changes: 42 additions & 6 deletions src/pvi/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,23 +107,59 @@ def device(
output: Annotated[
Path, typer.Argument(..., help="Directory to write output file to")
],
h: Annotated[Path, typer.Argument(..., help="Path to the .h file to convert")],
header: Annotated[
Optional[Path], # noqa
typer.Option(..., "--header", help="Path to the .h file to convert"),
] = None,
templates: Annotated[
Optional[list[Path]], # noqa
typer.Option(..., "--template", help="Paths to .template files to convert"),
] = None,
name: Annotated[
Optional[str], # noqa
typer.Option(
...,
help=(
"Name to use for Device. "
"This is usually the same as the EPICS driver class."
),
),
] = None,
label: Annotated[
Optional[str], # noqa
typer.Option(
...,
help=("Label for Device UI. Defaults to Device name."),
),
] = None,
parent: Annotated[
Optional[str], # noqa
typer.Option(..., help="Parent Device name."),
] = None,
):
"""Convert template to device YAML"""
templates = templates or []

if not output.exists():
os.mkdir(output)
device_name = None
parent_name = None
if header is not None:
device_name, parent_name = extract_device_and_parent_class(header.read_text())
if name is not None:
device_name = name.replace(" ", "") # No whitespace in file name
if parent is not None:
parent_name = parent
if device_name is None:
raise ValueError("Either Device name or header file must be provided.")

name, parent = extract_device_and_parent_class(h.read_text())
component_group = TemplateConverter(templates).convert()
device = Device(label=name, parent=parent, children=component_group)
device = Device(
label=label or device_name, parent=parent_name, children=component_group
)

if not output.exists():
os.mkdir(output)

device.serialize(output / f"{name}.pvi.device.yaml")
device.serialize(output / f"{device_name}.pvi.device.yaml")


@app.command()
Expand Down
3 changes: 2 additions & 1 deletion src/pvi/_schema_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def rec_subclasses(cls: Cls) -> list[Cls]:

subclasses: list[Cls] = []
for sub_cls in cls.__subclasses__():
subclasses += [sub_cls] + rec_subclasses(sub_cls)
subclasses.append(sub_cls)
subclasses.extend(rec_subclasses(sub_cls))

return subclasses
50 changes: 50 additions & 0 deletions tests/convert/input/Mako125B.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
record(ai, "$(P)$(R)GC_FirmwareVerMajor_RBV") {
field(DTYP, "asynInt64")
field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))GC_I_FirmwareVerMajor")
field(SCAN, "I/O Intr")
field(DISA, "0")
}

record(ao, "$(P)$(R)GC_FirmwareVerBuild") {
field(DTYP, "asynInt64")
field(OUT, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))GC_I_FirmwareVerBuild")
field(DISA, "0")
}

record(mbbi, "$(P)$(R)GC_SensorType_RBV") {
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))GC_E_SensorType")
field(ZRST, "Mono")
field(ZRVL, "0")
field(ONST, "Bayer")
field(ONVL, "1")
field(SCAN, "I/O Intr")
field(DISA, "0")
}

record(ai, "$(P)$(R)GC_SensorBits_RBV") {
field(DTYP, "asynInt64")
field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))GC_I_SensorBits")
field(SCAN, "I/O Intr")
field(DISA, "0")
}

record(ao, "$(P)$(R)GC_SensorBits") {
field(DTYP, "asynInt64")
field(OUT, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))GC_I_SensorBits")
field(DISA, "0")
}

record(stringin, "$(P)$(R)GC_DeviceVendorName_RBV") {
field(DTYP, "asynOctetRead")
field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))GC_S_DeviceVendorName")
field(SCAN, "I/O Intr")
field(DISA, "0")
}

record(stringin, "$(P)$(R)GC_DeviceModelName_RBV") {
field(DTYP, "asynOctetRead")
field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))GC_S_DeviceModelName")
field(SCAN, "I/O Intr")
field(DISA, "0")
}
49 changes: 49 additions & 0 deletions tests/convert/output/Mako125B.pvi.device.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
label: GenICam Mako125B
parent: GenICamDriver
children:

- type: Group
name: Mako125B
layout:
type: Grid
labelled: true
children:

- type: SignalW
name: GCFirmwareVerBuild
write_pv: $(P)$(R)GC_FirmwareVerBuild
write_widget:
type: TextWrite

- type: SignalR
name: GCFirmwareVerMajor
read_pv: $(P)$(R)GC_FirmwareVerMajor_RBV
read_widget:
type: TextRead

- type: SignalR
name: GCSensorType
read_pv: $(P)$(R)GC_SensorType_RBV
read_widget:
type: TextRead

- type: SignalR
name: GCDeviceVendorName
read_pv: $(P)$(R)GC_DeviceVendorName_RBV
read_widget:
type: TextRead

- type: SignalR
name: GCDeviceModelName
read_pv: $(P)$(R)GC_DeviceModelName_RBV
read_widget:
type: TextRead

- type: SignalRW
name: GCSensorBits
write_pv: $(P)$(R)GC_SensorBits
write_widget:
type: TextWrite
read_pv: $(P)$(R)GC_SensorBits_RBV
read_widget:
type: TextRead
22 changes: 21 additions & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,40 @@ def test_signal_default_widgets(tmp_path, helper):
)


def test_convert(tmp_path, helper):
def test_convert_header(tmp_path, helper):
expected_path = HERE / "convert" / "output"
input_path = HERE / "convert" / "input"
helper.assert_cli_output_matches(
app,
expected_path,
"convert device",
tmp_path,
"--header",
input_path / "simDetector.h",
"--template",
input_path / "simDetector.template",
)


def test_convert_device_name(tmp_path, helper):
expected_path = HERE / "convert" / "output"
input_path = HERE / "convert" / "input"
helper.assert_cli_output_matches(
app,
expected_path,
"convert device",
tmp_path,
"--name",
"Mako125B",
"--label",
"GenICam Mako125B",
"--parent",
"GenICamDriver",
"--template",
input_path / "Mako125B.template",
)


@pytest.mark.parametrize(
"input_yaml,formatter,output",
[
Expand Down

0 comments on commit 9648c5b

Please sign in to comment.