Add a `Portal.cancel_actor()` test
parent
0ab5e5cadd
commit
56357242e9
|
@ -2,10 +2,15 @@
|
||||||
The most hipster way to force SC onto the stdlib's "async".
|
The most hipster way to force SC onto the stdlib's "async".
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
from typing import Optional
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import builtins
|
||||||
|
import importlib
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
import trio
|
||||||
import tractor
|
import tractor
|
||||||
|
from tractor import RemoteActorError
|
||||||
|
|
||||||
|
|
||||||
async def sleep_and_err():
|
async def sleep_and_err():
|
||||||
|
@ -13,24 +18,78 @@ async def sleep_and_err():
|
||||||
assert 0
|
assert 0
|
||||||
|
|
||||||
|
|
||||||
async def asyncio_actor():
|
async def sleep_forever():
|
||||||
assert tractor.current_actor().is_infected_aio()
|
await asyncio.sleep(float('inf'))
|
||||||
|
|
||||||
await tractor.to_asyncio.run_task(sleep_and_err)
|
|
||||||
|
async def asyncio_actor(
|
||||||
|
|
||||||
|
target: str,
|
||||||
|
expect_err: Optional[Exception] = None
|
||||||
|
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
assert tractor.current_actor().is_infected_aio()
|
||||||
|
target = globals()[target]
|
||||||
|
|
||||||
|
if '.' in expect_err:
|
||||||
|
modpath, _, name = expect_err.rpartition('.')
|
||||||
|
mod = importlib.import_module(modpath)
|
||||||
|
error = getattr(mod, name)
|
||||||
|
error = builtins.__dict__.get(expect_err)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# spawn an ``asyncio`` task to run a func and return result
|
||||||
|
await tractor.to_asyncio.run_task(target)
|
||||||
|
except Exception as err:
|
||||||
|
if expect_err:
|
||||||
|
assert isinstance(err, error)
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def test_aio_simple_error(arb_addr):
|
def test_aio_simple_error(arb_addr):
|
||||||
|
'''
|
||||||
|
Verify a simple remote asyncio error propagates back through trio
|
||||||
|
to the parent actor.
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
async def main():
|
||||||
|
async with tractor.open_nursery(
|
||||||
|
arbiter_addr=arb_addr
|
||||||
|
) as n:
|
||||||
|
await n.run_in_actor(
|
||||||
|
asyncio_actor,
|
||||||
|
target='sleep_and_err',
|
||||||
|
expect_err='AssertionError',
|
||||||
|
infect_asyncio=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
with pytest.raises(RemoteActorError) as excinfo:
|
||||||
|
trio.run(main)
|
||||||
|
|
||||||
|
err = excinfo.value
|
||||||
|
assert isinstance(err, RemoteActorError)
|
||||||
|
assert err.type == AssertionError
|
||||||
|
|
||||||
|
|
||||||
|
def test_tractor_cancels_aio(arb_addr):
|
||||||
|
'''
|
||||||
|
Verify we can cancel a spawned asyncio task gracefully.
|
||||||
|
|
||||||
|
'''
|
||||||
async def main():
|
async def main():
|
||||||
async with tractor.open_nursery() as n:
|
async with tractor.open_nursery() as n:
|
||||||
await n.run_in_actor(asyncio_actor, infected_asyncio=True)
|
portal = await n.run_in_actor(
|
||||||
|
asyncio_actor,
|
||||||
|
target='sleep_forever',
|
||||||
|
expect_err='asyncio.CancelledError',
|
||||||
|
infect_asyncio=True,
|
||||||
|
)
|
||||||
|
await portal.cancel_actor()
|
||||||
|
|
||||||
with pytest.raises(tractor.RemoteActorError) as excinfo:
|
trio.run(main)
|
||||||
tractor.run(main, arbiter_addr=arb_addr)
|
|
||||||
|
|
||||||
|
|
||||||
def test_aio_cancel_from_trio(arb_addr):
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
def test_aio_cancelled_from_aio_causes_trio_cancelled(arb_addr):
|
def test_aio_cancelled_from_aio_causes_trio_cancelled(arb_addr):
|
||||||
|
@ -49,10 +108,6 @@ def test_basic_interloop_channel_stream(arb_addr):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
def test_basic_interloop_channel_stream(arb_addr):
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
def test_trio_cancels_and_channel_exits(arb_addr):
|
def test_trio_cancels_and_channel_exits(arb_addr):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
|
@ -475,6 +475,7 @@ class Actor:
|
||||||
self._mods[modpath] = mod
|
self._mods[modpath] = mod
|
||||||
if modpath == '__main__':
|
if modpath == '__main__':
|
||||||
self._mods['__mp_main__'] = mod
|
self._mods['__mp_main__'] = mod
|
||||||
|
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
# it is expected the corresponding `ModuleNotExposed` error
|
# it is expected the corresponding `ModuleNotExposed` error
|
||||||
# will be raised later
|
# will be raised later
|
||||||
|
|
Loading…
Reference in New Issue