Skip to content

Commit

Permalink
Merge pull request #129 from goodboy/multiproc_debug
Browse files Browse the repository at this point in the history
Wen? Multiprocessing-native debugger now!
  • Loading branch information
goodboy authored Oct 14, 2020
2 parents ce5c529 + 61a8df3 commit 7115d6c
Show file tree
Hide file tree
Showing 29 changed files with 1,259 additions and 151 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ jobs:
- name: Install dependencies
run: pip install -U . -r requirements-test.txt -r requirements-docs.txt --upgrade-strategy eager
- name: Run tests
run: pytest tests/ --spawn-backend=${{ matrix.spawn_backend }}
run: pytest tests/ --spawn-backend=${{ matrix.spawn_backend }} -rs
68 changes: 0 additions & 68 deletions .travis.yml

This file was deleted.

7 changes: 4 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ tractor
=======
A `structured concurrent`_, async-native "`actor model`_" built on trio_ and multiprocessing_.

|travis| |docs|
|gh_actions|
|docs|

.. _actor model: https://en.wikipedia.org/wiki/Actor_model
.. _trio: https://github.com/python-trio/trio
Expand Down Expand Up @@ -57,8 +58,8 @@ channel`_!
.. _matrix channel: https://matrix.to/#/!tractor:matrix.org


.. |travis| image:: https://img.shields.io/travis/goodboy/tractor/master.svg
:target: https://travis-ci.org/goodboy/tractor
.. |gh_actions| image:: https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fgoodboy%2Ftractor%2Fbadge&style=popout-square
:target: https://actions-badge.atrox.dev/goodboy/tractor/goto
.. |docs| image:: https://readthedocs.org/projects/tractor/badge/?version=latest
:target: https://tractor.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import tractor


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


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


async def spawn_until(depth=0):
""""A nested nursery that triggers another ``NameError``.
"""
async with tractor.open_nursery() as n:
if depth < 1:
# await n.run_in_actor('breakpoint_forever', breakpoint_forever)
await n.run_in_actor('name_error', name_error)
else:
depth -= 1
await n.run_in_actor(f'spawn_until_{depth}', spawn_until, depth=depth)


async def main():
"""The main ``tractor`` routine.
The process tree should look as approximately as follows when the debugger
first engages:
python examples/debugging/multi_nested_subactors_bp_forever.py
├─ python -m tractor._child --uid ('spawner1', '7eab8462 ...)
│ └─ python -m tractor._child --uid ('spawn_until_3', 'afcba7a8 ...)
│ └─ python -m tractor._child --uid ('spawn_until_2', 'd2433d13 ...)
│ └─ python -m tractor._child --uid ('spawn_until_1', '1df589de ...)
│ └─ python -m tractor._child --uid ('spawn_until_0', '3720602b ...)
└─ python -m tractor._child --uid ('spawner0', '1d42012b ...)
└─ python -m tractor._child --uid ('spawn_until_2', '2877e155 ...)
└─ python -m tractor._child --uid ('spawn_until_1', '0502d786 ...)
└─ python -m tractor._child --uid ('spawn_until_0', 'de918e6d ...)
"""
async with tractor.open_nursery() as n:

# spawn both actors
portal = await n.run_in_actor('spawner0', spawn_until, depth=3)
portal1 = await n.run_in_actor('spawner1', spawn_until, depth=4)

# gah still an issue here.
# await portal.result()
# await portal1.result()


if __name__ == '__main__':
tractor.run(main, debug_mode=True)
43 changes: 43 additions & 0 deletions examples/debugging/multi_subactor_root_errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import tractor


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


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_1', name_error)
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 ('spawn_error', '52ee14a5 ...)
`-python -m tractor._child --uid ('name_error', '3391222c ...)
"""
async with tractor.open_nursery() as n:

# spawn both actors
portal = await n.run_in_actor('name_error', name_error)
portal1 = await n.run_in_actor('spawn_error', spawn_error)

# trigger a root actor error
assert 0

# attempt to collect results (which raises error in parent)
# still has some issues where the parent seems to get stuck
await portal.result()
await portal1.result()


if __name__ == '__main__':
tractor.run(main, debug_mode=True)
47 changes: 47 additions & 0 deletions examples/debugging/multi_subactors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import tractor
import trio


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


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


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_1', name_error)
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() 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('bp_forever', breakpoint_forever)
await n.run_in_actor('name_error', name_error)
await n.run_in_actor('spawn_error', spawn_error)


if __name__ == '__main__':
tractor.run(main, debug_mode=True)
15 changes: 15 additions & 0 deletions examples/debugging/root_actor_breakpoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import trio
import tractor


async def main():

await trio.sleep(0.1)

await tractor.breakpoint()

await trio.sleep(0.1)


if __name__ == '__main__':
tractor.run(main, debug_mode=True)
11 changes: 11 additions & 0 deletions examples/debugging/root_actor_breakpoint_forever.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import tractor


async def main():

while True:
await tractor.breakpoint()


if __name__ == '__main__':
tractor.run(main, debug_mode=True)
9 changes: 9 additions & 0 deletions examples/debugging/root_actor_error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import tractor


async def main():
assert 0


if __name__ == '__main__':
tractor.run(main, debug_mode=True)
48 changes: 48 additions & 0 deletions examples/debugging/root_cancelled_but_child_is_in_tty_lock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import tractor


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


async def spawn_until(depth=0):
""""A nested nursery that triggers another ``NameError``.
"""
async with tractor.open_nursery() as n:
if depth < 1:
# await n.run_in_actor('breakpoint_forever', breakpoint_forever)
await n.run_in_actor('name_error', name_error)
else:
depth -= 1
await n.run_in_actor(f'spawn_until_{depth}', spawn_until, depth=depth)


async def main():
"""The main ``tractor`` routine.
The process tree should look as approximately as follows when the debugger
first engages:
python examples/debugging/multi_nested_subactors_bp_forever.py
├─ python -m tractor._child --uid ('spawner1', '7eab8462 ...)
│ └─ python -m tractor._child --uid ('spawn_until_0', '3720602b ...)
│ └─ python -m tractor._child --uid ('name_error', '505bf71d ...)
└─ python -m tractor._child --uid ('spawner0', '1d42012b ...)
└─ python -m tractor._child --uid ('name_error', '6c2733b8 ...)
"""
async with tractor.open_nursery() as n:

# spawn both actors
portal = await n.run_in_actor('spawner0', spawn_until, depth=0)
portal1 = await n.run_in_actor('spawner1', spawn_until, depth=1)

# nursery cancellation should be triggered due to propagated error
await portal.result()
await portal1.result()


if __name__ == '__main__':
tractor.run(main, debug_mode=True, loglevel='warning')
25 changes: 25 additions & 0 deletions examples/debugging/subactor_breakpoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import trio
import tractor


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


async def main():

async with tractor.open_nursery() as n:

portal = await n.run_in_actor(
'breakpoint_forever',
breakpoint_forever,
)
await portal.result()


if __name__ == '__main__':
tractor.run(main, debug_mode=True)
16 changes: 16 additions & 0 deletions examples/debugging/subactor_error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import tractor


async def name_error():
getattr(doggypants)


async def main():
async with tractor.open_nursery() as n:

portal = await n.run_in_actor('name_error', name_error)
await portal.result()


if __name__ == '__main__':
tractor.run(main, debug_mode=True)
1 change: 1 addition & 0 deletions requirements-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ pytest-trio
pdbpp
mypy
trio_typing
pexpect
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
],
install_requires=[
'msgpack', 'trio>0.8', 'async_generator', 'colorlog', 'wrapt',
'trio_typing'
'trio_typing', 'pdbpp',
],
tests_require=['pytest'],
python_requires=">=3.7",
Expand Down
Loading

0 comments on commit 7115d6c

Please sign in to comment.