Compare commits

..

3 Commits

Author SHA1 Message Date
Tyler Goodlet 64e5c8bd93 Disable tb colors in `._testing.mk_cmd()`
Unset the appropriate cpython osenv var such that our `pexpect` script
runs in the test suite can maintain original matching logic.
2025-02-26 13:49:14 -05:00
Tyler Goodlet 6b8322cdc9 Log format tweaks for sclang reprs
A space here, a newline there..
2025-02-26 13:16:15 -05:00
Tyler Goodlet a16aa300e0 Expose `hide_tb: bool` from `.open_nursery()`
Such that it gets passed through to `.open_root_actor()` in the
`implicit_runtime==True` case - useful for debugging cases where
`.devx._debug` APIs might be used to avoid REPL clobbering in subactors.
2025-02-26 13:04:37 -05:00
8 changed files with 52 additions and 21 deletions

View File

@ -1006,7 +1006,8 @@ class Context:
) )
else: else:
log.cancel( log.cancel(
'Timed out on cancel request of remote task?\n' f'Timed out on cancel request of remote task?\n'
f'\n'
f'{reminfo}' f'{reminfo}'
) )

View File

@ -238,7 +238,7 @@ def _trio_main(
nest_from_op( nest_from_op(
input_op='>(', # see syntax ideas above input_op='>(', # see syntax ideas above
tree_str=actor_info, tree_str=actor_info,
back_from_op=1, back_from_op=2, # since "complete"
) )
) )
logmeth = log.info logmeth = log.info

View File

@ -111,8 +111,8 @@ async def open_root_actor(
Runtime init entry point for ``tractor``. Runtime init entry point for ``tractor``.
''' '''
__tracebackhide__: bool = hide_tb
_debug.hide_runtime_frames() _debug.hide_runtime_frames()
__tracebackhide__: bool = hide_tb
# TODO: stick this in a `@cm` defined in `devx._debug`? # TODO: stick this in a `@cm` defined in `devx._debug`?
# #
@ -390,6 +390,12 @@ async def open_root_actor(
BaseExceptionGroup, BaseExceptionGroup,
) as err: ) as err:
# TODO, in beginning to handle the subsubactor with
# crashed grandparent cases..
#
# was_locked: bool = await _debug.maybe_wait_for_debugger(
# child_in_debug=True,
# )
# XXX NOTE XXX see equiv note inside # XXX NOTE XXX see equiv note inside
# `._runtime.Actor._stream_handler()` where in the # `._runtime.Actor._stream_handler()` where in the
# non-root or root-that-opened-this-mahually case we # non-root or root-that-opened-this-mahually case we

View File

