Compare commits

...

9 Commits

Author SHA1 Message Date
Tyler Goodlet adcb70c521 pdbp: adding typing to config settings vars 2023-05-08 12:07:07 -04:00
Tyler Goodlet c49cace550 TOSQUASH 4759e30: turn it ON i guess? XD 2023-05-08 12:06:19 -04:00
Tyler Goodlet 8b9cc44950 `pdbp`: turn off line truncating by default, fixes terminal resizing stuff 2023-04-20 10:11:41 -04:00
Tyler Goodlet adaea6e6ef Yeahh.. maybe sticky off by default is a little better for us XD 2023-04-17 16:40:08 -04:00
Tyler Goodlet f0db4f14b5 Hide actor nursery exit frame 2023-04-15 19:51:29 -04:00
Tyler Goodlet 9ab7c4af01 First try: switch debug machinery over to `pdbp` B) 2023-04-15 19:51:29 -04:00
Tyler Goodlet 4ac1da3fb2 Use multiline import for debug mod 2023-04-15 19:51:29 -04:00
Tyler Goodlet 174b73234c Change over debugger tests to use `PROMPT` var.. 2023-04-15 19:51:29 -04:00
Tyler Goodlet 84c9ff6fd8 Switch to `pdbp` since noone is maintaining `pdbpp` 2023-04-15 19:51:29 -04:00
5 changed files with 74 additions and 67 deletions

View File

