diff --git a/src/ophyd_async/core/_signal.py b/src/ophyd_async/core/_signal.py index 8cf282f463..ea42e98f1b 100644 --- a/src/ophyd_async/core/_signal.py +++ b/src/ophyd_async/core/_signal.py @@ -442,7 +442,7 @@ async def observe_value( If this status is complete, stop observing and make the iterator return. If it raises an exception then this exception will be raised by the iterator. except_after_time: - If given, the maximum time to watch a value in seconds. If the loop is still + If given, the maximum time to watch a signal, in seconds. If the loop is still being watched after this length, raise asyncio.TimeoutError. This should be used instead of on an 'asyncio.wait_for' timeout @@ -470,7 +470,6 @@ async def observe_value( def _get_iteration_timeout( timeout: float | None, overall_deadline: float | None ) -> float | None: - # Test this works if overall timeout <=0 overall_deadline = overall_deadline - time.monotonic() if overall_deadline else None return min([x for x in [overall_deadline, timeout] if x is not None], default=None) @@ -495,7 +494,7 @@ async def observe_signals_value( If this status is complete, stop observing and make the iterator return. If it raises an exception then this exception will be raised by the iterator. except_after_time: - If given, the maximum time to watch a value in seconds. If the loop is still + If given, the maximum time to watch a signal, in seconds. If the loop is still being watched after this length, raise asyncio.TimeoutError. This should be used instead of on an 'asyncio.wait_for' timeout diff --git a/tests/core/test_observe.py b/tests/core/test_observe.py index 8cd576034c..c38c85cfdf 100644 --- a/tests/core/test_observe.py +++ b/tests/core/test_observe.py @@ -60,14 +60,14 @@ async def tick(): recv = [] async def watch(): - async for val in observe_value(sig): + async for val in observe_value(sig, except_after_time=0.2): recv.append(val) t = asyncio.create_task(tick()) start = time.time() try: with pytest.raises(asyncio.TimeoutError): - await asyncio.wait_for(watch(), timeout=0.2) + await watch() assert recv == [0, 1] assert time.time() - start == pytest.approx(0.2, abs=0.05) finally: @@ -85,7 +85,7 @@ async def tick(): recv = [] async def watch(): - async for val in observe_value(sig): + async for val in observe_value(sig, except_after_time=0.2): time.sleep(0.15) recv.append(val) @@ -93,7 +93,7 @@ async def watch(): start = time.time() try: with pytest.raises(asyncio.TimeoutError): - await asyncio.wait_for(watch(), timeout=0.2) + await watch() assert recv == [0, 1] assert time.time() - start == pytest.approx(0.3, abs=0.05) finally: @@ -115,3 +115,16 @@ async def watch(except_after_time): await watch(except_after_time=0.1) assert recv assert time.time() - start == pytest.approx(0.1, abs=0.05) + + +async def test_observe_value_uses_correct_timeout(): + sig, _ = soft_signal_r_and_setter(float) + + async def watch(timeout, except_after_time): + async for _ in observe_value(sig, timeout, except_after_time=except_after_time): + ... + + start = time.time() + with pytest.raises(asyncio.TimeoutError): + await watch(timeout=0.3, except_after_time=0.15) + assert time.time() - start == pytest.approx(0.15, abs=0.05)