@ -852,8 +852,8 @@ async def try_ship_error_to_remote(
log.critical( log.critical(
'IPC transport failure -> ' 'IPC transport failure -> '
f'failed to ship error to {remote_descr}!\n\n' f'failed to ship error to {remote_descr}!\n\n'
f'X=> {channel.uid}\n\n' f'{type(msg)!r}[{msg.boxed_type}] X=> {channel.uid}\n'
f'\n'
# TODO: use `.msg.preetty_struct` for this! # TODO: use `.msg.preetty_struct` for this!
f'{msg}\n' f'{msg}\n'
) )

View File

@ -1288,6 +1288,7 @@ class Actor:
f'Actor-runtime cancel request from {requester_type}\n\n' f'Actor-runtime cancel request from {requester_type}\n\n'
f'<=c) {requesting_uid}\n' f'<=c) {requesting_uid}\n'
f' |_{self}\n' f' |_{self}\n'
f'\n'
) )
# TODO: what happens here when we self-cancel tho? # TODO: what happens here when we self-cancel tho?
@ -1307,13 +1308,15 @@ class Actor:
lock_req_ctx.has_outcome lock_req_ctx.has_outcome
): ):
msg += ( msg += (
'-> Cancelling active debugger request..\n' f'\n'
f'-> Cancelling active debugger request..\n'
f'|_{_debug.Lock.repr()}\n\n' f'|_{_debug.Lock.repr()}\n\n'
f'|_{lock_req_ctx}\n\n' f'|_{lock_req_ctx}\n\n'
) )
# lock_req_ctx._scope.cancel() # lock_req_ctx._scope.cancel()
# TODO: wrap this in a method-API.. # TODO: wrap this in a method-API..
debug_req.req_cs.cancel() debug_req.req_cs.cancel()
# if lock_req_ctx:
# self-cancel **all** ongoing RPC tasks # self-cancel **all** ongoing RPC tasks
await self.cancel_rpc_tasks( await self.cancel_rpc_tasks(

View File

@ -323,8 +323,9 @@ async def soft_kill(
uid: tuple[str, str] = portal.channel.uid uid: tuple[str, str] = portal.channel.uid
try: try:
log.cancel( log.cancel(
'Soft killing sub-actor via portal request\n' f'Soft killing sub-actor via portal request\n'
f'c)> {portal.chan.uid}\n' f'\n'
f'(c=> {portal.chan.uid}\n'
f' |_{proc}\n' f' |_{proc}\n'
) )
# wait on sub-proc to signal termination # wait on sub-proc to signal termination

View File

@ -402,7 +402,7 @@ async def _open_and_supervise_one_cancels_all_nursery(
try: try:
# This is the inner level "run in actor" nursery. It is # This is the inner level "run in actor" nursery. It is
# awaited first since actors spawned in this way (using # awaited first since actors spawned in this way (using
# ``ActorNusery.run_in_actor()``) are expected to only # `ActorNusery.run_in_actor()`) are expected to only
# return a single result and then complete (i.e. be canclled # return a single result and then complete (i.e. be canclled
# gracefully). Errors collected from these actors are # gracefully). Errors collected from these actors are
# immediately raised for handling by a supervisor strategy. # immediately raised for handling by a supervisor strategy.
@ -478,8 +478,8 @@ async def _open_and_supervise_one_cancels_all_nursery(
ContextCancelled, ContextCancelled,
}: }:
log.cancel( log.cancel(
'Actor-nursery caught remote cancellation\n\n' 'Actor-nursery caught remote cancellation\n'
'\n'
f'{inner_err.tb_str}' f'{inner_err.tb_str}'
) )
else: else:
@ -571,7 +571,9 @@ async def _open_and_supervise_one_cancels_all_nursery(
@acm @acm
# @api_frame # @api_frame
async def open_nursery( async def open_nursery(
hide_tb: bool = False,
**kwargs, **kwargs,
# ^TODO, paramspec for `open_root_actor()`
) -> typing.AsyncGenerator[ActorNursery, None]: ) -> typing.AsyncGenerator[ActorNursery, None]:
''' '''
@ -589,7 +591,7 @@ async def open_nursery(
which cancellation scopes correspond to each spawned subactor set. which cancellation scopes correspond to each spawned subactor set.
''' '''
__tracebackhide__: bool = True __tracebackhide__: bool = hide_tb
implicit_runtime: bool = False implicit_runtime: bool = False
actor: Actor = current_actor(err_on_no_runtime=False) actor: Actor = current_actor(err_on_no_runtime=False)
an: ActorNursery|None = None an: ActorNursery|None = None
@ -605,7 +607,10 @@ async def open_nursery(
# mark us for teardown on exit # mark us for teardown on exit
implicit_runtime: bool = True implicit_runtime: bool = True
async with open_root_actor(**kwargs) as actor: async with open_root_actor(
hide_tb=hide_tb,
**kwargs,
) as actor:
assert actor is current_actor() assert actor is current_actor()
try: try:
@ -643,8 +648,10 @@ async def open_nursery(
# show frame on any internal runtime-scope error # show frame on any internal runtime-scope error
if ( if (
an an
and not an.cancelled and
and an._scope_error not an.cancelled
and
an._scope_error
): ):
__tracebackhide__: bool = False __tracebackhide__: bool = False

View File

@ -19,7 +19,10 @@ Various helpers/utils for auditing your `tractor` app and/or the
core runtime. core runtime.
''' '''
from contextlib import asynccontextmanager as acm from contextlib import (
asynccontextmanager as acm,
)
import os
import pathlib import pathlib
import tractor import tractor
@ -59,7 +62,12 @@ def mk_cmd(
exs_subpath: str = 'debugging', exs_subpath: str = 'debugging',
) -> str: ) -> str:
''' '''
Generate a shell command suitable to pass to ``pexpect.spawn()``. Generate a shell command suitable to pass to `pexpect.spawn()`
which runs the script as a python program's entrypoint.
In particular ensure we disable the new tb coloring via unsetting
`$PYTHON_COLORS` so that `pexpect` can pattern match without
color-escape-codes.
''' '''
script_path: pathlib.Path = ( script_path: pathlib.Path = (
@ -67,10 +75,15 @@ def mk_cmd(
/ exs_subpath / exs_subpath
/ f'{ex_name}.py' / f'{ex_name}.py'
) )
return ' '.join([ py_cmd: str = ' '.join([
'python', 'python',
str(script_path) str(script_path)
]) ])
# XXX, required for py 3.13+
# https://docs.python.org/3/using/cmdline.html#using-on-controlling-color
# https://docs.python.org/3/using/cmdline.html#envvar-PYTHON_COLORS
os.environ['PYTHON_COLORS'] = '0'
return py_cmd
@acm @acm