Update `sync_bp` + tighten `test_pause_from_sync`

Add `disable_pdbp_color()` to the `sync_bp` example
to suppress pygments prompt coloring when
`PYTHON_COLORS=0` — makes pexpect pattern matching
deterministic.

Deats,
- set `loglevel='pdb'` in both script + test spawn.
- disable `enable_stack_on_sig` in example, assert
  no `stackscope` output in test.
- update `attach_patts` keys/values with `|_<Task`
  / `|_<Thread` / `|_('subactor'` prefixes to match
  actual tree-dump format.
- add call-site patterns (`tractor.pause_from_sync()`
  `tractor.pause()`, `breakpoint(hide_tb=...)`).
- trim trailing `\n` from `Lock.repr()` output.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
subint_forkserver_backend
Gud Boi 2026-04-30 20:54:50 -04:00
parent 48523358cf
commit fc2e298a29
4 changed files with 52 additions and 25 deletions

View File

@ -1,9 +1,22 @@
from functools import partial
import os
import time
# ?TODO? how to make `pdbp` enforce this?
# os.environ['PYTHON_COLORS'] = '0'
# os.environ['NO_COLOR'] = '1'
import trio
import tractor
# disable `pbdp` prompt colors
# for prompt matching in test.
def disable_pdbp_color():
if os.environ['PYTHON_COLORS'] == '0':
from tractor.devx.debug import _repl
_repl.TractorConfig.use_pygments = False
# TODO: only import these when not running from test harness?
# can we detect `pexpect` usage maybe?
# from tractor.devx.debug import (
@ -42,6 +55,7 @@ async def start_n_sync_pause(
ctx: tractor.Context,
):
actor: tractor.Actor = tractor.current_actor()
disable_pdbp_color()
# sync to parent-side task
await ctx.started()
@ -52,13 +66,15 @@ async def start_n_sync_pause(
async def main() -> None:
disable_pdbp_color()
async with (
tractor.open_nursery(
debug_mode=True,
maybe_enable_greenback=True,
enable_stack_on_sig=True,
# loglevel='warning',
# loglevel='devx',
# XXX flags required for test pattern matching.
loglevel='pdb',
# enable_stack_on_sig=True,
) as an,
trio.open_nursery() as tn,
):
@ -68,8 +84,8 @@ async def main() -> None:
p: tractor.Portal = await an.start_actor(
'subactor',
enable_modules=[__name__],
# infect_asyncio=True,
debug_mode=True,
# infect_asyncio=True,
)
# TODO: 3 sub-actor usage cases:

View File

@ -95,6 +95,8 @@ def spawn(
os.environ['PYTHON_COLORS'] = '0'
# disable all ANSI color output
# os.environ['NO_COLOR'] = '1'
# ?TODO, doesn't seem to disable prompt color
# for `pdbp`?
def set_spawn_method(
start_method: str,

View File

@ -66,19 +66,28 @@ def test_pause_from_sync(
# XXX required for `breakpoint()` overload and
# thus`tractor.devx.pause_from_sync()`.
pytest.importorskip('greenback')
child = spawn('sync_bp')
child = spawn(
'sync_bp',
loglevel='pdb', # XXX pattern matching
)
# first `sync_pause()` after nurseries open
child.expect(PROMPT)
assert_before(
_before: str = assert_before(
child,
[
# pre-prompt line
_pause_msg,
"<Task '__main__.main'",
# devx-loglevel
# "imported <module 'greenback' from",
# "successfully scheduled `._pause()` in `trio` thread on behalf of <Task",
_pause_msg, # pre-prompt line
"('root'",
"<Task '__main__.main'",
"tractor.pause_from_sync()",
]
)
# XXX `enable_stack_on_sig=False` in script
assert 'stackscope' not in _before
if ctlc:
do_ctlc(child)
# ^NOTE^ subactor not spawned yet; don't need extra delay.
@ -88,18 +97,18 @@ def test_pause_from_sync(
# first `await tractor.pause()` inside `p.open_context()` body
child.expect(PROMPT)
# XXX shouldn't see gb loaded message with PDB loglevel!
# assert not in_prompt_msg(
# child,
# ['`greenback` portal opened!'],
# )
# should be same root task
assert_before(
child,
[
# XXX should see gb loaded with devx-loglevel.
# "`greenback` portal opened!",
# "Activated `greenback` for `tractor.pause_from_sync()` support!",
_pause_msg,
"<Task '__main__.main'",
"('root'",
"<Task '__main__.main'",
"tractor.pause()",
]
)
@ -130,17 +139,17 @@ def test_pause_from_sync(
# `Lock.acquire()`-ed
# (NOT both, which will result in REPL clobbering!)
attach_patts: dict[str, list[str]] = {
'subactor': [
"'start_n_sync_pause'",
"('subactor'",
"|_<Task 'start_n_sync_pause'": [
"|_('subactor'",
"tractor.pause_from_sync()",
],
'inline_root_bg_thread': [
"<Thread(inline_root_bg_thread",
"|_<Thread(inline_root_bg_thread": [
"('root'",
"breakpoint(hide_tb=hide_tb)",
],
'start_soon_root_bg_thread': [
"<Thread(start_soon_root_bg_thread",
"('root'",
"|_<Thread(start_soon_root_bg_thread": [
"|_('root'",
"tractor.pause_from_sync()",
],
}
conts: int = 0 # for debugging below matching logic on failure

View File

@ -181,7 +181,7 @@ class Lock:
return (
f'<{cls.__name__}(\n'
f'{body}'
')>\n\n'
')>\n'
)
@classmethod
@ -282,7 +282,7 @@ class Lock:
):
message += (
'-> No new task holds the TTY lock!\n\n'
f'{Lock.repr()}\n'
f'{Lock.repr()}'
)
elif (