import tractor
import trio


async def breakpoint_forever():
    "Indefinitely re-enter debugger in child actor."
    while True:
        await trio.sleep(0.1)
        await tractor.pause()


async def name_error():
    "Raise a ``NameError``"
    getattr(doggypants)  # noqa


async def spawn_error():
    """"A nested nursery that triggers another ``NameError``.
    """
    async with tractor.open_nursery() as n:
        portal = await n.run_in_actor(
            name_error,
            name='name_error_1',
        )
        return await portal.result()


async def main():
    """The main ``tractor`` routine.

    The process tree should look as approximately as follows:

    -python examples/debugging/multi_subactors.py
    |-python -m tractor._child --uid ('name_error', 'a7caf490 ...)
    |-python -m tractor._child --uid ('bp_forever', '1f787a7e ...)
    `-python -m tractor._child --uid ('spawn_error', '52ee14a5 ...)
       `-python -m tractor._child --uid ('name_error', '3391222c ...)
    """
    async with tractor.open_nursery(
        debug_mode=True,
        # loglevel='runtime',
    ) as n:

        # Spawn both actors, don't bother with collecting results
        # (would result in a different debugger outcome due to parent's
        # cancellation).
        await n.run_in_actor(breakpoint_forever)
        await n.run_in_actor(name_error)
        await n.run_in_actor(spawn_error)


if __name__ == '__main__':
    trio.run(main)