Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions qtm_rt/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,13 @@ async def await_event(self, event=None, timeout=None):
if self.event_future is not None:
raise Exception("Can't wait on multiple events!")

result = await asyncio.wait_for(self._wait_loop(event), timeout)
return result
try:
return await asyncio.wait_for(self._wait_loop(event), timeout)
finally:
# On timeout/cancellation the future is still queued and pending.
# Clear it so the next await_event isn't blocked by stale state.
# On success _on_event already cleared it; assignment is a no-op.
self.event_future = None

def send_command(
self, command, callback=True, command_type=QRTPacketType.PacketCommand
Expand Down
16 changes: 16 additions & 0 deletions test/qtmprotocol_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ async def test_await_any_event_timeout(qtmprotocol: QTMProtocol):
await awaitable


@pytest.mark.asyncio
async def test_await_event_after_timeout(qtmprotocol: QTMProtocol):
# First call times out — previously this left event_future set, which made
# the next await_event raise "Can't wait on multiple events!" even though
# nothing was actually being awaited.
with pytest.raises(asyncio.TimeoutError):
await qtmprotocol.await_event(timeout=0.05)

# Second call must succeed; event_future was cleared on the timeout path.
awaitable = qtmprotocol.await_event(timeout=1)
asyncio.get_running_loop().call_later(
0, lambda: qtmprotocol._on_event(QRTEvent.EventConnected)
)
assert await awaitable == QRTEvent.EventConnected


@pytest.mark.asyncio
async def test_await_any_event(qtmprotocol: QTMProtocol):
awaitable = qtmprotocol.await_event(timeout=1)
Expand Down