commit
f48548ab94
|
@ -145,7 +145,7 @@ and use the ``run_in_actor()`` method:
|
|||
|
||||
What's going on?
|
||||
|
||||
- an initial *actor* is started with ``tractor.run()`` and told to execute
|
||||
- an initial *actor* is started with ``trio.run()`` and told to execute
|
||||
its main task_: ``main()``
|
||||
|
||||
- inside ``main()`` an actor is *spawned* using an ``ActorNusery`` and is told
|
||||
|
@ -182,7 +182,7 @@ Here is a similar example using the latter method:
|
|||
|
||||
.. literalinclude:: ../examples/actor_spawning_and_causality_with_daemon.py
|
||||
|
||||
The ``rpc_module_paths`` `kwarg` above is a list of module path
|
||||
The ``enable_modules`` `kwarg` above is a list of module path
|
||||
strings that will be loaded and made accessible for execution in the
|
||||
remote actor through a call to ``Portal.run()``. For now this is
|
||||
a simple mechanism to restrict the functionality of the remote
|
||||
|
@ -458,7 +458,7 @@ find an actor's socket address by name use the ``find_actor()`` function:
|
|||
.. literalinclude:: ../examples/service_discovery.py
|
||||
|
||||
The ``name`` value you should pass to ``find_actor()`` is the one you passed as the
|
||||
*first* argument to either ``tractor.run()`` or ``ActorNursery.start_actor()``.
|
||||
*first* argument to either ``trio.run()`` or ``ActorNursery.start_actor()``.
|
||||
|
||||
|
||||
Running actors standalone
|
||||
|
@ -472,7 +472,17 @@ need to hop into a debugger. You just need to pass the existing
|
|||
|
||||
.. code:: python
|
||||
|
||||
tractor.run(main, arbiter_addr=('192.168.0.10', 1616))
|
||||
import trio
|
||||
import tractor
|
||||
|
||||
async def main():
|
||||
|
||||
async with tractor.open_root_actor(
|
||||
arbiter_addr=('192.168.0.10', 1616)
|
||||
):
|
||||
await trio.sleep_forever()
|
||||
|
||||
trio.run(main)
|
||||
|
||||
|
||||
Choosing a process spawning backend
|
||||
|
@ -480,7 +490,7 @@ Choosing a process spawning backend
|
|||
``tractor`` is architected to support multiple actor (sub-process)
|
||||
spawning backends. Specific defaults are chosen based on your system
|
||||
but you can also explicitly select a backend of choice at startup
|
||||
via a ``start_method`` kwarg to ``tractor.run()``.
|
||||
via a ``start_method`` kwarg to ``tractor.open_nursery()``.
|
||||
|
||||
Currently the options available are:
|
||||
|
||||
|
@ -536,13 +546,14 @@ main python module of the program:
|
|||
.. code:: python
|
||||
|
||||
# application/__main__.py
|
||||
import trio
|
||||
import tractor
|
||||
import multiprocessing
|
||||
from . import tractor_app
|
||||
|
||||
if __name__ == '__main__':
|
||||
multiprocessing.freeze_support()
|
||||
tractor.run(tractor_app.main)
|
||||
trio.run(tractor_app.main)
|
||||
|
||||
And execute as::
|
||||
|
||||
|
|
|
@ -16,4 +16,4 @@ if __name__ == '__main__':
|
|||
# temporary dir and name it test_example.py. We import that script
|
||||
# module here and invoke it's ``main()``.
|
||||
from . import test_example
|
||||
test_example.tractor.run(test_example.main, start_method='spawn')
|
||||
test_example.trio.run(test_example.main)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import trio
|
||||
import tractor
|
||||
|
||||
_this_module = __name__
|
||||
|
@ -40,4 +41,4 @@ async def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main)
|
||||
trio.run(main)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import trio
|
||||
import tractor
|
||||
|
||||
|
||||
|
@ -23,4 +24,4 @@ async def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main)
|
||||
trio.run(main)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import trio
|
||||
import tractor
|
||||
|
||||
|
||||
|
@ -16,7 +17,7 @@ async def main():
|
|||
portal = await n.start_actor(
|
||||
'frank',
|
||||
# enable the actor to run funcs from this current module
|
||||
rpc_module_paths=[__name__],
|
||||
enable_modules=[__name__],
|
||||
)
|
||||
|
||||
print(await portal.run(movie_theatre_question))
|
||||
|
@ -30,4 +31,4 @@ async def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main)
|
||||
trio.run(main)
|
||||
|
|
|
@ -14,12 +14,15 @@ async def stream_forever():
|
|||
|
||||
|
||||
async def main():
|
||||
|
||||
# stream for at most 1 seconds
|
||||
with trio.move_on_after(1) as cancel_scope:
|
||||
|
||||
async with tractor.open_nursery() as n:
|
||||
|
||||
portal = await n.start_actor(
|
||||
f'donny',
|
||||
rpc_module_paths=[__name__],
|
||||
'donny',
|
||||
enable_modules=[__name__],
|
||||
)
|
||||
|
||||
# this async for loop streams values from the above
|
||||
|
@ -34,4 +37,4 @@ async def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main)
|
||||
trio.run(main)
|
||||
|
|
|
@ -11,7 +11,7 @@ async def breakpoint_forever():
|
|||
|
||||
async def name_error():
|
||||
"Raise a ``NameError``"
|
||||
getattr(doggypants)
|
||||
getattr(doggypants) # noqa
|
||||
|
||||
|
||||
async def main():
|
||||
|
|
|
@ -4,7 +4,7 @@ import tractor
|
|||
|
||||
async def name_error():
|
||||
"Raise a ``NameError``"
|
||||
getattr(doggypants)
|
||||
getattr(doggypants) # noqa
|
||||
|
||||
|
||||
async def breakpoint_forever():
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import trio
|
||||
import tractor
|
||||
|
||||
|
||||
async def name_error():
|
||||
"Raise a ``NameError``"
|
||||
getattr(doggypants)
|
||||
getattr(doggypants) # noqa
|
||||
|
||||
|
||||
async def spawn_error():
|
||||
|
@ -32,7 +33,9 @@ async def main():
|
|||
- root actor should then fail on assert
|
||||
- program termination
|
||||
"""
|
||||
async with tractor.open_nursery() as n:
|
||||
async with tractor.open_nursery(
|
||||
debug_mode=True,
|
||||
) as n:
|
||||
|
||||
# spawn both actors
|
||||
portal = await n.run_in_actor(
|
||||
|
@ -54,4 +57,4 @@ async def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main, debug_mode=True)
|
||||
trio.run(main)
|
||||
|
|
|
@ -11,7 +11,7 @@ async def breakpoint_forever():
|
|||
|
||||
async def name_error():
|
||||
"Raise a ``NameError``"
|
||||
getattr(doggypants)
|
||||
getattr(doggypants) # noqa
|
||||
|
||||
|
||||
async def spawn_error():
|
||||
|
@ -36,7 +36,9 @@ async def main():
|
|||
`-python -m tractor._child --uid ('spawn_error', '52ee14a5 ...)
|
||||
`-python -m tractor._child --uid ('name_error', '3391222c ...)
|
||||
"""
|
||||
async with tractor.open_nursery() as n:
|
||||
async with tractor.open_nursery(
|
||||
debug_mode=True,
|
||||
) as n:
|
||||
|
||||
# Spawn both actors, don't bother with collecting results
|
||||
# (would result in a different debugger outcome due to parent's
|
||||
|
@ -47,4 +49,4 @@ async def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main, debug_mode=True)
|
||||
trio.run(main)
|
||||
|
|
|
@ -4,12 +4,16 @@ import tractor
|
|||
|
||||
async def main():
|
||||
|
||||
await trio.sleep(0.1)
|
||||
async with tractor.open_root_actor(
|
||||
debug_mode=True,
|
||||
):
|
||||
|
||||
await tractor.breakpoint()
|
||||
await trio.sleep(0.1)
|
||||
|
||||
await trio.sleep(0.1)
|
||||
await tractor.breakpoint()
|
||||
|
||||
await trio.sleep(0.1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main, debug_mode=True)
|
||||
trio.run(main)
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import trio
|
||||
import tractor
|
||||
|
||||
|
||||
async def main():
|
||||
|
||||
while True:
|
||||
await tractor.breakpoint()
|
||||
async with tractor.open_root_actor(
|
||||
debug_mode=True,
|
||||
):
|
||||
while True:
|
||||
await tractor.breakpoint()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main, debug_mode=True)
|
||||
trio.run(main)
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import trio
|
||||
import tractor
|
||||
|
||||
|
||||
async def main():
|
||||
assert 0
|
||||
async with tractor.open_root_actor(
|
||||
debug_mode=True,
|
||||
):
|
||||
assert 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main, debug_mode=True)
|
||||
trio.run(main)
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import trio
|
||||
import tractor
|
||||
|
||||
|
||||
async def name_error():
|
||||
"Raise a ``NameError``"
|
||||
getattr(doggypants)
|
||||
getattr(doggypants) # noqa
|
||||
|
||||
|
||||
async def spawn_until(depth=0):
|
||||
|
@ -37,7 +38,10 @@ async def main():
|
|||
└─ python -m tractor._child --uid ('name_error', '6c2733b8 ...)
|
||||
|
||||
"""
|
||||
async with tractor.open_nursery() as n:
|
||||
async with tractor.open_nursery(
|
||||
debug_mode=True,
|
||||
loglevel='warning'
|
||||
) as n:
|
||||
|
||||
# spawn both actors
|
||||
portal = await n.run_in_actor(
|
||||
|
@ -58,4 +62,4 @@ async def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main, debug_mode=True, loglevel='warning')
|
||||
trio.run(main)
|
||||
|
|
|
@ -12,7 +12,9 @@ async def breakpoint_forever():
|
|||
|
||||
async def main():
|
||||
|
||||
async with tractor.open_nursery() as n:
|
||||
async with tractor.open_nursery(
|
||||
debug_mode=True,
|
||||
) as n:
|
||||
|
||||
portal = await n.run_in_actor(
|
||||
breakpoint_forever,
|
||||
|
@ -21,4 +23,4 @@ async def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main, debug_mode=True, loglevel='debug')
|
||||
trio.run(main)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import trio
|
||||
import tractor
|
||||
|
||||
|
||||
|
@ -6,11 +7,13 @@ async def name_error():
|
|||
|
||||
|
||||
async def main():
|
||||
async with tractor.open_nursery() as n:
|
||||
async with tractor.open_nursery(
|
||||
debug_mode=True,
|
||||
) as n:
|
||||
|
||||
portal = await n.run_in_actor(name_error)
|
||||
await portal.result()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main, debug_mode=True)
|
||||
trio.run(main)
|
||||
|
|
|
@ -68,10 +68,11 @@ async def aggregate(seed):
|
|||
# this is the main actor and *arbiter*
|
||||
async def main():
|
||||
# a nursery which spawns "actors"
|
||||
async with tractor.open_nursery() as nursery:
|
||||
async with tractor.open_nursery(
|
||||
arbiter_addr=('127.0.0.1', 1616)
|
||||
) as nursery:
|
||||
|
||||
seed = int(1e3)
|
||||
import time
|
||||
pre_start = time.time()
|
||||
|
||||
portal = await nursery.start_actor(
|
||||
|
@ -100,4 +101,4 @@ async def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
final_stream = tractor.run(main, arbiter_addr=('127.0.0.1', 1616))
|
||||
final_stream = trio.run(main)
|
||||
|
|
|
@ -10,6 +10,7 @@ PRIMES = [
|
|||
115797848077099,
|
||||
1099726899285419]
|
||||
|
||||
|
||||
def is_prime(n):
|
||||
if n < 2:
|
||||
return False
|
||||
|
@ -24,6 +25,7 @@ def is_prime(n):
|
|||
return False
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
start = time.time()
|
||||
|
@ -33,6 +35,7 @@ def main():
|
|||
|
||||
print(f'processing took {time.time() - start} seconds')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
start = time.time()
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import trio
|
||||
import tractor
|
||||
|
||||
|
||||
|
@ -11,7 +12,7 @@ async def main():
|
|||
for i in range(3):
|
||||
real_actors.append(await n.start_actor(
|
||||
f'actor_{i}',
|
||||
rpc_module_paths=[__name__],
|
||||
enable_modules=[__name__],
|
||||
))
|
||||
|
||||
# start one actor that will fail immediately
|
||||
|
@ -24,6 +25,6 @@ async def main():
|
|||
if __name__ == '__main__':
|
||||
try:
|
||||
# also raises
|
||||
tractor.run(main)
|
||||
trio.run(main)
|
||||
except tractor.RemoteActorError:
|
||||
print("Look Maa that actor failed hard, hehhh!")
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import trio
|
||||
import tractor
|
||||
|
||||
tractor.log.get_console_log("INFO")
|
||||
|
||||
|
||||
async def main(service_name):
|
||||
|
||||
async with tractor.open_nursery() as an:
|
||||
|
@ -17,4 +19,4 @@ async def main(service_name):
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tractor.run(main, 'some_actor_name')
|
||||
trio.run(main, 'some_actor_name')
|
||||
|
|
|
@ -47,7 +47,9 @@ def test_remote_error(arb_addr, args_err):
|
|||
args, errtype = args_err
|
||||
|
||||
async def main():
|
||||
async with tractor.open_nursery() as nursery:
|
||||
async with tractor.open_nursery(
|
||||
arbiter_addr=arb_addr,
|
||||
) as nursery:
|
||||
|
||||
portal = await nursery.run_in_actor(
|
||||
assert_err, name='errorer', **args
|
||||
|
@ -62,7 +64,7 @@ def test_remote_error(arb_addr, args_err):
|
|||
raise
|
||||
|
||||
with pytest.raises(tractor.RemoteActorError) as excinfo:
|
||||
tractor.run(main, arbiter_addr=arb_addr)
|
||||
trio.run(main)
|
||||
|
||||
# ensure boxed error is correct
|
||||
assert excinfo.value.type == errtype
|
||||
|
@ -73,7 +75,9 @@ def test_multierror(arb_addr):
|
|||
more then one actor errors.
|
||||
"""
|
||||
async def main():
|
||||
async with tractor.open_nursery() as nursery:
|
||||
async with tractor.open_nursery(
|
||||
arbiter_addr=arb_addr,
|
||||
) as nursery:
|
||||
|
||||
await nursery.run_in_actor(assert_err, name='errorer1')
|
||||
portal2 = await nursery.run_in_actor(assert_err, name='errorer2')
|
||||
|
@ -90,7 +94,7 @@ def test_multierror(arb_addr):
|
|||
# from both subactors
|
||||
|
||||
with pytest.raises(trio.MultiError):
|
||||
tractor.run(main, arbiter_addr=arb_addr)
|
||||
trio.run(main)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('delay', (0, 0.5))
|
||||
|
@ -103,7 +107,10 @@ def test_multierror_fast_nursery(arb_addr, start_method, num_subactors, delay):
|
|||
to test failure during an ongoing spawning.
|
||||
"""
|
||||
async def main():
|
||||
async with tractor.open_nursery() as nursery:
|
||||
async with tractor.open_nursery(
|
||||
arbiter_addr=arb_addr,
|
||||
) as nursery:
|
||||
|
||||
for i in range(num_subactors):
|
||||
await nursery.run_in_actor(
|
||||
assert_err,
|
||||
|
@ -112,7 +119,7 @@ def test_multierror_fast_nursery(arb_addr, start_method, num_subactors, delay):
|
|||
)
|
||||
|
||||
with pytest.raises(trio.MultiError) as exc_info:
|
||||
tractor.run(main, arbiter_addr=arb_addr)
|
||||
trio.run(main)
|
||||
|
||||
assert exc_info.type == tractor.MultiError
|
||||
err = exc_info.value
|
||||
|
@ -134,10 +141,12 @@ def test_cancel_single_subactor(arb_addr, mechanism):
|
|||
async def spawn_actor():
|
||||
"""Spawn an actor that blocks indefinitely.
|
||||
"""
|
||||
async with tractor.open_nursery() as nursery:
|
||||
async with tractor.open_nursery(
|
||||
arbiter_addr=arb_addr,
|
||||
) as nursery:
|
||||
|
||||
portal = await nursery.start_actor(
|
||||
'nothin', rpc_module_paths=[__name__],
|
||||
'nothin', enable_modules=[__name__],
|
||||
)
|
||||
assert (await portal.run(do_nothing)) is None
|
||||
|
||||
|
@ -148,10 +157,10 @@ def test_cancel_single_subactor(arb_addr, mechanism):
|
|||
raise mechanism
|
||||
|
||||
if mechanism == 'nursery_cancel':
|
||||
tractor.run(spawn_actor, arbiter_addr=arb_addr)
|
||||
trio.run(spawn_actor)
|
||||
else:
|
||||
with pytest.raises(mechanism):
|
||||
tractor.run(spawn_actor, arbiter_addr=arb_addr)
|
||||
trio.run(spawn_actor)
|
||||
|
||||
|
||||
async def stream_forever():
|
||||
|
@ -229,7 +238,7 @@ async def test_some_cancels_all(num_actors_and_errs, start_method, loglevel):
|
|||
for i in range(num_actors):
|
||||
dactor_portals.append(await n.start_actor(
|
||||
f'deamon_{i}',
|
||||
rpc_module_paths=[__name__],
|
||||
enable_modules=[__name__],
|
||||
))
|
||||
|
||||
func, kwargs = ria_func
|
||||
|
@ -395,7 +404,7 @@ def test_cancel_via_SIGINT(
|
|||
await trio.sleep_forever()
|
||||
|
||||
with pytest.raises(KeyboardInterrupt):
|
||||
tractor.run(main)
|
||||
trio.run(main)
|
||||
|
||||
|
||||
@no_windows
|
||||
|
@ -430,8 +439,7 @@ def test_cancel_via_SIGINT_other_task(
|
|||
os.kill(pid, signal.SIGINT)
|
||||
|
||||
with pytest.raises(KeyboardInterrupt):
|
||||
tractor.run(main)
|
||||
|
||||
trio.run(main)
|
||||
|
||||
async def spin_for(period=3):
|
||||
"Sync sleep."
|
||||
|
@ -470,4 +478,4 @@ def test_cancel_while_childs_child_in_sync_sleep(
|
|||
assert 0
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
tractor.run(main)
|
||||
trio.run(main)
|
||||
|
|
|
@ -20,8 +20,11 @@ async def test_reg_then_unreg(arb_addr):
|
|||
assert actor.is_arbiter
|
||||
assert len(actor._registry) == 1 # only self is registered
|
||||
|
||||
async with tractor.open_nursery() as n:
|
||||
portal = await n.start_actor('actor', rpc_module_paths=[__name__])
|
||||
async with tractor.open_nursery(
|
||||
arbiter_addr=arb_addr,
|
||||
) as n:
|
||||
|
||||
portal = await n.start_actor('actor', enable_modules=[__name__])
|
||||
uid = portal.channel.uid
|
||||
|
||||
async with tractor.get_arbiter(*arb_addr) as aportal:
|
||||
|
@ -66,7 +69,7 @@ async def say_hello_use_wait(other_actor):
|
|||
|
||||
@tractor_test
|
||||
@pytest.mark.parametrize('func', [say_hello, say_hello_use_wait])
|
||||
async def test_trynamic_trio(func, start_method):
|
||||
async def test_trynamic_trio(func, start_method, arb_addr):
|
||||
"""Main tractor entry point, the "master" process (for now
|
||||
acts as the "director").
|
||||
"""
|
||||
|
@ -119,74 +122,78 @@ async def spawn_and_check_registry(
|
|||
remote_arbiter: bool = False,
|
||||
with_streaming: bool = False,
|
||||
) -> None:
|
||||
actor = tractor.current_actor()
|
||||
|
||||
if remote_arbiter:
|
||||
assert not actor.is_arbiter
|
||||
async with tractor.open_root_actor(
|
||||
arbiter_addr=arb_addr,
|
||||
):
|
||||
async with tractor.get_arbiter(*arb_addr) as portal:
|
||||
# runtime needs to be up to call this
|
||||
actor = tractor.current_actor()
|
||||
|
||||
async with tractor.get_arbiter(*arb_addr) as portal:
|
||||
if remote_arbiter:
|
||||
assert not actor.is_arbiter
|
||||
|
||||
if actor.is_arbiter:
|
||||
if actor.is_arbiter:
|
||||
|
||||
async def get_reg():
|
||||
return actor._registry
|
||||
async def get_reg():
|
||||
return actor._registry
|
||||
|
||||
extra = 1 # arbiter is local root actor
|
||||
else:
|
||||
get_reg = partial(portal.run_from_ns, 'self', 'get_registry')
|
||||
extra = 2 # local root actor + remote arbiter
|
||||
extra = 1 # arbiter is local root actor
|
||||
else:
|
||||
get_reg = partial(portal.run_from_ns, 'self', 'get_registry')
|
||||
extra = 2 # local root actor + remote arbiter
|
||||
|
||||
# ensure current actor is registered
|
||||
registry = await get_reg()
|
||||
assert actor.uid in registry
|
||||
# ensure current actor is registered
|
||||
registry = await get_reg()
|
||||
assert actor.uid in registry
|
||||
|
||||
try:
|
||||
async with tractor.open_nursery() as n:
|
||||
async with trio.open_nursery() as trion:
|
||||
try:
|
||||
async with tractor.open_nursery() as n:
|
||||
async with trio.open_nursery() as trion:
|
||||
|
||||
portals = {}
|
||||
for i in range(3):
|
||||
name = f'a{i}'
|
||||
if with_streaming:
|
||||
portals[name] = await n.start_actor(
|
||||
name=name, enable_modules=[__name__])
|
||||
|
||||
else: # no streaming
|
||||
portals[name] = await n.run_in_actor(
|
||||
trio.sleep_forever, name=name)
|
||||
|
||||
# wait on last actor to come up
|
||||
async with tractor.wait_for_actor(name):
|
||||
registry = await get_reg()
|
||||
for uid in n._children:
|
||||
assert uid in registry
|
||||
|
||||
assert len(portals) + extra == len(registry)
|
||||
|
||||
portals = {}
|
||||
for i in range(3):
|
||||
name = f'a{i}'
|
||||
if with_streaming:
|
||||
portals[name] = await n.start_actor(
|
||||
name=name, enable_modules=[__name__])
|
||||
await trio.sleep(0.1)
|
||||
|
||||
else: # no streaming
|
||||
portals[name] = await n.run_in_actor(
|
||||
trio.sleep_forever, name=name)
|
||||
pts = list(portals.values())
|
||||
for p in pts[:-1]:
|
||||
trion.start_soon(stream_from, p)
|
||||
|
||||
# wait on last actor to come up
|
||||
async with tractor.wait_for_actor(name):
|
||||
registry = await get_reg()
|
||||
for uid in n._children:
|
||||
assert uid in registry
|
||||
# stream for 1 sec
|
||||
trion.start_soon(cancel, use_signal, 1)
|
||||
|
||||
assert len(portals) + extra == len(registry)
|
||||
last_p = pts[-1]
|
||||
await stream_from(last_p)
|
||||
|
||||
if with_streaming:
|
||||
await trio.sleep(0.1)
|
||||
else:
|
||||
await cancel(use_signal)
|
||||
|
||||
pts = list(portals.values())
|
||||
for p in pts[:-1]:
|
||||
trion.start_soon(stream_from, p)
|
||||
finally:
|
||||
with trio.CancelScope(shield=True):
|
||||
await trio.sleep(0.5)
|
||||
|
||||
# stream for 1 sec
|
||||
trion.start_soon(cancel, use_signal, 1)
|
||||
|
||||
last_p = pts[-1]
|
||||
await stream_from(last_p)
|
||||
|
||||
else:
|
||||
await cancel(use_signal)
|
||||
|
||||
finally:
|
||||
with trio.CancelScope(shield=True):
|
||||
await trio.sleep(0.5)
|
||||
|
||||
# all subactors should have de-registered
|
||||
registry = await get_reg()
|
||||
assert len(registry) == extra
|
||||
assert actor.uid in registry
|
||||
# all subactors should have de-registered
|
||||
registry = await get_reg()
|
||||
assert len(registry) == extra
|
||||
assert actor.uid in registry
|
||||
|
||||
|
||||
@pytest.mark.parametrize('use_signal', [False, True])
|
||||
|
@ -201,7 +208,7 @@ def test_subactors_unregister_on_cancel(
|
|||
deregistering themselves with the arbiter.
|
||||
"""
|
||||
with pytest.raises(KeyboardInterrupt):
|
||||
tractor.run(
|
||||
trio.run(
|
||||
partial(
|
||||
spawn_and_check_registry,
|
||||
arb_addr,
|
||||
|
@ -209,7 +216,6 @@ def test_subactors_unregister_on_cancel(
|
|||
remote_arbiter=False,
|
||||
with_streaming=with_streaming,
|
||||
),
|
||||
arbiter_addr=arb_addr
|
||||
)
|
||||
|
||||
|
||||
|
@ -227,7 +233,7 @@ def test_subactors_unregister_on_cancel_remote_daemon(
|
|||
tree) arbiter.
|
||||
"""
|
||||
with pytest.raises(KeyboardInterrupt):
|
||||
tractor.run(
|
||||
trio.run(
|
||||
partial(
|
||||
spawn_and_check_registry,
|
||||
arb_addr,
|
||||
|
@ -235,8 +241,6 @@ def test_subactors_unregister_on_cancel_remote_daemon(
|
|||
remote_arbiter=True,
|
||||
with_streaming=with_streaming,
|
||||
),
|
||||
# XXX: required to use remote daemon!
|
||||
arbiter_addr=arb_addr
|
||||
)
|
||||
|
||||
|
||||
|
@ -258,49 +262,52 @@ async def close_chans_before_nursery(
|
|||
else:
|
||||
entries_at_end = 1
|
||||
|
||||
async with tractor.get_arbiter(*arb_addr) as aportal:
|
||||
try:
|
||||
get_reg = partial(aportal.run_from_ns, 'self', 'get_registry')
|
||||
async with tractor.open_root_actor(
|
||||
arbiter_addr=arb_addr,
|
||||
):
|
||||
async with tractor.get_arbiter(*arb_addr) as aportal:
|
||||
try:
|
||||
get_reg = partial(aportal.run_from_ns, 'self', 'get_registry')
|
||||
|
||||
async with tractor.open_nursery() as tn:
|
||||
portal1 = await tn.start_actor(
|
||||
name='consumer1', enable_modules=[__name__])
|
||||
portal2 = await tn.start_actor(
|
||||
'consumer2', enable_modules=[__name__])
|
||||
async with tractor.open_nursery() as tn:
|
||||
portal1 = await tn.start_actor(
|
||||
name='consumer1', enable_modules=[__name__])
|
||||
portal2 = await tn.start_actor(
|
||||
'consumer2', enable_modules=[__name__])
|
||||
|
||||
# TODO: compact this back as was in last commit once
|
||||
# 3.9+, see https://github.com/goodboy/tractor/issues/207
|
||||
async with portal1.open_stream_from(stream_forever) as agen1:
|
||||
async with portal2.open_stream_from(
|
||||
stream_forever
|
||||
) as agen2:
|
||||
async with trio.open_nursery() as n:
|
||||
n.start_soon(streamer, agen1)
|
||||
n.start_soon(cancel, use_signal, .5)
|
||||
try:
|
||||
await streamer(agen2)
|
||||
finally:
|
||||
# Kill the root nursery thus resulting in
|
||||
# normal arbiter channel ops to fail during
|
||||
# teardown. It doesn't seem like this is
|
||||
# reliably triggered by an external SIGINT.
|
||||
# tractor.current_actor()._root_nursery.cancel_scope.cancel()
|
||||
# TODO: compact this back as was in last commit once
|
||||
# 3.9+, see https://github.com/goodboy/tractor/issues/207
|
||||
async with portal1.open_stream_from(stream_forever) as agen1:
|
||||
async with portal2.open_stream_from(
|
||||
stream_forever
|
||||
) as agen2:
|
||||
async with trio.open_nursery() as n:
|
||||
n.start_soon(streamer, agen1)
|
||||
n.start_soon(cancel, use_signal, .5)
|
||||
try:
|
||||
await streamer(agen2)
|
||||
finally:
|
||||
# Kill the root nursery thus resulting in
|
||||
# normal arbiter channel ops to fail during
|
||||
# teardown. It doesn't seem like this is
|
||||
# reliably triggered by an external SIGINT.
|
||||
# tractor.current_actor()._root_nursery.cancel_scope.cancel()
|
||||
|
||||
# XXX: THIS IS THE KEY THING that happens
|
||||
# **before** exiting the actor nursery block
|
||||
# XXX: THIS IS THE KEY THING that happens
|
||||
# **before** exiting the actor nursery block
|
||||
|
||||
# also kill off channels cuz why not
|
||||
await agen1.aclose()
|
||||
await agen2.aclose()
|
||||
finally:
|
||||
with trio.CancelScope(shield=True):
|
||||
await trio.sleep(1)
|
||||
# also kill off channels cuz why not
|
||||
await agen1.aclose()
|
||||
await agen2.aclose()
|
||||
finally:
|
||||
with trio.CancelScope(shield=True):
|
||||
await trio.sleep(1)
|
||||
|
||||
# all subactors should have de-registered
|
||||
registry = await get_reg()
|
||||
assert portal1.channel.uid not in registry
|
||||
assert portal2.channel.uid not in registry
|
||||
assert len(registry) == entries_at_end
|
||||
# all subactors should have de-registered
|
||||
registry = await get_reg()
|
||||
assert portal1.channel.uid not in registry
|
||||
assert portal2.channel.uid not in registry
|
||||
assert len(registry) == entries_at_end
|
||||
|
||||
|
||||
@pytest.mark.parametrize('use_signal', [False, True])
|
||||
|
@ -314,15 +321,13 @@ def test_close_channel_explicit(
|
|||
results in subactor(s) deregistering from the arbiter.
|
||||
"""
|
||||
with pytest.raises(KeyboardInterrupt):
|
||||
tractor.run(
|
||||
trio.run(
|
||||
partial(
|
||||
close_chans_before_nursery,
|
||||
arb_addr,
|
||||
use_signal,
|
||||
remote_arbiter=False,
|
||||
),
|
||||
# XXX: required to use remote daemon!
|
||||
arbiter_addr=arb_addr
|
||||
)
|
||||
|
||||
|
||||
|
@ -338,13 +343,11 @@ def test_close_channel_explicit_remote_arbiter(
|
|||
results in subactor(s) deregistering from the arbiter.
|
||||
"""
|
||||
with pytest.raises(KeyboardInterrupt):
|
||||
tractor.run(
|
||||
trio.run(
|
||||
partial(
|
||||
close_chans_before_nursery,
|
||||
arb_addr,
|
||||
use_signal,
|
||||
remote_arbiter=True,
|
||||
),
|
||||
# XXX: required to use remote daemon!
|
||||
arbiter_addr=arb_addr
|
||||
)
|
||||
|
|
|
@ -15,8 +15,8 @@ async def test_no_arbitter():
|
|||
"""An arbitter must be established before any nurseries
|
||||
can be created.
|
||||
|
||||
(In other words ``tractor.run`` must be used instead of ``trio.run`` as is
|
||||
done by the ``pytest-trio`` plugin.)
|
||||
(In other words ``tractor.open_root_actor()`` must be engaged at
|
||||
some point?)
|
||||
"""
|
||||
with pytest.raises(RuntimeError):
|
||||
with tractor.open_nursery():
|
||||
|
@ -49,7 +49,8 @@ async def test_self_is_registered_localportal(arb_addr):
|
|||
assert isinstance(portal, tractor._portal.LocalPortal)
|
||||
|
||||
with trio.fail_after(0.2):
|
||||
sockaddr = await portal.run_from_ns('self', 'wait_for_actor', name='root')
|
||||
sockaddr = await portal.run_from_ns(
|
||||
'self', 'wait_for_actor', name='root')
|
||||
assert sockaddr[0] == arb_addr
|
||||
|
||||
|
||||
|
@ -59,15 +60,19 @@ def test_local_actor_async_func(arb_addr):
|
|||
nums = []
|
||||
|
||||
async def print_loop():
|
||||
# arbiter is started in-proc if dne
|
||||
assert tractor.current_actor().is_arbiter
|
||||
|
||||
for i in range(10):
|
||||
nums.append(i)
|
||||
await trio.sleep(0.1)
|
||||
async with tractor.open_root_actor(
|
||||
arbiter_addr=arb_addr,
|
||||
):
|
||||
# arbiter is started in-proc if dne
|
||||
assert tractor.current_actor().is_arbiter
|
||||
|
||||
for i in range(10):
|
||||
nums.append(i)
|
||||
await trio.sleep(0.1)
|
||||
|
||||
start = time.time()
|
||||
tractor.run(print_loop, arbiter_addr=arb_addr)
|
||||
trio.run(print_loop)
|
||||
|
||||
# ensure the sleeps were actually awaited
|
||||
assert time.time() - start >= 1
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
"""
|
||||
Multiple python programs invoking ``tractor.run()``
|
||||
Multiple python programs invoking the runtime.
|
||||
"""
|
||||
import platform
|
||||
import time
|
||||
|
||||
import pytest
|
||||
import trio
|
||||
import tractor
|
||||
from conftest import (
|
||||
tractor_test,
|
||||
|
@ -45,8 +46,13 @@ async def test_cancel_remote_arbiter(daemon, arb_addr):
|
|||
def test_register_duplicate_name(daemon, arb_addr):
|
||||
|
||||
async def main():
|
||||
assert not tractor.current_actor().is_arbiter
|
||||
async with tractor.open_nursery() as n:
|
||||
|
||||
async with tractor.open_nursery(
|
||||
arbiter_addr=arb_addr,
|
||||
) as n:
|
||||
|
||||
assert not tractor.current_actor().is_arbiter
|
||||
|
||||
p1 = await n.start_actor('doggy')
|
||||
p2 = await n.start_actor('doggy')
|
||||
|
||||
|
@ -57,4 +63,4 @@ def test_register_duplicate_name(daemon, arb_addr):
|
|||
|
||||
# run it manually since we want to start **after**
|
||||
# the other "daemon" program
|
||||
tractor.run(main, arbiter_addr=arb_addr)
|
||||
trio.run(main)
|
||||
|
|
|
@ -46,8 +46,9 @@ async def pubber(get_topics, seed=10):
|
|||
|
||||
|
||||
async def subs(
|
||||
which, pub_actor_name, seed=10,
|
||||
portal=None,
|
||||
which,
|
||||
pub_actor_name,
|
||||
seed=10,
|
||||
task_status=trio.TASK_STATUS_IGNORED,
|
||||
):
|
||||
if len(which) == 1:
|
||||
|
@ -61,7 +62,9 @@ async def subs(
|
|||
return isinstance(i, int)
|
||||
|
||||
# TODO: https://github.com/goodboy/tractor/issues/207
|
||||
async with tractor.find_actor(pub_actor_name) as portal:
|
||||
async with tractor.wait_for_actor(pub_actor_name) as portal:
|
||||
assert portal
|
||||
|
||||
async with portal.open_stream_from(
|
||||
pubber,
|
||||
topics=which,
|
||||
|
@ -164,7 +167,10 @@ def test_multi_actor_subs_arbiter_pub(
|
|||
|
||||
async def main():
|
||||
|
||||
async with tractor.open_nursery() as n:
|
||||
async with tractor.open_nursery(
|
||||
arbiter_addr=arb_addr,
|
||||
enable_modules=[__name__],
|
||||
) as n:
|
||||
|
||||
name = 'root'
|
||||
|
||||
|
@ -172,7 +178,7 @@ def test_multi_actor_subs_arbiter_pub(
|
|||
# start the publisher as a daemon
|
||||
master_portal = await n.start_actor(
|
||||
'streamer',
|
||||
rpc_module_paths=[__name__],
|
||||
enable_modules=[__name__],
|
||||
)
|
||||
|
||||
even_portal = await n.run_in_actor(
|
||||
|
@ -232,7 +238,6 @@ def test_multi_actor_subs_arbiter_pub(
|
|||
assert 'even' not in get_topics()
|
||||
|
||||
await odd_portal.cancel_actor()
|
||||
await trio.sleep(2)
|
||||
|
||||
if pub_actor == 'arbiter':
|
||||
while get_topics():
|
||||
|
@ -242,11 +247,7 @@ def test_multi_actor_subs_arbiter_pub(
|
|||
else:
|
||||
await master_portal.cancel_actor()
|
||||
|
||||
tractor.run(
|
||||
main,
|
||||
arbiter_addr=arb_addr,
|
||||
rpc_module_paths=[__name__],
|
||||
)
|
||||
trio.run(main)
|
||||
|
||||
|
||||
def test_single_subactor_pub_multitask_subs(
|
||||
|
@ -255,11 +256,14 @@ def test_single_subactor_pub_multitask_subs(
|
|||
):
|
||||
async def main():
|
||||
|
||||
async with tractor.open_nursery() as n:
|
||||
async with tractor.open_nursery(
|
||||
arbiter_addr=arb_addr,
|
||||
enable_modules=[__name__],
|
||||
) as n:
|
||||
|
||||
portal = await n.start_actor(
|
||||
'streamer',
|
||||
rpc_module_paths=[__name__],
|
||||
enable_modules=[__name__],
|
||||
)
|
||||
async with tractor.wait_for_actor('streamer'):
|
||||
# block until 2nd actor is initialized
|
||||
|
@ -283,8 +287,4 @@ def test_single_subactor_pub_multitask_subs(
|
|||
|
||||
await portal.cancel_actor()
|
||||
|
||||
tractor.run(
|
||||
main,
|
||||
arbiter_addr=arb_addr,
|
||||
rpc_module_paths=[__name__],
|
||||
)
|
||||
trio.run(main)
|
||||
|
|
|
@ -74,11 +74,15 @@ def test_rpc_errors(arb_addr, to_call, testdir):
|
|||
remote_err = inside_err
|
||||
|
||||
async def main():
|
||||
actor = tractor.current_actor()
|
||||
assert actor.is_arbiter
|
||||
|
||||
# spawn a subactor which calls us back
|
||||
async with tractor.open_nursery() as n:
|
||||
async with tractor.open_nursery(
|
||||
arbiter_addr=arb_addr,
|
||||
enable_modules=exposed_mods.copy(),
|
||||
) as n:
|
||||
|
||||
actor = tractor.current_actor()
|
||||
assert actor.is_arbiter
|
||||
await n.run_in_actor(
|
||||
sleep_back_actor,
|
||||
actor_name=subactor_requests_to,
|
||||
|
@ -90,15 +94,11 @@ def test_rpc_errors(arb_addr, to_call, testdir):
|
|||
func_name=funcname,
|
||||
exposed_mods=exposed_mods,
|
||||
func_defined=True if func_defined else False,
|
||||
rpc_module_paths=subactor_exposed_mods,
|
||||
enable_modules=subactor_exposed_mods,
|
||||
)
|
||||
|
||||
def run():
|
||||
tractor.run(
|
||||
main,
|
||||
arbiter_addr=arb_addr,
|
||||
rpc_module_paths=exposed_mods.copy(),
|
||||
)
|
||||
trio.run(main)
|
||||
|
||||
# handle both parameterized cases
|
||||
if exposed_mods and func_defined:
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"""
|
||||
Spawning basics
|
||||
"""
|
||||
from functools import partial
|
||||
|
||||
import pytest
|
||||
import trio
|
||||
|
@ -12,41 +11,50 @@ from conftest import tractor_test
|
|||
data_to_pass_down = {'doggy': 10, 'kitty': 4}
|
||||
|
||||
|
||||
async def spawn(is_arbiter, data):
|
||||
async def spawn(is_arbiter, data, arb_addr):
|
||||
namespaces = [__name__]
|
||||
|
||||
await trio.sleep(0.1)
|
||||
actor = tractor.current_actor()
|
||||
assert actor.is_arbiter == is_arbiter
|
||||
data == data_to_pass_down
|
||||
|
||||
if actor.is_arbiter:
|
||||
async with tractor.open_nursery() as nursery:
|
||||
# forks here
|
||||
portal = await nursery.run_in_actor(
|
||||
spawn,
|
||||
is_arbiter=False,
|
||||
name='sub-actor',
|
||||
data=data,
|
||||
rpc_module_paths=namespaces,
|
||||
)
|
||||
async with tractor.open_root_actor(
|
||||
arbiter_addr=arb_addr,
|
||||
):
|
||||
|
||||
assert len(nursery._children) == 1
|
||||
assert portal.channel.uid in tractor.current_actor()._peers
|
||||
# be sure we can still get the result
|
||||
result = await portal.result()
|
||||
assert result == 10
|
||||
return result
|
||||
else:
|
||||
return 10
|
||||
actor = tractor.current_actor()
|
||||
assert actor.is_arbiter == is_arbiter
|
||||
data = data_to_pass_down
|
||||
|
||||
if actor.is_arbiter:
|
||||
|
||||
async with tractor.open_nursery(
|
||||
) as nursery:
|
||||
|
||||
# forks here
|
||||
portal = await nursery.run_in_actor(
|
||||
spawn,
|
||||
is_arbiter=False,
|
||||
name='sub-actor',
|
||||
data=data,
|
||||
arb_addr=arb_addr,
|
||||
enable_modules=namespaces,
|
||||
)
|
||||
|
||||
assert len(nursery._children) == 1
|
||||
assert portal.channel.uid in tractor.current_actor()._peers
|
||||
# be sure we can still get the result
|
||||
result = await portal.result()
|
||||
assert result == 10
|
||||
return result
|
||||
else:
|
||||
return 10
|
||||
|
||||
|
||||
def test_local_arbiter_subactor_global_state(arb_addr):
|
||||
result = tractor.run(
|
||||
partial(spawn, data=data_to_pass_down),
|
||||
result = trio.run(
|
||||
spawn,
|
||||
True,
|
||||
name='arbiter',
|
||||
arbiter_addr=arb_addr,
|
||||
data_to_pass_down,
|
||||
arb_addr,
|
||||
)
|
||||
assert result == 10
|
||||
|
||||
|
@ -67,7 +75,7 @@ async def test_movie_theatre_convo(start_method):
|
|||
portal = await n.start_actor(
|
||||
'frank',
|
||||
# enable the actor to run funcs from this current module
|
||||
rpc_module_paths=[__name__],
|
||||
enable_modules=[__name__],
|
||||
)
|
||||
|
||||
print(await portal.run(movie_theatre_question))
|
||||
|
@ -121,19 +129,20 @@ def test_loglevel_propagated_to_subactor(
|
|||
level = 'critical'
|
||||
|
||||
async def main():
|
||||
async with tractor.open_nursery() as tn:
|
||||
async with tractor.open_nursery(
|
||||
name='arbiter',
|
||||
loglevel=level,
|
||||
start_method=start_method,
|
||||
arbiter_addr=arb_addr,
|
||||
|
||||
) as tn:
|
||||
await tn.run_in_actor(
|
||||
check_loglevel,
|
||||
level=level,
|
||||
)
|
||||
|
||||
tractor.run(
|
||||
main,
|
||||
name='arbiter',
|
||||
loglevel=level,
|
||||
start_method=start_method,
|
||||
arbiter_addr=arb_addr,
|
||||
)
|
||||
trio.run(main)
|
||||
|
||||
# ensure subactor spits log message on stderr
|
||||
captured = capfd.readouterr()
|
||||
assert 'yoyoyo' in captured.err
|
||||
|
|
|
@ -50,14 +50,24 @@ async def context_stream(ctx, sequence):
|
|||
assert cs.cancelled_caught
|
||||
|
||||
|
||||
async def stream_from_single_subactor(stream_func):
|
||||
async def stream_from_single_subactor(
|
||||
arb_addr,
|
||||
start_method,
|
||||
stream_func,
|
||||
):
|
||||
"""Verify we can spawn a daemon actor and retrieve streamed data.
|
||||
"""
|
||||
async with tractor.find_actor('streamerd') as portals:
|
||||
# only one per host address, spawns an actor if None
|
||||
|
||||
async with tractor.open_nursery(
|
||||
arbiter_addr=arb_addr,
|
||||
start_method=start_method,
|
||||
) as nursery:
|
||||
|
||||
async with tractor.find_actor('streamerd') as portals:
|
||||
|
||||
if not portals:
|
||||
|
||||
if not portals:
|
||||
# only one per host address, spawns an actor if None
|
||||
async with tractor.open_nursery() as nursery:
|
||||
# no brokerd actor found
|
||||
portal = await nursery.start_actor(
|
||||
'streamerd',
|
||||
|
@ -101,13 +111,13 @@ async def stream_from_single_subactor(stream_func):
|
|||
def test_stream_from_single_subactor(arb_addr, start_method, stream_func):
|
||||
"""Verify streaming from a spawned async generator.
|
||||
"""
|
||||
tractor.run(
|
||||
trio.run(
|
||||
partial(
|
||||
stream_from_single_subactor,
|
||||
arb_addr,
|
||||
start_method,
|
||||
stream_func=stream_func,
|
||||
),
|
||||
arbiter_addr=arb_addr,
|
||||
start_method=start_method,
|
||||
)
|
||||
|
||||
|
||||
|
@ -208,9 +218,10 @@ async def a_quadruple_example():
|
|||
return result_stream
|
||||
|
||||
|
||||
async def cancel_after(wait):
|
||||
with trio.move_on_after(wait):
|
||||
return await a_quadruple_example()
|
||||
async def cancel_after(wait, arb_addr):
|
||||
async with tractor.open_root_actor(arbiter_addr=arb_addr):
|
||||
with trio.move_on_after(wait):
|
||||
return await a_quadruple_example()
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
|
@ -222,7 +233,7 @@ def time_quad_ex(arb_addr, ci_env, spawn_backend):
|
|||
|
||||
timeout = 7 if platform.system() in ('Windows', 'Darwin') else 4
|
||||
start = time.time()
|
||||
results = tractor.run(cancel_after, timeout, arbiter_addr=arb_addr)
|
||||
results = trio.run(cancel_after, timeout, arb_addr)
|
||||
diff = time.time() - start
|
||||
assert results
|
||||
return results, diff
|
||||
|
@ -249,7 +260,7 @@ def test_not_fast_enough_quad(
|
|||
"""
|
||||
results, diff = time_quad_ex
|
||||
delay = max(diff - cancel_delay, 0)
|
||||
results = tractor.run(cancel_after, delay, arbiter_addr=arb_addr)
|
||||
results = trio.run(cancel_after, delay, arb_addr)
|
||||
system = platform.system()
|
||||
if system in ('Windows', 'Darwin') and results is not None:
|
||||
# In CI envoirments it seems later runs are quicker then the first
|
||||
|
|
|
@ -113,6 +113,7 @@ class ActorNursery:
|
|||
name: Optional[str] = None,
|
||||
bind_addr: Tuple[str, int] = _default_bind_addr,
|
||||
rpc_module_paths: Optional[List[str]] = None,
|
||||
enable_modules: List[str] = None,
|
||||
loglevel: str = None, # set log level per subactor
|
||||
**kwargs, # explicit args to ``fn``
|
||||
) -> Portal:
|
||||
|
@ -131,7 +132,9 @@ class ActorNursery:
|
|||
|
||||
portal = await self.start_actor(
|
||||
name,
|
||||
rpc_module_paths=[mod_path] + (rpc_module_paths or []),
|
||||
enable_modules=[mod_path] + (
|
||||
enable_modules or rpc_module_paths or []
|
||||
),
|
||||
bind_addr=bind_addr,
|
||||
loglevel=loglevel,
|
||||
# use the run_in_actor nursery
|
||||
|
@ -366,7 +369,6 @@ async def open_nursery(
|
|||
async with _open_and_supervise_one_cancels_all_nursery(
|
||||
actor
|
||||
) as anursery:
|
||||
|
||||
yield anursery
|
||||
|
||||
else: # sub-nursery case
|
||||
|
|
Loading…
Reference in New Issue