ophyd_async.epics.testing#
Package Contents#
Classes#
Device for use in a channel access test IOC. |
|
For testing strict enum values in test IOCs. |
|
For testing subset enum values in test IOCs. |
|
For testing superset enum values in test IOCs. |
|
Device for use in a pv access test IOC. |
|
Connects to the same served PVI tree as |
|
Device for use in a generic PVI test IOC, independent of PandA/FastCS. |
|
Connects to the same served PVI tree as |
|
Device whose |
|
Leaf sub-device for |
|
Real-IOC-backed |
|
Connects to the same served PVI tree as |
|
Real-IOC-backed structural PVI test device. |
|
Connects to the same served PVI tree as EpicsTestPviNestedDevice. |
|
An abstraction of a Table where each field is a column. |
Functions#
For generating random PV names in test devices. |
|
Start an EPICS IOC subprocess by running |
Data#
API#
- ophyd_async.epics.testing.CA_PVA_RECORDS#
None
- ophyd_async.epics.testing.IOC#
None
- ophyd_async.epics.testing.PVA_RECORDS#
None
- ophyd_async.epics.testing.PVI_NESTED_RECORDS#
None
- class ophyd_async.epics.testing.EpicsTestCaDevice(prefix: str = '', with_pvi: bool = False, name: str = '', connector: DeviceConnector | None = None)[source]#
Bases:
ophyd_async.epics.core.EpicsDeviceDevice for use in a channel access test IOC.
- enum: Annotated[SignalRW[EpicsTestEnum], PvSuffix('enum')]#
None
- enum2: Annotated[SignalRW[EpicsTestEnum], PvSuffix('enum2')]#
None
- subset_enum: Annotated[SignalRW[EpicsTestSubsetEnum], PvSuffix('subset_enum')]#
None
- superset_enum: Annotated[SignalRW[EpicsTestSupersetEnum], PvSuffix('subset_enum')]#
None
- go: Annotated[TriggerableCommand, PvSuffix('go')]#
None
- class ophyd_async.epics.testing.EpicsTestEnum[source]#
Bases:
ophyd_async.core.StrictEnumFor testing strict enum values in test IOCs.
- A#
‘Aaa’
- B#
‘Bbb’
- C#
‘Ccc’
- class ophyd_async.epics.testing.EpicsTestSubsetEnum[source]#
Bases:
ophyd_async.core.SubsetEnumFor testing subset enum values in test IOCs.
The backing PV (mbbo with choices Aaa/Bbb/Ccc) has an extra choice (“Ccc”) beyond what this enum declares.
- A#
‘Aaa’
- B#
‘Bbb’
- class ophyd_async.epics.testing.EpicsTestSupersetEnum[source]#
Bases:
ophyd_async.core.SupersetEnumFor testing superset enum values in test IOCs.
Deliberately points at the same backing PV as
EpicsTestSubsetEnum(mbbo with choices Aaa/Bbb/Ccc): this enum declares a choice (“Ddd”) that does not exist in the backend, which is exactly what a superset enum allows.- A#
‘Aaa’
- B#
‘Bbb’
- C#
‘Ccc’
- D#
‘Ddd’
- class ophyd_async.epics.testing.EpicsTestPvaDevice(prefix: str = '', with_pvi: bool = False, name: str = '', connector: DeviceConnector | None = None)[source]#
Bases:
ophyd_async.epics.testing._devices.EpicsTestCaDeviceDevice for use in a pv access test IOC.
- table: Annotated[SignalRW[EpicsTestTable], PvSuffix('table')]#
None
- class ophyd_async.epics.testing.EpicsTestPviAgreeingPvSuffixDevice(prefix: str = '', with_pvi: bool = False, name: str = '', connector: DeviceConnector | None = None)[source]#
Bases:
ophyd_async.epics.core.EpicsDeviceConnects to the same served PVI tree as
EpicsTestPviNestedDevice.Addresses its children with a
PvSuffixas well as via PVI, naming the same PVs the served tree does. PVI is the one that fills them; the annotations are only cross-checked against it, so connecting succeeds. Construct withwith_pvi=True.- child: Annotated[EpicsTestPviLeafDevice, PvSuffix('child:')]#
None
- class ophyd_async.epics.testing.EpicsTestPviDevice(prefix: str = '', with_pvi: bool = False, name: str = '', connector: DeviceConnector | None = None)[source]#
Bases:
ophyd_async.epics.core.EpicsDeviceDevice for use in a generic PVI test IOC, independent of PandA/FastCS.
Construct with
with_pvi=True: signals here are plain type annotations with noPvSuffix, discovered and filled in from the IOC’s PVI structure byPviDeviceConnectorat connect time.Most fields (
mbb_direct_bit_r,a_float,table,ntndarray,go) reuse the same attribute names, PVI entries and backing records asEpicsTestCaDevice/EpicsTestPvaDevice, rather than declaring new synthetic ones. Onlywo_floatis bespoke to this device, as no write-only field exists on those devices to reuse.- table: SignalRW[EpicsTestTable]#
None
- go: TriggerableCommand#
None
- class ophyd_async.epics.testing.EpicsTestPviDisagreeingDeviceDevice(prefix: str = '', with_pvi: bool = False, name: str = '', connector: DeviceConnector | None = None)[source]#
Bases:
ophyd_async.epics.core.EpicsDeviceConnects to the same served PVI tree as
EpicsTestPviNestedDevice.Gives
childaPvSuffixnaming a different PVI PV to the served one, so connecting must raise rather than silently take PVI’s. The sub-device counterpart ofEpicsTestPviDisagreeingSuffixDevice, which covers a disagreeing Signal. Construct withwith_pvi=True.- child: Annotated[EpicsTestPviLeafDevice, PvSuffix('not_child:')]#
None
- class ophyd_async.epics.testing.EpicsTestPviDisagreeingSuffixDevice(prefix: str = '', with_pvi: bool = False, name: str = '', connector: DeviceConnector | None = None)[source]#
Bases:
ophyd_async.epics.core.EpicsDeviceDevice whose
PvSuffixcontradicts the PVI structure serving it.overridden_floatis annotated at thefloat_prec_1record, but the IOC’s PVI directory points it at the same record asa_float. Two different PVs for one Signal means one of them is wrong, so connecting must raise rather than silently pick either. Construct withwith_pvi=True.It is a device of its own because it cannot connect: a disagreeing Signal would otherwise stop
EpicsTestPviDeviceconnecting at all.
- class ophyd_async.epics.testing.EpicsTestPviLeafDevice(name: str = '', connector: DeviceConnector | None = None)[source]#
Bases:
ophyd_async.core.DeviceLeaf sub-device for
childanddevice_vectoron EpicsTestPviNestedDevice.- signal_x: TriggerableCommand#
None
- class ophyd_async.epics.testing.EpicsTestPviMapDevice(prefix: str = '', with_pvi: bool = False, name: str = '', connector: DeviceConnector | None = None)[source]#
Bases:
ophyd_async.epics.core.EpicsDeviceReal-IOC-backed
DeviceMaptest device, served under themapd:group.Proves that a
DeviceMapis created only from an explicitDeviceMap[...]annotation and filled from a node’s normal named entries, keyed by name (signal_map->{"a", "b"},device_map->{"one", "two"}), with each entry type-checked against the map’s element type – the counterpart toEpicsTestPviNestedDevice’s integer-keyedDeviceVectors. Construct withwith_pvi=Trueand a prefix endingmapd:.- device_map: DeviceMap[EpicsTestPviLeafDevice]#
None
- class ophyd_async.epics.testing.EpicsTestPviMapOverVectorDevice(prefix: str = '', with_pvi: bool = False, name: str = '', connector: DeviceConnector | None = None)[source]#
Bases:
ophyd_async.epics.core.EpicsDeviceConnects to the same served PVI tree as
EpicsTestPviNestedDevice.Annotates
device_vector– which PVI serves as integer-keyed “__N” entries – as aDeviceMap. ADeviceMapcan only hold the named entries of a node, so its “__N” children have nowhere to go and connecting must raise rather than yield a map that has silently dropped them. Construct withwith_pvi=True.- device_vector: DeviceMap[EpicsTestPviLeafDevice]#
None
- class ophyd_async.epics.testing.EpicsTestPviNestedDevice(prefix: str = '', with_pvi: bool = False, name: str = '', connector: DeviceConnector | None = None)[source]#
Bases:
ophyd_async.epics.core.EpicsDeviceReal-IOC-backed structural PVI test device.
Exercises PviDeviceConnector’s handling of nested sub-devices, DeviceVector of devices, DeviceVector of signals, DeviceVector of commands, and an Optional signal absent from the served tree – the structural mechanics that tests/unit_tests/epics/pvi/test_pvi.py’s Block1-Block5 classes exercise only against a mocked PVI tree. Construct with
with_pvi=True.The served PVI tree also includes an
extra_devicesDeviceVector that is deliberately not annotated here, to prove that PviDeviceConnector fills in undeclared DeviceVectors of devices dynamically.Legacy list-based vector encoding (
PviTree._handle_legacy_entry) is deliberately not covered here: it’s exclusively produced by pandablocks-ioc’s own hand-rolled PVA server, not something a QSRV2/db-file-based IOC can construct declaratively, so it stays covered by the existing mock-only unit test instead.- signal_x: TriggerableCommand#
None
- child: EpicsTestPviLeafDevice#
None
- device_vector: DeviceVector[EpicsTestPviLeafDevice]#
None
- signal_vector: DeviceVector[SignalRW[float]]#
None
- command_vector: DeviceVector[TriggerableCommand]#
None
- class ophyd_async.epics.testing.EpicsTestPviNestedDeviceMissingChild(prefix: str = '', with_pvi: bool = False, name: str = '', connector: DeviceConnector | None = None)[source]#
Bases:
ophyd_async.epics.core.EpicsDeviceConnects to the same served PVI tree as EpicsTestPviNestedDevice.
Declares an extra required (non-Optional) sub-device the server doesn’t actually provide – demonstrates that connecting raises a clear RuntimeError when a required field can’t be resolved via PVI (the mirror image of
optional_signalabove, which is allowed to be absent).- missing_child: EpicsTestPviLeafDevice#
None
- class ophyd_async.epics.testing.EpicsTestTable(**kwargs)[source]#
Bases:
ophyd_async.core.TableAn abstraction of a Table where each field is a column.
For example:
>>> from ophyd_async.core import Table, Array1D >>> import numpy as np >>> from collections.abc import Sequence >>> class MyTable(Table): ... a: Array1D[np.int8] ... b: Sequence[str] ... >>> t = MyTable(a=[1, 2], b=["x", "y"]) >>> len(t) # the length is the number of rows 2 >>> t2 = t + t # adding tables together concatenates them >>> t2.a array([1, 2, 1, 2], dtype=int8) >>> t2.b ['x', 'y', 'x', 'y'] >>> t2[1] # slice a row array([(2, b'y')], dtype=[('a', 'i1'), ('b', 'S40')])
- a_enum: Sequence[EpicsTestEnum]#
None
- ophyd_async.epics.testing.generate_random_pv_prefix() str[source]#
For generating random PV names in test devices.
- ophyd_async.epics.testing.start_ioc(script: Path, *args: str) ManagedSubprocess[source]#
Start an EPICS IOC subprocess by running
scriptwithargs.Mirrors
ophyd_async.tango.testing.start_tango_device_servers’s shape and subprocess handling: rather than building the IOC’s full argv inline, this always launches a real, independently-runnable file - the exact command a human would type by hand, so there’s no separate “does this even work standalone” code path to keep correct.- Parameters:
script – The script implementing the IOC topology to host, e.g.
ophyd_async.epics.demo.IOCorophyd_async.epics.testing.IOC.args – Positional args for that script’s
__main__, e.g.prefixorprefix, str(num_channels)- whatever it expects. Overriding which executable actually hosts the IOC (defaulting to the bundledepicscorelibs.ioc) is a command-line-only concern of that script itself - pass--softioc ...as one ofargsif you need that (see the script’s own--help); this function doesn’t thread it through.