Releases: bluesky/ophyd-async
v0.9.0a1
Changes
mock_puts_blocked
is now sync rather than async
# old
async with mock_puts_blocked(sig):
...
# old
with mock_puts_blocked(sig):
...
All enums are now uppercase, and StrictEnum
and SubsetEnum
subclasses enforce this.
# old
trigger_mode = DetectorTrigger.internal
image_mode = adcore.ImageMode.multiple
# new
trigger_mode = DetectorTrigger.INTERNAL
image_mode = adcore.ImageMode.MULTIPLE
Testing utils moved to ophyd_async.testing
The following have moved to ophyd_async.testing
and should be imported from there:
- assert_configuration
- assert_emitted
- assert_reading
- assert_value
- callback_on_mock_put
- get_mock
- get_mock_put
- mock_puts_blocked
- reset_mock_put_calls
- set_mock_put_proceeds
- set_mock_value
- set_mock_values
- wait_for_pending_wakeups
# old
from ophyd_async.core import set_mock_value
# new
from ophyd_async.testing import set_mock_value
What's Changed
- Make mock_puts_blocked a sync contextmanager as it doesn't do any async things by @coretl in #672
- Update all Enums to UPPER_CASE across the code base by @jennmald in #673
- Add a hint to PandA if we can't find a block by @coretl in #668
- Make name separator configurable by @coretl in #675
- Prevent issues with writing data with software scans by @DiamondJoseph in #685
- Add new timeout for observe_value by @coretl in #650
- Ensure motors can be stopped by @Tom-Willemsen in #688
- adjusted tests to avoid
pytest.approx
bool
comparison by @evalott100 in #689 - Remove mailmap by @coretl in #690
- Allow for fields w/
epics_signal_rw_rbv
, also support long strings/waveforms with PVA backend. by @jwlodek in #682 - Add Python 3.12 to CI now that p4p is updated by @OCopping in #655
- fixed bad logic introducted to
test_observe
by @evalott100 in #692 - Fix SimMotor watcher output direction by @coretl in #670
- Move testing utils from core to testing by @coretl in #695
- Update copier template to 2.6.0 by @coretl in #698
- Faster tango tests by @jsouter in #684
New Contributors
Full Changelog: v0.8.0...v0.9.0a1
v0.8.0
Breaking changes
pvi structure changes
Structure now read from .value
rather than .pvi
and includes DeviceVector
support. Supported in FastCS. Requires at least PandABlocks-ioc 0.11.4
set_and_wait_for_value
changes
Some keyword argument changes to observe_value
and set_and_wait_for_value
. There is a new argument to set_and_wait_for_value
, it now has a wait_for_set_completion
argument with default of True
. This is a change in behaviour to before where it would not wait for the set to complete before returning the Status
, however it is the desired behaviour in the majority of cases. If using with areaDetector then supply wait_for_set_completion=False
as per the docs
Epics signal
module moves
ophyd_async.epics.signal
moves to ophyd_async.epics.core
with a backwards compat module that emits deprecation warning.
# old
from ophyd_async.epics.signal import epics_signal_rw
# new
from ophyd_async.epics.core import epics_signal_rw
StandardReadable
wrappers change to StandardReadableFormat
StandardReadable
wrappers change to enum members of StandardReadableFormat
(normally imported as Format
)
# old
from ophyd_async.core import ConfigSignal, HintedSignal
class MyDevice(StandardReadable):
def __init__(self):
self.add_readables([sig1], ConfigSignal)
self.add_readables([sig2], HintedSignal)
self.add_readables([sig3], HintedSignal.uncached)
# new
from ophyd_async.core import StandardReadableFormat as Format
class MyDevice(StandardReadable):
def __init__(self):
self.add_readables([sig1], Format.CONFIG_SIGNAL)
self.add_readables([sig2], Format.HINTED_SIGNAL)
self.add_readables([sig3], Format.HINTED_UNCACHED_SIGNAL
Declarative Devices are now available
# old
from ophyd_async.core import ConfigSignal, HintedSignal
from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw
class Sensor(StandardReadable):
def __init__(self, prefix: str, name="") -> None:
with self.add_children_as_readables(HintedSignal):
self.value = epics_signal_r(float, prefix + "Value")
with self.add_children_as_readables(ConfigSignal):
self.mode = epics_signal_rw(EnergyMode, prefix + "Mode")
super().__init__(name=name)
# new
from typing import Annotated as A
from ophyd_async.core import StandardReadableFormat as Format
from ophyd_async.epics.core import EpicsDevice, PvSuffix, epics_signal_r, epics_signal_rw
class Sensor(StandardReadable, EpicsDevice):
value: A[SignalR[float], PvSuffix("Value"), Format.HINTED_SIGNAL]
mode: A[SignalRW[EnergyMode], PvSuffix("Mode"), Format.CONFIG_SIGNAL]
StrictEnum
is now requried for all strictly checked Enums
# old
from enum import Enum
class MyEnum(str, Enum):
ONE = "one"
TWO = "two"
# new
from ophyd_async.core import StrictEnum
class MyEnum(StrictEnum):
ONE = "one"
TWO = "two"
SubsetEnum
is now an Enum
subclass:
from ophyd_async.core import SubsetEnum
# old
MySubsetEnum = SubsetEnum["one", "two"]
# new
class MySubsetEnum(SubsetEnum):
ONE = "one"
TWO = "two"
Use python primitives for scalar types instead of numpy types
# old
import numpy as np
x = epics_signal_rw(np.int32, "PV")
# new
x = epics_signal_rw(int, "PV")
Use Array1D
for 1D arrays instead of npt.NDArray
import numpy as np
# old
import numpy.typing as npt
x = epics_signal_rw(npt.NDArray[np.int32], "PV")
# new
from ophyd_async.core import Array1D
x = epics_signal_rw(Array1D[np.int32], "PV")
Use Sequence[str]
for arrays of strings instead of npt.NDArray[np.str_]
import numpy as np
# old
import numpy.typing as npt
x = epics_signal_rw(npt.NDArray[np.str_], "PV")
# new
from collections.abc import Sequence
x = epics_signal_rw(Sequence[str], "PV")
MockSignalBackend
requires a real backend
# old
fake_set_signal = SignalRW(MockSignalBackend(float))
# new
fake_set_signal = soft_signal_rw(float)
await fake_set_signal.connect(mock=True)
get_mock_put
is no longer passed timeout as it is handled in Signal
# old
get_mock_put(driver.capture).assert_called_once_with(Writing.ON, wait=ANY, timeout=ANY)
# new
get_mock_put(driver.capture).assert_called_once_with(Writing.ON, wait=ANY)
super().__init__
required for Device
subclasses
# old
class MyDevice(Device):
def __init__(self, name: str = ""):
self.signal, self.backend_put = soft_signal_r_and_setter(int)
# new
class MyDevice(Device):
def __init__(self, name: str = ""):
self.signal, self.backend_put = soft_signal_r_and_setter(int)
super().__init__(name=name)
Arbitrary BaseModel
s not supported, pending use cases for them
The Table
type has been suitable for everything we have seen so far, if you need an arbitrary BaseModel
subclass then please make an issue
Child Device
s set parent on attach, and can't be public children of more than one parent
class SourceDevice(Device):
def __init__(self, name: str = ""):
self.signal = soft_signal_rw(int)
super().__init__(name=name)
# old
class ReferenceDevice(Device):
def __init__(self, signal: SignalRW[int], name: str = ""):
self.signal = signal
super().__init__(name=name)
def set(self, value) -> AsyncStatus:
return self.signal.set(value + 1)
# new
from ophyd_async.core import Reference
class ReferenceDevice(Device):
def __init__(self, signal: SignalRW[int], name: str = ""):
self._signal_ref = Reference(signal)
super().__init__(name=name)
def set(self, value) -> AsyncStatus:
return self._signal_ref().set(value + 1)
What's Changed
- Add test for context race condition by @DominicOram in #600
- New signal typing by @coretl in #594
- Update copier template to 2.4.0 by @coretl in #628
- Logo by @coretl in #629
- Allow CA/PVA mismatching enums to be bools by @coretl in #632
- Allow shared parent mock to be passed to Device.connect by @jsouter in #599
- Report Device name in error when using AsyncStatus.wrap by @jsouter in #607
- Temporary fix for PyPI publishing by @coretl in #634
- Windows: fix unit tests & enable CI by @Tom-Willemsen in #633
- Declarative EPICS and StandardReadable Devices by @coretl in #598
- Update to copier 2.5.0 by @coretl in #637
- Speed up device creation and connection in mock mode by @coretl in #641
- Set parent of children of DeviceVector passed at init by @coretl in #644
- Fix some small issues discovered in testing by @coretl in #646
- Yield in each loop of observe_value by @coretl in #648
- Add introspection of the errors that make up NotConnected by @coretl in #649
- Rename hdf5_type to data_type in DatasetTable by @jwlodek in #651
- Fix wrong function call name for str waveform that causes issue when … by @DiamondJoseph in #653
- wait_for_value_interface_change by @ZohebShaikh in #652
- Fix type hints and error messages in tests caused by pydantic update by @coretl in #665
- FIX: Handle NonSupportedFeature exception for pipes by @burkeds in #660
- Change tango decorators to Annotations by @coretl in #658
- Restructure epics/test_signals.py by @jsouter in #630
- Add the python package and the config and make the contracts kept by @stan-dot in #669
- Add missing space in log message by @jwlodek in #676
Full Changelog: v0.7.0...v0.8.0
v0.8.0a6
What's Changed
- wait_for_value_interface_change by @ZohebShaikh in #652
- Fix type hints and error messages in tests caused by pydantic update by @coretl in #665
- FIX: Handle NonSupportedFeature exception for pipes by @burkeds in #660
- Change tango decorators to Annotations by @coretl in #658
- Restructure epics/test_signals.py by @jsouter in #630
Changes
set_and_wait_for_value
changes
Some keyword argument changes to observe_value
and set_and_wait_for_value
. There is a new argument to set_and_wait_for_value
, it now has a wait_for_set_completion
argument with default of True
. This is a change in behaviour to before where it would not wait for the set to complete before returning the Status
, however it is the desired behaviour in the majority of cases. If using with areaDetector then supply wait_for_set_completion=False
as per the docs
Full Changelog: v0.8.0a5...v0.8.0a6
v0.8.0a5
What's Changed
- Set parent of children of DeviceVector passed at init by @coretl in #644
- Fix some small issues discovered in testing by @coretl in #646
- Yield in each loop of observe_value by @coretl in #648
- Add introspection of the errors that make up NotConnected by @coretl in #649
- Rename hdf5_type to data_type in DatasetTable by @jwlodek in #651
- Fix wrong function call name for str waveform that causes issue when … by @DiamondJoseph in #653
Full Changelog: v0.8.0a4...v0.8.0a5
v0.8.0a4
v0.8.0a3
What's Changed
- Windows: fix unit tests & enable CI by @Tom-Willemsen in #633
- Declarative EPICS and StandardReadable Devices by @coretl in #598
Changes
pvi structure changes
Structure read from .value
now includes DeviceVector
support. Requires at least PandABlocks-ioc 0.11.2
Epics signal
module moves
ophyd_async.epics.signal
moves to ophyd_async.epics.core
with a backwards compat module that emits deprecation warning.
# old
from ophyd_async.epics.signal import epics_signal_rw
# new
from ophyd_async.epics.core import epics_signal_rw
StandardReadable
wrappers change to StandardReadableFormat
StandardReadable
wrappers change to enum members of StandardReadableFormat
(normally imported as Format
)
# old
from ophyd_async.core import ConfigSignal, HintedSignal
class MyDevice(StandardReadable):
def __init__(self):
self.add_readables([sig1], ConfigSignal)
self.add_readables([sig2], HintedSignal)
self.add_readables([sig3], HintedSignal.uncached)
# new
from ophyd_async.core import StandardReadableFormat as Format
class MyDevice(StandardReadable):
def __init__(self):
self.add_readables([sig1], Format.CONFIG_SIGNAL)
self.add_readables([sig2], Format.HINTED_SIGNAL)
self.add_readables([sig3], Format.HINTED_UNCACHED_SIGNAL
Declarative Devices are now available
# old
from ophyd_async.core import ConfigSignal, HintedSignal
from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw
class Sensor(StandardReadable):
def __init__(self, prefix: str, name="") -> None:
with self.add_children_as_readables(HintedSignal):
self.value = epics_signal_r(float, prefix + "Value")
with self.add_children_as_readables(ConfigSignal):
self.mode = epics_signal_rw(EnergyMode, prefix + "Mode")
super().__init__(name=name)
# new
from typing import Annotated as A
from ophyd_async.core import StandardReadableFormat as Format
from ophyd_async.epics.core import EpicsDevice, PvSuffix, epics_signal_r, epics_signal_rw
class Sensor(StandardReadable, EpicsDevice):
value: A[SignalR[float], PvSuffix("Value"), Format.HINTED_SIGNAL]
mode: A[SignalRW[EnergyMode], PvSuffix("Mode"), Format.CONFIG_SIGNAL]
Full Changelog: v0.8.0a2...v0.8.0a3
v0.8.0a2
What's Changed
- Allow CA/PVA mismatching enums to be bools by @coretl in #632
- Allow shared parent mock to be passed to Device.connect by @jsouter in #599
- Report Device name in error when using AsyncStatus.wrap by @jsouter in #607
- Temporary fix for PyPI publishing by @coretl in #634
Full Changelog: v0.8.0a1...v0.8.0a2
v0.8.0a1
What's Changed
- Add test for context race condition by @DominicOram in #600
- New signal typing by @coretl in #594
- Update copier template to 2.4.0 by @coretl in #628
- Logo by @coretl in #629
Breaking changes
pvi structure changes
Structure now read from .value
rather than .pvi
. Supported in FastCS. Requires at least PandABlocks-ioc 0.10.0
StrictEnum
is now requried for all strictly checked Enums
# old
from enum import Enum
class MyEnum(str, Enum):
ONE = "one"
TWO = "two"
# new
from ophyd_async.core import StrictEnum
class MyEnum(StrictEnum):
ONE = "one"
TWO = "two"
SubsetEnum
is now an Enum
subclass:
from ophyd_async.core import SubsetEnum
# old
MySubsetEnum = SubsetEnum["one", "two"]
# new
class MySubsetEnum(SubsetEnum):
ONE = "one"
TWO = "two"
Use python primitives for scalar types instead of numpy types
# old
import numpy as np
x = epics_signal_rw(np.int32, "PV")
# new
x = epics_signal_rw(int, "PV")
Use Array1D
for 1D arrays instead of npt.NDArray
import numpy as np
# old
import numpy.typing as npt
x = epics_signal_rw(npt.NDArray[np.int32], "PV")
# new
from ophyd_async.core import Array1D
x = epics_signal_rw(Array1D[np.int32], "PV")
Use Sequence[str]
for arrays of strings instead of npt.NDArray[np.str_]
import numpy as np
# old
import numpy.typing as npt
x = epics_signal_rw(npt.NDArray[np.str_], "PV")
# new
from collections.abc import Sequence
x = epics_signal_rw(Sequence[str], "PV")
MockSignalBackend
requires a real backend
# old
fake_set_signal = SignalRW(MockSignalBackend(float))
# new
fake_set_signal = soft_signal_rw(float)
await fake_set_signal.connect(mock=True)
get_mock_put
is no longer passed timeout as it is handled in Signal
# old
get_mock_put(driver.capture).assert_called_once_with(Writing.ON, wait=ANY, timeout=ANY)
# new
get_mock_put(driver.capture).assert_called_once_with(Writing.ON, wait=ANY)
super().__init__
required for Device
subclasses
# old
class MyDevice(Device):
def __init__(self, name: str = ""):
self.signal, self.backend_put = soft_signal_r_and_setter(int)
# new
class MyDevice(Device):
def __init__(self, name: str = ""):
self.signal, self.backend_put = soft_signal_r_and_setter(int)
super().__init__(name=name)
Arbitrary BaseModel
s not supported, pending use cases for them
The Table
type has been suitable for everything we have seen so far, if you need an arbitrary BaseModel
subclass then please make an issue
Child Device
s set parent on attach, and can't be public children of more than one parent
class SourceDevice(Device):
def __init__(self, name: str = ""):
self.signal = soft_signal_rw(int)
super().__init__(name=name)
# old
class ReferenceDevice(Device):
def __init__(self, signal: SignalRW[int], name: str = ""):
self.signal = signal
super().__init__(name=name)
def set(self, value) -> AsyncStatus:
return self.signal.set(value + 1)
# new
from ophyd_async.core import Reference
class ReferenceDevice(Device):
def __init__(self, signal: SignalRW[int], name: str = ""):
self._signal_ref = Reference(signal)
super().__init__(name=name)
def set(self, value) -> AsyncStatus:
return self._signal_ref().set(value + 1)
Full Changelog: v0.7.0...v0.8.0a1
v0.7.0
What's Changed
- fixed typos by @ZohebShaikh in #589
- Make table subclass enums be sequence enum rather than numpy string by @evalott100 in #579
- Reset completed iterations counter to 0 once target iterations are reached and detector is disarmed by @jwlodek in #590
- Simplify ad standard det tests by @jwlodek in #592
- Remove config sigs kwarg from flyer since use case for them was unclear. by @jwlodek in #593
- added number_of_frames instead of iterations by @ZohebShaikh in #581
- Rename core classes by @abbiemery in #577
- Tango support by @burkeds in #437
- add Capture mode signal to Panda DataBlock by @jsouter in #604
- with DeviceCollector doesn't work in plans, so error rather than hang by @coretl in #612
New Contributors
Full Changelog: v0.6.0...v0.7.0
v0.7.0a1
What's Changed
- fixed typos by @ZohebShaikh in #589
- Make table subclass enums be sequence enum rather than numpy string by @evalott100 in #579
- Reset completed iterations counter to 0 once target iterations are reached and detector is disarmed by @jwlodek in #590
- Simplify ad standard det tests by @jwlodek in #592
- Remove config sigs kwarg from flyer since use case for them was unclear. by @jwlodek in #593
- added number_of_frames instead of iterations by @ZohebShaikh in #581
- Rename core classes by @abbiemery in #577
- Tango support by @burkeds in #437
New Contributors
Full Changelog: v0.6.0...v0.7.0a1