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
parent
48523358cf
commit
fc2e298a29
|
|
@ -1,9 +1,22 @@
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
# ?TODO? how to make `pdbp` enforce this?
|
||||||
|
# os.environ['PYTHON_COLORS'] = '0'
|
||||||
|
# os.environ['NO_COLOR'] = '1'
|
||||||
|
|
||||||
import trio
|
import trio
|
||||||
import tractor
|
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?
|
# TODO: only import these when not running from test harness?
|
||||||
# can we detect `pexpect` usage maybe?
|
# can we detect `pexpect` usage maybe?
|
||||||
# from tractor.devx.debug import (
|
# from tractor.devx.debug import (
|
||||||
|
|
@ -42,6 +55,7 @@ async def start_n_sync_pause(
|
||||||
ctx: tractor.Context,
|
ctx: tractor.Context,
|
||||||
):
|
):
|
||||||
actor: tractor.Actor = tractor.current_actor()
|
actor: tractor.Actor = tractor.current_actor()
|
||||||
|
disable_pdbp_color()
|
||||||
|
|
||||||
# sync to parent-side task
|
# sync to parent-side task
|
||||||
await ctx.started()
|
await ctx.started()
|
||||||
|
|
@ -52,13 +66,15 @@ async def start_n_sync_pause(
|
||||||
|
|
||||||
|
|
||||||
async def main() -> None:
|
async def main() -> None:
|
||||||
|
disable_pdbp_color()
|
||||||
async with (
|
async with (
|
||||||
tractor.open_nursery(
|
tractor.open_nursery(
|
||||||
debug_mode=True,
|
debug_mode=True,
|
||||||
maybe_enable_greenback=True,
|
maybe_enable_greenback=True,
|
||||||
enable_stack_on_sig=True,
|
|
||||||
# loglevel='warning',
|
# XXX flags required for test pattern matching.
|
||||||
# loglevel='devx',
|
loglevel='pdb',
|
||||||
|
# enable_stack_on_sig=True,
|
||||||
) as an,
|
) as an,
|
||||||
trio.open_nursery() as tn,
|
trio.open_nursery() as tn,
|
||||||
):
|
):
|
||||||
|
|
@ -68,8 +84,8 @@ async def main() -> None:
|
||||||
p: tractor.Portal = await an.start_actor(
|
p: tractor.Portal = await an.start_actor(
|
||||||
'subactor',
|
'subactor',
|
||||||
enable_modules=[__name__],
|
enable_modules=[__name__],
|
||||||
# infect_asyncio=True,
|
|
||||||
debug_mode=True,
|
debug_mode=True,
|
||||||
|
# infect_asyncio=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO: 3 sub-actor usage cases:
|
# TODO: 3 sub-actor usage cases:
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,8 @@ def spawn(
|
||||||
os.environ['PYTHON_COLORS'] = '0'
|
os.environ['PYTHON_COLORS'] = '0'
|
||||||
# disable all ANSI color output
|
# disable all ANSI color output
|
||||||
# os.environ['NO_COLOR'] = '1'
|
# os.environ['NO_COLOR'] = '1'
|
||||||
|
# ?TODO, doesn't seem to disable prompt color
|
||||||
|
# for `pdbp`?
|
||||||
|
|
||||||
def set_spawn_method(
|
def set_spawn_method(
|
||||||
start_method: str,
|
start_method: str,
|
||||||
|
|
|
||||||
|
|
@ -66,19 +66,28 @@ def test_pause_from_sync(
|
||||||
# XXX required for `breakpoint()` overload and
|
# XXX required for `breakpoint()` overload and
|
||||||
# thus`tractor.devx.pause_from_sync()`.
|
# thus`tractor.devx.pause_from_sync()`.
|
||||||
pytest.importorskip('greenback')
|
pytest.importorskip('greenback')
|
||||||
child = spawn('sync_bp')
|
child = spawn(
|
||||||
|
'sync_bp',
|
||||||
|
loglevel='pdb', # XXX pattern matching
|
||||||
|
)
|
||||||
|
|
||||||
# first `sync_pause()` after nurseries open
|
# first `sync_pause()` after nurseries open
|
||||||
child.expect(PROMPT)
|
child.expect(PROMPT)
|
||||||
assert_before(
|
_before: str = assert_before(
|
||||||
child,
|
child,
|
||||||
[
|
[
|
||||||
# pre-prompt line
|
# devx-loglevel
|
||||||
_pause_msg,
|
# "imported <module 'greenback' from",
|
||||||
"<Task '__main__.main'",
|
# "successfully scheduled `._pause()` in `trio` thread on behalf of <Task",
|
||||||
|
|
||||||
|
_pause_msg, # pre-prompt line
|
||||||
"('root'",
|
"('root'",
|
||||||
|
"<Task '__main__.main'",
|
||||||
|
"tractor.pause_from_sync()",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
# XXX `enable_stack_on_sig=False` in script
|
||||||
|
assert 'stackscope' not in _before
|
||||||
if ctlc:
|
if ctlc:
|
||||||
do_ctlc(child)
|
do_ctlc(child)
|
||||||
# ^NOTE^ subactor not spawned yet; don't need extra delay.
|
# ^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
|
# first `await tractor.pause()` inside `p.open_context()` body
|
||||||
child.expect(PROMPT)
|
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
|
# should be same root task
|
||||||
assert_before(
|
assert_before(
|
||||||
child,
|
child,
|
||||||
[
|
[
|
||||||
|
# XXX should see gb loaded with devx-loglevel.
|
||||||
|
# "`greenback` portal opened!",
|
||||||
|
# "Activated `greenback` for `tractor.pause_from_sync()` support!",
|
||||||
|
|
||||||
_pause_msg,
|
_pause_msg,
|
||||||
"<Task '__main__.main'",
|
|
||||||
"('root'",
|
"('root'",
|
||||||
|
"<Task '__main__.main'",
|
||||||
|
"tractor.pause()",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -130,17 +139,17 @@ def test_pause_from_sync(
|
||||||
# `Lock.acquire()`-ed
|
# `Lock.acquire()`-ed
|
||||||
# (NOT both, which will result in REPL clobbering!)
|
# (NOT both, which will result in REPL clobbering!)
|
||||||
attach_patts: dict[str, list[str]] = {
|
attach_patts: dict[str, list[str]] = {
|
||||||
'subactor': [
|
"|_<Task 'start_n_sync_pause'": [
|
||||||
"'start_n_sync_pause'",
|
"|_('subactor'",
|
||||||
"('subactor'",
|
"tractor.pause_from_sync()",
|
||||||
],
|
],
|
||||||
'inline_root_bg_thread': [
|
"|_<Thread(inline_root_bg_thread": [
|
||||||
"<Thread(inline_root_bg_thread",
|
|
||||||
"('root'",
|
"('root'",
|
||||||
|
"breakpoint(hide_tb=hide_tb)",
|
||||||
],
|
],
|
||||||
'start_soon_root_bg_thread': [
|
"|_<Thread(start_soon_root_bg_thread": [
|
||||||
"<Thread(start_soon_root_bg_thread",
|
"|_('root'",
|
||||||
"('root'",
|
"tractor.pause_from_sync()",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
conts: int = 0 # for debugging below matching logic on failure
|
conts: int = 0 # for debugging below matching logic on failure
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ class Lock:
|
||||||
return (
|
return (
|
||||||
f'<{cls.__name__}(\n'
|
f'<{cls.__name__}(\n'
|
||||||
f'{body}'
|
f'{body}'
|
||||||
')>\n\n'
|
')>\n'
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -282,7 +282,7 @@ class Lock:
|
||||||
):
|
):
|
||||||
message += (
|
message += (
|
||||||
'-> No new task holds the TTY lock!\n\n'
|
'-> No new task holds the TTY lock!\n\n'
|
||||||
f'{Lock.repr()}\n'
|
f'{Lock.repr()}'
|
||||||
)
|
)
|
||||||
|
|
||||||
elif (
|
elif (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue