Move runtime frame hiding into helper func

Call it `hide_runtime_frames()` and stick all the lines from the top of
the `._debug` mod in there along with a little `log.devx()` emission on
what gets hidden by default ;)

Other,
- fix ref-error where internal-error handler might trigger despite the
  debug `req_ctx` not yet having init-ed, such that we don't try to
  cancel or log about it when it never was fully created/initialize..
- fix assignment typo iniside `_set_trace()` for `task`.. lel
runtime_to_msgspec
Tyler Goodlet 2024-05-22 14:56:54 -04:00
parent 74d4b5280a
commit d15e73557a
1 changed files with 86 additions and 45 deletions

View File

@ -48,9 +48,11 @@ from typing import (
TYPE_CHECKING, TYPE_CHECKING,
) )
from types import ( from types import (
FunctionType,
FrameType, FrameType,
ModuleType, ModuleType,
TracebackType, TracebackType,
CodeType,
) )
from msgspec import Struct from msgspec import Struct
@ -90,6 +92,14 @@ if TYPE_CHECKING:
log = get_logger(__name__) log = get_logger(__name__)
def hide_runtime_frames() -> dict[FunctionType, CodeType]:
'''
Hide call-stack frames for various std-lib and `trio`-API primitives
such that the tracebacks presented from our runtime are as minimized
as possible, particularly from inside a `PdbREPL`.
'''
# XXX HACKZONE XXX # XXX HACKZONE XXX
# hide exit stack frames on nurseries and cancel-scopes! # hide exit stack frames on nurseries and cancel-scopes!
# |_ so avoid seeing it when the `pdbp` REPL is first engaged from # |_ so avoid seeing it when the `pdbp` REPL is first engaged from
@ -117,16 +127,37 @@ log = get_logger(__name__)
# -[ ] maybe dig into the core `pdb` issue why the extra frame is shown # -[ ] maybe dig into the core `pdb` issue why the extra frame is shown
# at all? # at all?
# #
pdbp.hideframe(trio._core._run.NurseryManager.__aexit__) funcs: list[FunctionType] = [
pdbp.hideframe(trio._core._run.CancelScope.__exit__) trio._core._run.NurseryManager.__aexit__,
pdbp.hideframe(_GeneratorContextManager.__exit__) trio._core._run.CancelScope.__exit__,
pdbp.hideframe(_AsyncGeneratorContextManager.__aexit__) _GeneratorContextManager.__exit__,
pdbp.hideframe(trio.Event.wait) _AsyncGeneratorContextManager.__aexit__,
_AsyncGeneratorContextManager.__aenter__,
__all__ = [ trio.Event.wait,
'breakpoint',
'post_mortem',
] ]
func_list_str: str = textwrap.indent(
"\n".join(f.__qualname__ for f in funcs),
prefix=' |_ ',
)
log.devx(
'Hiding the following runtime frames by default:\n'
f'{func_list_str}\n'
)
codes: dict[FunctionType, CodeType] = {}
for ref in funcs:
# stash a pre-modified version of each ref's code-obj
# so it can be reverted later if needed.
codes[ref] = ref.__code__
pdbp.hideframe(ref)
#
# pdbp.hideframe(trio._core._run.NurseryManager.__aexit__)
# pdbp.hideframe(trio._core._run.CancelScope.__exit__)
# pdbp.hideframe(_GeneratorContextManager.__exit__)
# pdbp.hideframe(_AsyncGeneratorContextManager.__aexit__)
# pdbp.hideframe(_AsyncGeneratorContextManager.__aenter__)
# pdbp.hideframe(trio.Event.wait)
return codes
class LockStatus( class LockStatus(
@ -1032,15 +1063,24 @@ async def request_root_stdio_lock(
except ( except (
BaseException, BaseException,
): ) as ctx_err:
log.exception( message: str = (
'Failed during root TTY-lock dialog?\n' 'Failed during debug request dialog with root actor?\n\n'
f'{req_ctx}\n' )
if req_ctx:
message += (
f'{req_ctx}\n'
f'Cancelling IPC ctx!\n' f'Cancelling IPC ctx!\n'
) )
await req_ctx.cancel() await req_ctx.cancel()
raise
else:
message += 'Failed during `Portal.open_context()` ?\n'
log.exception(message)
ctx_err.add_note(message)
raise ctx_err
except ( except (
@ -1067,6 +1107,7 @@ async def request_root_stdio_lock(
# ctl-c out of the currently hanging task! # ctl-c out of the currently hanging task!
raise DebugRequestError( raise DebugRequestError(
'Failed to lock stdio from subactor IPC ctx!\n\n' 'Failed to lock stdio from subactor IPC ctx!\n\n'
f'req_ctx: {DebugStatus.req_ctx}\n' f'req_ctx: {DebugStatus.req_ctx}\n'
) from req_err ) from req_err
@ -1777,7 +1818,7 @@ def _set_trace(
): ):
__tracebackhide__: bool = hide_tb __tracebackhide__: bool = hide_tb
actor: tractor.Actor = actor or current_actor() actor: tractor.Actor = actor or current_actor()
task: task or current_task() task: trio.Task = task or current_task()
# else: # else:
# TODO: maybe print the actor supervion tree up to the # TODO: maybe print the actor supervion tree up to the