async def test_join_not_waited_with_timeout(): """ Ensure that when the scope is done, all tasks not awaited are cancelled without waiting """ before = time.time() with pytest.raises(TimeoutError): async with Scope(timeout=0.2) as scope: scope.spawn(run10(), awaited=False) scope << run10() after = time.time() assert 0.1 < (after - before) < 0.3
async def test_cancel_master(): """Test if cancelling master cancels the loop""" before = time.time() async with Scope(timeout=0.5) as n: n.spawn(run10()) t = n.spawn(run10(), master=True) await asyncio.sleep(0.05) t.cancel() after = time.time() assert (after - before) < 0.2
async def test_nested_fork_raises_catch(): """ Two nested Nurseries, but completely unrelated. Remember that we cannot do magic (yet). As long as the inner code is blocking and not related to the surrounding Scope, The outer timeout will be stuck! """ before = time.time() async def bomb(): await asyncio.sleep(0.2) raise ValueError('boom!') with pytest.raises(TimeoutError): async with Scope(timeout=0.5) as parent: parent.spawn(run10(), name='run10') inner = parent.fork() inner.spawn(bomb()) with pytest.raises(ValueError): # This should prevent bubbling await inner after = time.time() assert (after - before) > 0.4
async def test_nested_fork_timeout_sibling(): """ Two nested Nurseries, but completely unrelated. Remember that we cannot do magic (yet). As long as the inner code is blocking and not related to the surrounding Scope, The outer timeout will be stuck! """ before = time.time() async def fork_my_parent(scope, timeout: float = 0): async with scope.fork(timeout=timeout) as inner: inner.spawn(run10()) with pytest.raises(TimeoutError): async with Scope() as parent: parent.spawn(run10()) # First long one parent.spawn(fork_my_parent(parent)) # Second will timeout soon parent.spawn(fork_my_parent(parent, timeout=0.1)) after = time.time() assert (after - before) < 0.2
async def test_join_task_cancelled(): """Test joining a task, but cancelled""" async with Scope(timeout=1) as n: t = n.spawn(run10()) t.cancel() with pytest.raises(asyncio.CancelledError): await t
async def test_nested_fork_timeout_inner(): """ Two nested Nurseries, but completely unrelated. Remember that we cannot do magic (yet). As long as the inner code is blocking and not related to the surrounding Scope, The outer timeout will be stuck! """ before = time.time() with pytest.raises(TimeoutError): async with Scope() as parent: parent.spawn(run10()) async with parent.fork(timeout=0.1) as inner: inner.spawn(run10()) after = time.time() assert (after - before) < 0.2
async def test_timeout(): """Simple timeout""" before = time.time() with pytest.raises(TimeoutError): async with Scope(timeout=0.1) as n: n.spawn(run10()) after = time.time() assert (after - before) < 0.5
async def test_timeout_override(): """Override timeout value""" before = time.time() with pytest.raises(TimeoutError): async with Scope(timeout=5) as n: n.spawn(run10()) n.timeout = 0.1 after = time.time() assert (after - before) < 0.5
async def test_join_not_waited_alone(): """ Ensure that when the scope is done, all tasks not awaited are cancelled without waiting """ before = time.time() async with Scope() as scope: scope.spawn(run10(), awaited=False) after = time.time() assert (after - before) < 0.1
async def test_internal_cancel(): """Test an internal cancellation""" before = time.time() async with Scope() as n: n.spawn(run10()) await asyncio.sleep(0.2) n.cancel() after = time.time() assert (after - before) < 0.5
async def test_nested_fork_timeout_parent(): """ Two nested Nurseries, inner one generated by parent """ before = time.time() with pytest.raises(TimeoutError): async with Scope(timeout=0.1) as parent: async with parent.fork() as inner: inner.spawn(run10()) after = time.time() assert (after - before) < 0.2
async def test_master_raises(awaited): """ Raise an exception from a task This is independent of awaited flag """ async def raiser(): await asyncio.sleep(0.01) raise ValueError('boom') with pytest.raises(ValueError): async with Scope() as n: n.spawn(run10()) n.spawn(raiser(), master=True, awaited=awaited)
async def test_nested_cancel_wait(): """ """ parent = Scope() child = parent.fork() child << run10() await asyncio.sleep(0.1) child.cancel() parent.cancel() await asyncio.wait_for(asyncio.shield(parent), 1)
async def test_join_task_cancelled_no_env(wait): """Test joining a task, but cancelled""" n = Scope(timeout=1) t = n.spawn(run10()) t.cancel() with pytest.raises(asyncio.CancelledError): await t n.finalize() if wait: await asyncio.wait_for(n, 2) else: await n
async def test_nested_unrelated(): """ Two nested Nurseries, outer will timeout before inner. This should be handled properly now. """ before = time.time() with pytest.raises(TimeoutError): async with Scope(timeout=0.2): async with Scope(timeout=0.5) as inner: """ A completely different """ inner.spawn(run10()) after = time.time() assert (after - before) < 0.4, 'for now...'
async def test_nested_cancel_join(wait): """ """ parent = Scope() child = parent.fork() child << run10() await asyncio.sleep(0.1) child.cancel() parent.cancel() if wait: await parent else: await asyncio.wait_for(parent, 1)
async def test_master(bubble, awaited): """ Test if a master correctly cancels pending tasks This is independent from bubbling and awaited flags """ async def master(): await asyncio.sleep(0.01) before = time.time() async with Scope() as n: n.spawn(run10()) n.spawn(master(), master=True, bubble=bubble, awaited=awaited) after = time.time() assert (after - before) < 0.5
async def test_no_bubble_master(awaited): """ Test if no bubble does not raise, but cancels because of master=True This is independent of awaited flag """ async def trivial(): await asyncio.sleep(0.01) raise ValueError('not interesting') before = time.time() async with Scope(timeout=0.5) as n: n.spawn(run10()) n.spawn(trivial(), bubble=False, master=True, awaited=awaited) after = time.time() assert (after - before) < 0.2
async def test_cancel_double(): """ Cancelled externally, twice """ async def cleaner(scope): await asyncio.sleep(0.2) scope.cancel() # Should we raise something in case of double close? scope.cancel() scope = Scope() task = asyncio.ensure_future(cleaner(scope)) async with scope: scope << run10() await task assert scope.done() and scope.exception() is None
async def test_no_bubble(awaited): """ Test if no bubble does not cancel scope This is independent of awaited flag """ async def trivial(): await asyncio.sleep(0.01) raise ValueError('not interesting') before = time.time() with pytest.raises(TimeoutError): async with Scope(timeout=0.5) as n: n.spawn(run10()) n.spawn(trivial(), bubble=False, awaited=awaited) after = time.time() assert (after - before) > 0.4
async def test_cancel_double_exception(): """ Cancelled externally, twice, with exception """ async def cleaner(scope): await asyncio.sleep(0.2) scope.cancel(ValueError('boom')) # Should we raise something in case of double close? scope.cancel(ValueError('boom')) scope = Scope() task = asyncio.ensure_future(cleaner(scope)) with pytest.raises(ValueError): async with scope: scope << run10() await task assert scope.done() and isinstance(scope.exception(), ValueError)
async def run_me(): n = Scope() async with n: n.spawn(run10()) assert n.cancelled()
async def fork_my_parent(scope, timeout: float = 0): async with scope.fork(timeout=timeout) as inner: inner.spawn(run10())