@ -26,12 +26,12 @@ with open('docs/README.rst', encoding='utf-8') as f:
setup( setup(
name="tractor", name="tractor",
version='0.1.0a6dev0', # alpha zone version='0.1.0a6dev0', # alpha zone
description='structured concurrrent "actors"', description='structured concurrrent `trio`-"actors"',
long_description=readme, long_description=readme,
license='AGPLv3', license='AGPLv3',
author='Tyler Goodlet', author='Tyler Goodlet',
maintainer='Tyler Goodlet', maintainer='Tyler Goodlet',
maintainer_email='jgbt@protonmail.com', maintainer_email='goodboy_foss@protonmail.com',
url='https://github.com/goodboy/tractor', url='https://github.com/goodboy/tractor',
platforms=['linux', 'windows'], platforms=['linux', 'windows'],
packages=[ packages=[
@ -52,16 +52,14 @@ setup(
# tooling # tooling
'tricycle', 'tricycle',
'trio_typing', 'trio_typing',
# tooling
'colorlog', 'colorlog',
'wrapt', 'wrapt',
# serialization # IPC serialization
'msgspec', 'msgspec',
# debug mode REPL # debug mode REPL
'pdbpp', 'pdbp',
# pip ref docs on these specs: # pip ref docs on these specs:
# https://pip.pypa.io/en/stable/reference/requirement-specifiers/#examples # https://pip.pypa.io/en/stable/reference/requirement-specifiers/#examples
@ -73,10 +71,9 @@ setup(
# https://github.com/pdbpp/fancycompleter/issues/37 # https://github.com/pdbpp/fancycompleter/issues/37
'pyreadline3 ; platform_system == "Windows"', 'pyreadline3 ; platform_system == "Windows"',
], ],
tests_require=['pytest'], tests_require=['pytest'],
python_requires=">=3.9", python_requires=">=3.10",
keywords=[ keywords=[
'trio', 'trio',
'async', 'async',

View File

@ -95,7 +95,7 @@ def spawn(
return _spawn return _spawn
PROMPT = r"\(Pdb\+\+\)" PROMPT = r"\(Pdb\+\)"
def expect( def expect(
@ -151,6 +151,7 @@ def ctlc(
use_ctlc = request.param use_ctlc = request.param
# TODO: we can remove this bc pdbp right?
if ( if (
sys.version_info <= (3, 10) sys.version_info <= (3, 10)
and use_ctlc and use_ctlc
@ -231,7 +232,7 @@ def test_root_actor_bp(spawn, user_in_out):
child = spawn('root_actor_breakpoint') child = spawn('root_actor_breakpoint')
# scan for the pdbpp prompt # scan for the pdbpp prompt
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
assert 'Error' not in str(child.before) assert 'Error' not in str(child.before)
@ -272,7 +273,7 @@ def do_ctlc(
if expect_prompt: if expect_prompt:
before = str(child.before.decode()) before = str(child.before.decode())
time.sleep(delay) time.sleep(delay)
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
time.sleep(delay) time.sleep(delay)
if patt: if patt:
@ -291,7 +292,7 @@ def test_root_actor_bp_forever(
# entries # entries
for _ in range(10): for _ in range(10):
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
if ctlc: if ctlc:
do_ctlc(child) do_ctlc(child)
@ -301,7 +302,7 @@ def test_root_actor_bp_forever(
# do one continue which should trigger a # do one continue which should trigger a
# new task to lock the tty # new task to lock the tty
child.sendline('continue') child.sendline('continue')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
# seems that if we hit ctrl-c too fast the # seems that if we hit ctrl-c too fast the
# sigint guard machinery might not kick in.. # sigint guard machinery might not kick in..
@ -312,10 +313,10 @@ def test_root_actor_bp_forever(
# XXX: this previously caused a bug! # XXX: this previously caused a bug!
child.sendline('n') child.sendline('n')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
child.sendline('n') child.sendline('n')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
# quit out of the loop # quit out of the loop
child.sendline('q') child.sendline('q')
@ -339,7 +340,7 @@ def test_subactor_error(
child = spawn('subactor_error') child = spawn('subactor_error')
# scan for the pdbpp prompt # scan for the pdbpp prompt
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
assert "Attaching to pdb in crashed actor: ('name_error'" in before assert "Attaching to pdb in crashed actor: ('name_error'" in before
@ -359,7 +360,7 @@ def test_subactor_error(
# creating actor # creating actor
child.sendline('continue') child.sendline('continue')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
# root actor gets debugger engaged # root actor gets debugger engaged
@ -387,7 +388,7 @@ def test_subactor_breakpoint(
child = spawn('subactor_breakpoint') child = spawn('subactor_breakpoint')
# scan for the pdbpp prompt # scan for the pdbpp prompt
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
assert "Attaching pdb to actor: ('breakpoint_forever'" in before assert "Attaching pdb to actor: ('breakpoint_forever'" in before
@ -396,7 +397,7 @@ def test_subactor_breakpoint(
# entries # entries
for _ in range(10): for _ in range(10):
child.sendline('next') child.sendline('next')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
if ctlc: if ctlc:
do_ctlc(child) do_ctlc(child)
@ -404,7 +405,7 @@ def test_subactor_breakpoint(
# now run some "continues" to show re-entries # now run some "continues" to show re-entries
for _ in range(5): for _ in range(5):
child.sendline('continue') child.sendline('continue')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
assert "Attaching pdb to actor: ('breakpoint_forever'" in before assert "Attaching pdb to actor: ('breakpoint_forever'" in before
@ -415,7 +416,7 @@ def test_subactor_breakpoint(
child.sendline('q') child.sendline('q')
# child process should exit but parent will capture pdb.BdbQuit # child process should exit but parent will capture pdb.BdbQuit
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
assert "RemoteActorError: ('breakpoint_forever'" in before assert "RemoteActorError: ('breakpoint_forever'" in before
@ -448,7 +449,7 @@ def test_multi_subactors(
child = spawn(r'multi_subactors') child = spawn(r'multi_subactors')
# scan for the pdbpp prompt # scan for the pdbpp prompt
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
assert "Attaching pdb to actor: ('breakpoint_forever'" in before assert "Attaching pdb to actor: ('breakpoint_forever'" in before
@ -460,7 +461,7 @@ def test_multi_subactors(
# entries # entries
for _ in range(10): for _ in range(10):
child.sendline('next') child.sendline('next')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
if ctlc: if ctlc:
do_ctlc(child) do_ctlc(child)
@ -469,7 +470,7 @@ def test_multi_subactors(
child.sendline('c') child.sendline('c')
# first name_error failure # first name_error failure
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
assert "Attaching to pdb in crashed actor: ('name_error'" in before assert "Attaching to pdb in crashed actor: ('name_error'" in before
assert "NameError" in before assert "NameError" in before
@ -481,7 +482,7 @@ def test_multi_subactors(
child.sendline('c') child.sendline('c')
# 2nd name_error failure # 2nd name_error failure
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
# TODO: will we ever get the race where this crash will show up? # TODO: will we ever get the race where this crash will show up?
# blocklist strat now prevents this crash # blocklist strat now prevents this crash
@ -495,7 +496,7 @@ def test_multi_subactors(
# breakpoint loop should re-engage # breakpoint loop should re-engage
child.sendline('c') child.sendline('c')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
assert "Attaching pdb to actor: ('breakpoint_forever'" in before assert "Attaching pdb to actor: ('breakpoint_forever'" in before
@ -511,7 +512,7 @@ def test_multi_subactors(
): ):
child.sendline('c') child.sendline('c')
time.sleep(0.1) time.sleep(0.1)
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
if ctlc: if ctlc:
@ -530,11 +531,11 @@ def test_multi_subactors(
# now run some "continues" to show re-entries # now run some "continues" to show re-entries
for _ in range(5): for _ in range(5):
child.sendline('c') child.sendline('c')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
# quit the loop and expect parent to attach # quit the loop and expect parent to attach
child.sendline('q') child.sendline('q')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
assert_before(child, [ assert_before(child, [
@ -578,7 +579,7 @@ def test_multi_daemon_subactors(
''' '''
child = spawn('multi_daemon_subactors') child = spawn('multi_daemon_subactors')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
# there can be a race for which subactor will acquire # there can be a race for which subactor will acquire
# the root's tty lock first so anticipate either crash # the root's tty lock first so anticipate either crash
@ -608,7 +609,7 @@ def test_multi_daemon_subactors(
# second entry by `bp_forever`. # second entry by `bp_forever`.
child.sendline('c') child.sendline('c')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
assert_before(child, [next_msg]) assert_before(child, [next_msg])
# XXX: hooray the root clobbering the child here was fixed! # XXX: hooray the root clobbering the child here was fixed!
@ -630,7 +631,7 @@ def test_multi_daemon_subactors(
# expect another breakpoint actor entry # expect another breakpoint actor entry
child.sendline('c') child.sendline('c')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
try: try:
assert_before(child, [bp_forever_msg]) assert_before(child, [bp_forever_msg])
@ -646,7 +647,7 @@ def test_multi_daemon_subactors(
# after 1 or more further bp actor entries. # after 1 or more further bp actor entries.
child.sendline('c') child.sendline('c')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
assert_before(child, [name_error_msg]) assert_before(child, [name_error_msg])
# wait for final error in root # wait for final error in root
@ -654,7 +655,7 @@ def test_multi_daemon_subactors(
while True: while True:
try: try:
child.sendline('c') child.sendline('c')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
assert_before( assert_before(
child, child,
[bp_forever_msg] [bp_forever_msg]
@ -688,7 +689,7 @@ def test_multi_subactors_root_errors(
child = spawn('multi_subactor_root_errors') child = spawn('multi_subactor_root_errors')
# scan for the pdbpp prompt # scan for the pdbpp prompt
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
# at most one subactor should attach before the root is cancelled # at most one subactor should attach before the root is cancelled
before = str(child.before.decode()) before = str(child.before.decode())
@ -703,7 +704,7 @@ def test_multi_subactors_root_errors(
# due to block list strat from #337, this will no longer # due to block list strat from #337, this will no longer
# propagate before the root errors and cancels the spawner sub-tree. # propagate before the root errors and cancels the spawner sub-tree.
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
# only if the blocking condition doesn't kick in fast enough # only if the blocking condition doesn't kick in fast enough
before = str(child.before.decode()) before = str(child.before.decode())
@ -718,7 +719,7 @@ def test_multi_subactors_root_errors(
do_ctlc(child) do_ctlc(child)
child.sendline('c') child.sendline('c')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
# check if the spawner crashed or was blocked from debug # check if the spawner crashed or was blocked from debug
# and if this intermediary attached check the boxed error # and if this intermediary attached check the boxed error
@ -735,7 +736,7 @@ def test_multi_subactors_root_errors(
do_ctlc(child) do_ctlc(child)
child.sendline('c') child.sendline('c')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
# expect a root actor crash # expect a root actor crash
assert_before(child, [ assert_before(child, [
@ -784,7 +785,7 @@ def test_multi_nested_subactors_error_through_nurseries(
for send_char in itertools.cycle(['c', 'q']): for send_char in itertools.cycle(['c', 'q']):
try: try:
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
child.sendline(send_char) child.sendline(send_char)
time.sleep(0.01) time.sleep(0.01)
@ -826,7 +827,7 @@ def test_root_nursery_cancels_before_child_releases_tty_lock(
child = spawn('root_cancelled_but_child_is_in_tty_lock') child = spawn('root_cancelled_but_child_is_in_tty_lock')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
assert "NameError: name 'doggypants' is not defined" in before assert "NameError: name 'doggypants' is not defined" in before
@ -841,7 +842,7 @@ def test_root_nursery_cancels_before_child_releases_tty_lock(
for i in range(4): for i in range(4):
time.sleep(0.5) time.sleep(0.5)
try: try:
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
except ( except (
EOF, EOF,
@ -898,7 +899,7 @@ def test_root_cancels_child_context_during_startup(
''' '''
child = spawn('fast_error_in_root_after_spawn') child = spawn('fast_error_in_root_after_spawn')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
before = str(child.before.decode()) before = str(child.before.decode())
assert "AssertionError" in before assert "AssertionError" in before
@ -915,7 +916,7 @@ def test_different_debug_mode_per_actor(
ctlc: bool, ctlc: bool,
): ):
child = spawn('per_actor_debug') child = spawn('per_actor_debug')
child.expect(r"\(Pdb\+\+\)") child.expect(PROMPT)
# only one actor should enter the debugger # only one actor should enter the debugger
before = str(child.before.decode()) before = str(child.before.decode())

View File

@ -44,7 +44,10 @@ from ._exceptions import (
ModuleNotExposed, ModuleNotExposed,
ContextCancelled, ContextCancelled,
) )
from ._debug import breakpoint, post_mortem from ._debug import (
breakpoint,
post_mortem,
)
from . import msg from . import msg
from ._root import ( from ._root import (
run_daemon, run_daemon,

View File

@ -37,6 +37,7 @@ from typing import (
) )
from types import FrameType from types import FrameType
import pdbp
import tractor import tractor
import trio import trio
from trio_typing import TaskStatus from trio_typing import TaskStatus
@ -54,15 +55,16 @@ from ._exceptions import (
from ._ipc import Channel from ._ipc import Channel
try: # TODO: we can drop this now yah?
# wtf: only exported when installed in dev mode? # try:
import pdbpp # # wtf: only exported when installed in dev mode?
except ImportError: # import pdbp
# pdbpp is installed in regular mode...it monkey patches stuff # except ImportError:
import pdb # # pdbpp is installed in regular mode...it monkey patches stuff
xpm = getattr(pdb, 'xpm', None) # import pdb
assert xpm, "pdbpp is not installed?" # type: ignore # xpm = getattr(pdb, 'xpm', None)
pdbpp = pdb # assert xpm, "pdbpp is not installed?" # type: ignore
# pdbpp = pdb
log = get_logger(__name__) log = get_logger(__name__)
@ -154,22 +156,26 @@ class Lock:
cls.repl = None cls.repl = None
class TractorConfig(pdbpp.DefaultConfig): class TractorConfig(pdbp.DefaultConfig):
''' '''
Custom ``pdbpp`` goodness. Custom ``pdbp`` goodness :surfer:
''' '''
# use_pygments = True use_pygments: bool = True
# sticky_by_default = True sticky_by_default: bool = False
enable_hidden_frames = False enable_hidden_frames: bool = False
# much thanks @mdmintz for the hot tip!
# fixes line spacing issue when resizing terminal B)
truncate_long_lines: bool = False
class MultiActorPdb(pdbpp.Pdb): class MultiActorPdb(pdbp.Pdb):
''' '''
Add teardown hooks to the regular ``pdbpp.Pdb``. Add teardown hooks to the regular ``pdbp.Pdb``.
''' '''
# override the pdbpp config with our coolio one # override the pdbp config with our coolio one
DefaultConfig = TractorConfig DefaultConfig = TractorConfig
# def preloop(self): # def preloop(self):
@ -313,7 +319,7 @@ async def lock_tty_for_child(
) -> str: ) -> str:
''' '''
Lock the TTY in the root process of an actor tree in a new Lock the TTY in the root process of an actor tree in a new
inter-actor-context-task such that the ``pdbpp`` debugger console inter-actor-context-task such that the ``pdbp`` debugger console
can be mutex-allocated to the calling sub-actor for REPL control can be mutex-allocated to the calling sub-actor for REPL control
without interference by other processes / threads. without interference by other processes / threads.
@ -433,7 +439,7 @@ async def wait_for_parent_stdin_hijack(
def mk_mpdb() -> tuple[MultiActorPdb, Callable]: def mk_mpdb() -> tuple[MultiActorPdb, Callable]:
pdb = MultiActorPdb() pdb = MultiActorPdb()
# signal.signal = pdbpp.hideframe(signal.signal) # signal.signal = pdbp.hideframe(signal.signal)
Lock.shield_sigint() Lock.shield_sigint()
@ -583,7 +589,7 @@ async def _breakpoint(
# # frame = sys._getframe() # # frame = sys._getframe()
# # last_f = frame.f_back # # last_f = frame.f_back
# # last_f.f_globals['__tracebackhide__'] = True # # last_f.f_globals['__tracebackhide__'] = True
# # signal.signal = pdbpp.hideframe(signal.signal) # # signal.signal = pdbp.hideframe(signal.signal)
def shield_sigint_handler( def shield_sigint_handler(
@ -743,7 +749,7 @@ def shield_sigint_handler(
# https://github.com/goodboy/tractor/issues/130#issuecomment-663752040 # https://github.com/goodboy/tractor/issues/130#issuecomment-663752040
# https://github.com/prompt-toolkit/python-prompt-toolkit/blob/c2c6af8a0308f9e5d7c0e28cb8a02963fe0ce07a/prompt_toolkit/patch_stdout.py # https://github.com/prompt-toolkit/python-prompt-toolkit/blob/c2c6af8a0308f9e5d7c0e28cb8a02963fe0ce07a/prompt_toolkit/patch_stdout.py
# XXX: lol, see ``pdbpp`` issue: # XXX LEGACY: lol, see ``pdbpp`` issue:
# https://github.com/pdbpp/pdbpp/issues/496 # https://github.com/pdbpp/pdbpp/issues/496
@ -798,7 +804,7 @@ def _post_mortem(
# https://github.com/pdbpp/pdbpp/issues/480 # https://github.com/pdbpp/pdbpp/issues/480
# TODO: help with a 3.10+ major release if/when it arrives. # TODO: help with a 3.10+ major release if/when it arrives.
pdbpp.xpm(Pdb=lambda: pdb) pdbp.xpm(Pdb=lambda: pdb)
post_mortem = partial( post_mortem = partial(

View File

@ -302,7 +302,7 @@ async def _open_and_supervise_one_cancels_all_nursery(
) -> typing.AsyncGenerator[ActorNursery, None]: ) -> typing.AsyncGenerator[ActorNursery, None]:
# TODO: yay or nay? # TODO: yay or nay?
# __tracebackhide__ = True __tracebackhide__ = True
# the collection of errors retreived from spawned sub-actors # the collection of errors retreived from spawned sub-actors
errors: dict[tuple[str, str], BaseException] = {} errors: dict[tuple[str, str], BaseException] = {}