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_clear(): import asyncgui as ag e1 = ag.Event() e2 = ag.Event() async def main(): nonlocal task_state task_state = 'A' await e1.wait() task_state = 'B' await e2.wait() task_state = 'C' await e1.wait() task_state = 'D' task_state = None ag.start(main()) assert task_state == 'A' e1.set() assert task_state == 'B' e1.clear() e2.set() assert task_state == 'C' e1.set() assert task_state == 'D'
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_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
async def run_awaitable(ag_awaitable, *, task_status=trio.TASK_STATUS_IGNORED): '''(experimental) Run an asyncgui-flavored awaitable under Trio. Usage #1: nursery.start_soon(run_awaitable, an_asyncgui_awaitable) Usage #2: return_value = await run_awaitable(an_asyncgui_awaitable) ''' if not isawaitable(ag_awaitable): raise ValueError(f"{ag_awaitable} is not awaitable") end_signal = trio.Event() try: outcome = {} wrapper_coro = _ag_awaitable_wrapper( outcome, end_signal, ag_awaitable, ) asyncgui.start(wrapper_coro) task_status.started(wrapper_coro) await end_signal.wait() exception = outcome.get('exception', None) if exception is not None: raise exception if outcome.get('cancelled', False): raise CancelledError("Inner task was cancelled") return outcome['return_value'] finally: wrapper_coro.close()
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_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_concurrency(): import asyncgui as ag from asyncgui.testing import open_scheduler state = 'started' async def state_changer(sleep): nonlocal state await sleep(0.1) state = 'A' await sleep(0.1) state = 'B' await sleep(0.1) state = 'C' async def state_watcher(sleep): await sleep(0.05) assert state == 'started' await sleep(0.1) assert state == 'A' await sleep(0.1) assert state == 'B' await sleep(0.1) assert state == 'C' with open_scheduler() as (schedulr, sleep): task1 = ag.start(state_changer(sleep)) task2 = ag.start(state_watcher(sleep)) assert task1.done assert task2.done
def test__already_started(): import asyncgui as ag task1 = ag.start(ag.sleep_forever()) task2 = ag.start(async_fn()) for task in (task1, task2): with pytest.raises(ValueError): ag.start(task)
def test_regular_gen(): import asyncgui as ag def regular_gen(): yield 1 with pytest.raises(ValueError): ag.start(regular_gen())
def test__unsupported_type(): import asyncgui as ag func = lambda: None gen = (i for i in range(3)) for v in (func, gen): with pytest.raises(ValueError): ag.start(v)
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_multiple_tasks(): import asyncgui as ag TS = ag.TaskState e = ag.Event() task1 = ag.start(e.wait()) task2 = ag.start(e.wait()) assert task1.state is TS.STARTED assert task2.state is TS.STARTED e.set() assert task1.state is TS.DONE assert task2.state is TS.DONE
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__get_step_coro(raw): import asyncgui as ag done = False async def job(): step_coro = await ag.get_step_coro() assert callable(step_coro) nonlocal done done = True if raw: ag.raw_start(job()) else: ag.start(job()) assert done
def test__get_current_task(raw): import asyncgui as ag done = False async def job(): task = await ag.get_current_task() assert (task is None) if raw else isinstance(task, ag.Task) nonlocal done done = True if raw: ag.raw_start(job()) else: ag.start(job()) assert done
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_one_child_fails_immediately(): import asyncgui as ag from asyncgui.structured_concurrency import or_ async def main(): with pytest.raises(ZeroDivisionError): await or_(fail_immediately()) main_task = ag.start(main()) assert main_task.done
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_no_child(): import asyncgui as ag from asyncgui.structured_concurrency import and_ async def main(): tasks = await and_() assert len(tasks) == 0 main_task = ag.start(main()) assert main_task.done
def test_multiple_children_finish_immediately(): import asyncgui as ag from asyncgui.structured_concurrency import and_ async def main(): tasks = await and_(finish_immediately(), finish_immediately()) assert [True, True] == [task.done for task in tasks] main_task = ag.start(main()) assert main_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_no_child(): import asyncgui as ag from asyncgui.structured_concurrency import or_ async def main(): tasks = await or_() assert tasks == [] main_task = ag.start(main()) assert main_task.done
def test_set_before_task_starts(): import asyncgui as ag e = ag.Event() e.set() async def main(): await e.wait() task = ag.start(main()) assert task.done