Even smarter `RemoteActorError.pformat()`-ing

Related to the prior patch, re the new `with_type_header: bool`:
- in the `with_type_header == True` use case make sure we keep the first
  `._message: str` line non-indented since it'll show just after the
  header-line's type path with ':'.
- when `False` drop the `)>` `repr()`-instance style as well so that we
  just get the ascii boxed traceback as though it's the error
  message-`str` not the `repr()` of the error obj.

Other,
- hide `pack_from_raise()` call frame since it'll show in debug mode
  crash handling..
- mk `MsgTypeError.from_decode()` explicitly accept and proxy an
  optional `ipc_msg` and change `msgdict` to also be optional, only
  reading out the `**extra_msgdata` when provided.
- expose a `_mk_msg_type_err(src_err_msg: Error|None = None,)` for
  callers who which to inject a `._ipc_msg: Msgtype` to the MTE.
  |_ add a note how we can't use it due to a causality-dilemma when pld
     validating `Started` on the send side..
runtime_to_msgspec
Tyler Goodlet 2024-05-22 15:26:48 -04:00
parent 9ce958cb4a
commit e4ec6b7b0c
1 changed files with 62 additions and 22 deletions

View File

@ -35,7 +35,6 @@ import trio
from msgspec import (
defstruct,
msgpack,
Raw,
structs,
ValidationError,
)
@ -44,11 +43,12 @@ from tractor._state import current_actor
from tractor.log import get_logger
from tractor.msg import (
Error,
PayloadMsg,
MsgType,
Stop,
types as msgtypes,
MsgCodec,
MsgDec,
Stop,
types as msgtypes,
)
from tractor.msg.pretty_struct import (
iter_fields,
@ -156,6 +156,7 @@ def pack_from_raise(
`Error`-msg using `pack_error()` to extract the tb info.
'''
__tracebackhide__: bool = True
try:
raise local_err
except type(local_err) as local_err:
@ -525,10 +526,26 @@ class RemoteActorError(Exception):
if not with_type_header:
body = '\n' + body
else:
body: str = textwrap.indent(
self._message,
prefix=' ',
) + '\n'
first: str = ''
message: str = self._message
# split off the first line so it isn't indented
# the same like the "boxed content".
if not with_type_header:
lines: list[str] = message.splitlines()
first = lines[0]
message = ''.join(lines[1:])
body: str = (
first
+
textwrap.indent(
message,
prefix=' ',
)
+
'\n'
)
if with_type_header:
tail: str = ')>'
@ -734,25 +751,38 @@ class MsgTypeError(
def from_decode(
cls,
message: str,
msgdict: dict,
ipc_msg: PayloadMsg|None = None,
msgdict: dict|None = None,
) -> MsgTypeError:
return cls(
message=message,
boxed_type=cls,
'''
Constuctor for easy creation from (presumably) catching
the backend interchange lib's underlying validation error
and passing context-specific meta-data to `_mk_msg_type_err()`
(which is normally the caller of this).
# NOTE: original "vanilla decode" of the msg-bytes
# is placed inside a value readable from
# `.msgdata['_msg_dict']`
_msg_dict=msgdict,
# expand and pack all RAE compat fields
# into the `._extra_msgdata` aux `dict`.
**{
'''
# if provided, expand and pack all RAE compat fields into the
# `._extra_msgdata` auxillary data `dict` internal to
# `RemoteActorError`.
extra_msgdata: dict = {}
if msgdict:
extra_msgdata: dict = {
k: v
for k, v in msgdict.items()
if k in _ipcmsg_keys
},
}
# NOTE: original "vanilla decode" of the msg-bytes
# is placed inside a value readable from
# `.msgdata['_msg_dict']`
extra_msgdata['_msg_dict'] = msgdict
return cls(
message=message,
boxed_type=cls,
ipc_msg=ipc_msg,
**extra_msgdata,
)
@ -1076,7 +1106,7 @@ _raise_from_no_key_in_msg = _raise_from_unexpected_msg
def _mk_msg_type_err(
msg: Any|bytes|Raw,
msg: Any|bytes|MsgType,
codec: MsgCodec|MsgDec,
message: str|None = None,
@ -1085,6 +1115,7 @@ def _mk_msg_type_err(
src_validation_error: ValidationError|None = None,
src_type_error: TypeError|None = None,
is_invalid_payload: bool = False,
src_err_msg: Error|None = None,
**mte_kwargs,
@ -1159,9 +1190,10 @@ def _mk_msg_type_err(
# only the payload being wrong?
# -[ ] maybe the better design is to break this construct
# logic into a separate explicit helper raiser-func?
msg_dict: dict = {}
msg_dict = None
else:
msg: bytes
# decode the msg-bytes using the std msgpack
# interchange-prot (i.e. without any
# `msgspec.Struct` handling) so that we can
@ -1206,6 +1238,14 @@ def _mk_msg_type_err(
msgtyperr = MsgTypeError.from_decode(
message=message,
msgdict=msg_dict,
# NOTE: for the send-side `.started()` pld-validate
# case we actually set the `._ipc_msg` AFTER we return
# from here inside `Context.started()` since we actually
# want to emulate the `Error` from the mte we build here
# Bo
# so by default in that case this is set to `None`
ipc_msg=src_err_msg,
)
msgtyperr.__cause__ = src_validation_error
return msgtyperr