async def test_awaitables_are_cancelled_and_cleaned_up_on_outer_cancellation(): token = CancelToken('token') ready = asyncio.Event() got_cancelation = asyncio.Event() async def _signal_then_sleep(): ready.set() try: await asyncio.sleep(10) except asyncio.CancelledError: got_cancelation.set() raise fut = asyncio.ensure_future(_signal_then_sleep()) task = asyncio.ensure_future(token.cancellable_wait(fut)) # wait till we know the coro is running await ready.wait() # cancel the task task.cancel() try: await task except asyncio.CancelledError: pass # ensure that the task was indeed cancelled. await asyncio.wait_for(got_cancelation.wait(), timeout=0.01) await assert_only_current_task_not_done()
async def test_cancellable_wait_cancels_subtasks_when_cancelled(event_loop): token = CancelToken('') future = asyncio.ensure_future(token.cancellable_wait(asyncio.sleep(2))) with pytest.raises(asyncio.TimeoutError): # asyncio.wait_for() will timeout and then cancel our cancellable_wait() future, but # Task.cancel() doesn't immediately cancels the task # (https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel), so we need # the sleep below before we check that the task is actually cancelled. await asyncio.wait_for(future, timeout=0.01) await asyncio.sleep(0) assert future.cancelled() await assert_only_current_task_not_done()
async def test_finished_task_with_exceptions_is_raised_on_cancellation(): token = CancelToken('token') ready = asyncio.Event() async def _signal_then_raise(): ready.set() raise ValueError("raising from _signal_then_raise") # schedule in the background task = asyncio.ensure_future(token.cancellable_wait(_signal_then_raise())) # wait until the coro is running and we know it's raised an error await ready.wait() # trigger the cancel token token.trigger() with pytest.raises(ValueError, match="raising from _signal_then_raise"): await task await assert_only_current_task_not_done()