async def main(ctx): from asyncgui.structured_concurrency import or_ task_a = ag.Task(child_a(ctx)) task_b = ctx['task_b'] = ag.Task(child_b(ctx)) task_c = ag.Task(child_c(ctx)) if n_exceptions == 1: with pytest.raises(ZeroDivisionError): await or_(task_a, task_b, task_c) elif n_exceptions: with pytest.raises(ag.MultiError) as excinfo: await or_(task_a, task_b, task_c) assert [ZeroDivisionError, ] * n_exceptions == \ [type(e) for e in excinfo.value.exceptions] else: await or_(task_a, task_b, task_c)
def test_nested_cancel_protection(): import asyncgui as ag async def outer_fn(e): async with ag.cancel_protection(): await inner_fn(e) await ag.sleep_forever() pytest.fail("Failed to cancel") async def inner_fn(e): assert task._cancel_protection == 1 async with ag.cancel_protection(): assert task._cancel_protection == 2 await e.wait() assert task._cancel_protection == 1 e = ag.Event() task = ag.Task(outer_fn(e)) assert task._cancel_protection == 0 ag.start(task) assert task._cancel_protection == 2 task.cancel() assert not task.cancelled assert not task._is_cancellable e.set() assert task._cancel_protection == 0 assert task.cancelled
def test_nested(set_immediately_1, set_immediately_2): import asyncgui as ag TS = ag.TaskState e1 = ag.Event() e2 = ag.Event() if set_immediately_1: e1.set() if set_immediately_2: e2.set() main_task = ag.Task(main(e1, e2)) ag.start(main_task) main_task.cancel() if set_immediately_1 and set_immediately_2: # 中断の機会を与えられずに終わる為 DONE assert main_task.state is TS.DONE return assert main_task.state is TS.STARTED if set_immediately_1 or set_immediately_2: e1.set() e2.set() assert main_task.state is TS.CANCELLED return e1.set() assert main_task.state is TS.STARTED e2.set() assert main_task.state is TS.CANCELLED
def test_the_state_and_the_result__ver_cancel(): job_state = 'A' async def job(): nonlocal job_state job_state = 'B' await ag.sleep_forever() job_state = 'C' return 'result' task = ag.Task(job(), name='pytest') root_coro = task.root_coro assert task.state is TS.CREATED assert task._exception is None assert job_state == 'A' with pytest.raises(ag.InvalidStateError): task.result ag.start(task) assert task.state is TS.STARTED assert task._exception is None assert job_state == 'B' with pytest.raises(ag.InvalidStateError): task.result root_coro.close() assert task.state is TS.CANCELLED assert task._exception is None assert not task.done assert task.cancelled with pytest.raises(ag.InvalidStateError): task.result
def test_the_state_and_the_result__ver_uncaught_exception_2(): '''coro.throw()によって例外を起こした場合''' job_state = 'A' async def job(): nonlocal job_state job_state = 'B' await ag.sleep_forever() job_state = 'C' return 'result' task = ag.Task(job(), name='pytest') root_coro = task.root_coro assert task.state is TS.CREATED assert task._exception is None assert job_state == 'A' with pytest.raises(ag.InvalidStateError): task.result ag.start(task) assert task.state is TS.STARTED assert task._exception is None assert job_state == 'B' with pytest.raises(ag.InvalidStateError): task.result with pytest.raises(ZeroDivisionError): root_coro.throw(ZeroDivisionError) assert task.state is TS.CANCELLED assert task._exception is None job_state = 'B' assert not task.done assert task.cancelled with pytest.raises(ag.InvalidStateError): task.result
def test_the_state_and_the_result(): job_state = 'A' async def job(): nonlocal job_state job_state = 'B' await ag.sleep_forever() job_state = 'C' return 'result' task = ag.Task(job()) root_coro = task.root_coro assert task.state is TS.CREATED assert task._exception is None assert job_state == 'A' with pytest.raises(ag.InvalidStateError): task.result ag.start(task) assert task.state is TS.STARTED assert task._exception is None assert job_state == 'B' with pytest.raises(ag.InvalidStateError): task.result with pytest.raises(StopIteration): root_coro.send(None) assert task.state is TS.DONE assert task._exception is None assert task.done assert not task.cancelled assert task.result == 'result'
def test_cancel_without_start(): from inspect import getcoroutinestate, CORO_CLOSED import asyncgui as ag task = ag.Task(ag.sleep_forever()) task.cancel() assert task.cancelled assert task._exception is None assert getcoroutinestate(task.root_coro) == CORO_CLOSED
def test_cancel_all_children(): import asyncgui as ag from asyncgui.structured_concurrency import or_ TS = ag.TaskState async def main(): tasks = await or_(child1, child2) for task in tasks: assert task.cancelled child1 = ag.Task(ag.sleep_forever()) child2 = ag.Task(ag.sleep_forever()) main_task = ag.start(main()) assert main_task.state is TS.STARTED child1.cancel() assert main_task.state is TS.STARTED child2.cancel() assert main_task.state is TS.DONE
def test_try_to_cancel_self_but_no_opportunity_for_that(): import asyncgui as ag async def async_fn(): assert not task._is_cancellable task.cancel() task = ag.Task(async_fn()) ag.start(task) assert task.done
def test__return_value(): import asyncgui as ag task = ag.Task(ag.sleep_forever()) gen_based_coro = ag.sleep_forever() coro = async_fn() assert ag.start(task) is task for v in (gen_based_coro, coro): assert isinstance(ag.start(v), ag.Task)
def test_cancel_self(): import asyncgui as ag async def async_fn(): assert not task._is_cancellable task.cancel() assert task._cancel_called await ag.sleep_forever() pytest.fail("Failed to cancel") task = ag.Task(async_fn()) ag.start(task) assert task.cancelled assert task._exception is None
def test_suppress_exception(do_suppress): async def job(): raise ZeroDivisionError task = ag.Task(job(), name='pytest') task._suppresses_exception = do_suppress if do_suppress: ag.start(task) assert type(task._exception) is ZeroDivisionError else: with pytest.raises(ZeroDivisionError): ag.start(task) assert task._exception is None assert task.state is TS.CANCELLED
def test_例外を起こさない子_を複数持つ親を中断(): import asyncgui as ag from asyncgui.structured_concurrency import or_ TS = ag.TaskState async def main(): await or_(ag.sleep_forever(), ag.sleep_forever()) pytest.fail() main_task = ag.Task(main()) ag.start(main_task) assert main_task.state is TS.STARTED main_task.cancel() assert main_task.state is TS.CANCELLED
def test_complicated_case( starts_immediately, what_a_should_do, should_b_fail, should_c_fail, ): import asyncgui as ag ctx = { 'e_begin': ag.Event(), 'e': ag.Event(), 'what_a_should_do': what_a_should_do, 'should_b_fail': should_b_fail, 'should_c_fail': should_c_fail, } n_exceptions = 0 if what_a_should_do == 'fail': n_exceptions += 1 if should_b_fail: n_exceptions += 1 if should_c_fail: n_exceptions += 1 async def main(ctx): from asyncgui.structured_concurrency import and_ task_a = ag.Task(child_a(ctx)) task_b = ctx['task_b'] = ag.Task(child_b(ctx)) task_c = ag.Task(child_c(ctx)) if n_exceptions == 1: with pytest.raises(ZeroDivisionError): await and_(task_a, task_b, task_c) await ag.sleep_forever() elif n_exceptions: with pytest.raises(ag.MultiError) as excinfo: await and_(task_a, task_b, task_c) assert [ZeroDivisionError, ] * n_exceptions == \ [type(e) for e in excinfo.value.exceptions] await ag.sleep_forever() else: await and_(task_a, task_b, task_c) if starts_immediately: ctx['e_begin'].set() ctx['main_task'] = main_task = ag.Task(main(ctx)) ag.start(main_task) if not starts_immediately: ctx['e_begin'].set() assert main_task._cancel_called assert main_task.cancelled
def test_other_child_does_not_fail(self, other_child): import asyncgui as ag from asyncgui.structured_concurrency import and_ async def main(e): await and_(finish_soon_but_protected(e), other_child(e)) pytest.fail("Failed to cancel") e = ag.Event() main_task = ag.Task(main(e)) ag.start(main_task) assert not main_task.cancelled main_task.cancel() assert not main_task.cancelled e.set() assert main_task.cancelled
def test_other_child_fails(self, other_child): import asyncgui as ag from asyncgui.structured_concurrency import or_ async def main(e): with pytest.raises(ZeroDivisionError): await or_(finish_soon_but_protected(e), other_child(e)) e = ag.Event() main_task = ag.Task(main(e)) ag.start(main_task) assert not main_task.done main_task.cancel() assert not main_task.done e.set() assert main_task.done
def test_必ず例外を起こす子_を複数持つ親を中断_2(): import asyncgui as ag from asyncgui.structured_concurrency import or_ TS = ag.TaskState async def main(): await or_(fail_on_cancel(), fail_on_cancel()) pytest.fail("Failed to cancel") main_task = ag.Task(main()) ag.start(main_task) assert main_task.state is TS.STARTED with pytest.raises(ag.MultiError) as excinfo: main_task.cancel() assert [ZeroDivisionError, ZeroDivisionError] == \ [type(e) for e in excinfo.value.exceptions] assert main_task.state is TS.CANCELLED
def test_checkpoint(call_cancel, protect): import asyncgui as ag async def async_func(ctx): if call_cancel: ctx['task'].cancel() if protect: async with ag.cancel_protection(): await ag.checkpoint() else: await ag.checkpoint() ctx = {} ctx['task'] = task = ag.Task(async_func(ctx)) ag.start(task) if (not protect) and call_cancel: assert task.cancelled else: assert task.done
def test_cancel_protected_self(): import asyncgui as ag async def async_fn(): task = await ag.get_current_task() async with ag.cancel_protection(): task.cancel() await ag.sleep_forever() await ag.sleep_forever() pytest.fail("Failed to cancel") task = ag.Task(async_fn()) ag.start(task) assert not task.cancelled assert not task._is_cancellable assert task._cancel_protection == 1 task._step_coro() assert task.cancelled assert task._cancel_protection == 0
def test_weakref(): import weakref import asyncgui as ag task = ag.Task(ag.sleep_forever()) weakref.ref(task) task.cancel()