From 3e74761b76f337bf0e36dcdbdd7fdc0dd814105b Mon Sep 17 00:00:00 2001 From: "Tom C (DLS)" <101418278+coretl@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:14:08 +0100 Subject: [PATCH 1/2] with DeviceCollector doesn't work in plans, so error rather than hang (#612) --- src/ophyd_async/core/_device.py | 7 ++++++- tests/core/test_device_collector.py | 10 ++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ophyd_async/core/_device.py b/src/ophyd_async/core/_device.py index b4305c2bfa..bf3e23f5d6 100644 --- a/src/ophyd_async/core/_device.py +++ b/src/ophyd_async/core/_device.py @@ -12,7 +12,7 @@ ) from bluesky.protocols import HasName -from bluesky.run_engine import call_in_bluesky_event_loop +from bluesky.run_engine import call_in_bluesky_event_loop, in_bluesky_event_loop from ._utils import DEFAULT_TIMEOUT, NotConnected, wait_for_connection @@ -224,6 +224,11 @@ async def __aexit__(self, type, value, traceback): await self._on_exit() def __exit__(self, type_, value, traceback): + if in_bluesky_event_loop(): + raise RuntimeError( + "Cannot use DeviceConnector inside a plan, instead use " + "`yield from ophyd_async.plan_stubs.ensure_connected(device)`" + ) self._objects_on_exit = self._caller_locals() try: fut = call_in_bluesky_event_loop(self._on_exit()) diff --git a/tests/core/test_device_collector.py b/tests/core/test_device_collector.py index efebc6a48f..cdb6e122c5 100644 --- a/tests/core/test_device_collector.py +++ b/tests/core/test_device_collector.py @@ -67,6 +67,16 @@ def test_sync_device_connector_run_engine_created_connects(RE): assert working_device.connected +def test_connecting_in_plan_raises(RE): + def bad_plan(): + yield from bps.null() + with DeviceCollector(): + working_device = WorkingDevice("somename") # noqa: F841 + + with pytest.raises(RuntimeError, match="Cannot use DeviceConnector inside a plan"): + RE(bad_plan()) + + def test_async_device_connector_run_engine_same_event_loop(): async def set_up_device(): async with DeviceCollector(mock=True): From c91d2831d95df8c8f23e85f7f18686362f5e8922 Mon Sep 17 00:00:00 2001 From: Dominic Oram Date: Tue, 29 Oct 2024 13:45:17 +0000 Subject: [PATCH 2/2] Add test for context race condition (#600) * Add test for context race condition * Add timeout to wait on connection in test --- tests/epics/signal/test_signals.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/epics/signal/test_signals.py b/tests/epics/signal/test_signals.py index e2e5c20f7d..0ce7fd6b45 100644 --- a/tests/epics/signal/test_signals.py +++ b/tests/epics/signal/test_signals.py @@ -14,12 +14,15 @@ from typing import Any, Literal from unittest.mock import ANY +import bluesky.plan_stubs as bps import numpy as np import numpy.typing as npt import pytest from aioca import CANothing, purge_channel_caches from bluesky.protocols import Reading +from bluesky.run_engine import RunEngine from event_model import DataKey +from ophyd.signal import EpicsSignal from typing_extensions import TypedDict from ophyd_async.core import ( @@ -917,3 +920,21 @@ async def test_signals_created_for_not_prec_0_float_cannot_use_int(ioc: IOC): TypeError, match=f"{ioc.protocol}:float_prec_1 has type float not int" ): await sig.connect() + + +async def test_can_read_using_ophyd_async_then_ophyd(ioc: IOC): + oa_read = f"{ioc.protocol}://{PV_PREFIX}:{ioc.protocol}:float_prec_1" + ophyd_read = f"{PV_PREFIX}:{ioc.protocol}:float_prec_0" + + ophyd_async_sig = epics_signal_rw(float, oa_read) + await ophyd_async_sig.connect() + ophyd_signal = EpicsSignal(ophyd_read) + ophyd_signal.wait_for_connection(timeout=5) + + RE = RunEngine() + + def my_plan(): + yield from bps.rd(ophyd_async_sig) + yield from bps.rd(ophyd_signal) + + RE(my_plan())