diff --git a/examples/debugging/asyncio_bp.py b/examples/debugging/asyncio_bp.py new file mode 100644 index 0000000..882ebbe --- /dev/null +++ b/examples/debugging/asyncio_bp.py @@ -0,0 +1,79 @@ +import asyncio + +import trio +import tractor + + +async def bp_then_error( + to_trio: trio.MemorySendChannel, + from_trio: asyncio.Queue, + +) -> None: + + # sync with ``trio``-side (caller) task + to_trio.send_nowait('start') + + # NOTE: what happens here inside the hook needs some refinement.. + # => seems like it's still `._debug._set_trace()` but + # we set `Lock.local_task_in_debug = 'sync'`, we probably want + # some further, at least, meta-data about the task/actoq in debug + # in terms of making it clear it's asyncio mucking about. + + breakpoint() + + await asyncio.sleep(0.5) + raise ValueError('blah') + + +async def aio_sleep_forever(): + await asyncio.sleep(float('inf')) + + +@tractor.context +async def trio_ctx( + ctx: tractor.Context, +): + + # this will block until the ``asyncio`` task sends a "first" + # message, see first line in above func. + async with ( + tractor.to_asyncio.open_channel_from(bp_then_error) as (first, chan), + trio.open_nursery() as n, + ): + + assert first == 'start' + await ctx.started(first) + + n.start_soon( + tractor.to_asyncio.run_task, + aio_sleep_forever, + ) + await trio.sleep_forever() + + +async def main(): + + async with tractor.open_nursery() as n: + + p = await n.start_actor( + 'aio_daemon', + enable_modules=[__name__], + infect_asyncio=True, + debug_mode=True, + loglevel='cancel', + ) + + async with p.open_context(trio_ctx) as (ctx, first): + + assert first == 'start' + await trio.sleep_forever() + + assert 0 + + # TODO: case where we cancel from trio-side while asyncio task + # has debugger lock? + # await p.cancel_actor() + + +if __name__ == '__main__': + trio.run(main)