From eec240a70a6fea5412f970a22c6b91fc3472410c Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Thu, 11 Apr 2024 21:24:02 -0400 Subject: [PATCH] Tweak some `pformat_boxed_tb()` indent inputs - add some `tb_str: str` indent-prefix args for diff indent levels for the body vs. the surrounding "ascii box". - ^-use it-^ from `RemoteActorError.__repr()__` obvi. - use new `msg.types.from_dict_msg()` in impl of `MsgTypeError.payload_msg`, handy for showing what the message "would have looked like in `Struct` form" had it not failed it's type constraints. --- tractor/_exceptions.py | 73 ++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/tractor/_exceptions.py b/tractor/_exceptions.py index a31aa11..31b7b36 100644 --- a/tractor/_exceptions.py +++ b/tractor/_exceptions.py @@ -40,7 +40,7 @@ from tractor._state import current_actor from tractor.log import get_logger from tractor.msg import ( Error, - Msg, + MsgType, Stop, Yield, pretty_struct, @@ -130,7 +130,10 @@ def pformat_boxed_tb( tb_str: str, fields_str: str|None = None, field_prefix: str = ' |_', - indent: str = ' '*2 + + tb_box_indent: int|None = None, + tb_body_indent: int = 1, + ) -> str: if ( fields_str @@ -139,15 +142,19 @@ def pformat_boxed_tb( ): fields: str = textwrap.indent( fields_str, - # prefix=' '*2, - # prefix=' |_', prefix=field_prefix, ) else: fields = fields_str or '' - # body_indent: str = len(field_prefix) * ' ' - body: str = ( + tb_body = tb_str + if tb_body_indent: + tb_body: str = textwrap.indent( + tb_str, + prefix=tb_body_indent * ' ', + ) + + tb_box: str = ( # orig # f' |\n' @@ -158,21 +165,29 @@ def pformat_boxed_tb( f'|\n' f' ------ - ------\n\n' - f'{tb_str}\n' + # f'{tb_str}\n' + f'{tb_body}' f' ------ - ------\n' f'_|\n' ) - if len(indent): - body: str = textwrap.indent( - body, - # prefix=body_indent, - prefix=indent, + tb_box_indent: str = ( + tb_box_indent + or + 1 + + # (len(field_prefix)) + # ? ^-TODO-^ ? if you wanted another indent level + ) + if tb_box_indent > 0: + tb_box: str = textwrap.indent( + tb_box, + prefix=tb_box_indent * ' ', ) return ( fields + - body + tb_box ) @@ -316,7 +331,7 @@ class RemoteActorError(Exception): if self._ipc_msg is None: return None - msg_type: Msg = type(self._ipc_msg) + msg_type: MsgType = type(self._ipc_msg) fields: dict[str, Any] = { k: v for _, k, v in pretty_struct.iter_fields(self._ipc_msg) @@ -493,7 +508,10 @@ class RemoteActorError(Exception): tb_str=self.tb_str, fields_str=fields, field_prefix=' |_', - indent=' ', # no indent? + # ^- is so that it's placed like so, + # just after dict[str, Any]: ''' - If the underlying IPC `Msg` was received from a remote + If the underlying IPC `MsgType` was received from a remote actor but was unable to be decoded to a native `Yield`|`Started`|`Return` struct, the interchange backend native format decoder can be used to stash a `dict` @@ -643,22 +661,21 @@ class MsgTypeError( return self.msgdata.get('_msg_dict') @property - def payload_msg(self) -> Msg|None: + def payload_msg( + self, + ) -> MsgType|None: ''' Attempt to construct what would have been the original - `Msg`-with-payload subtype (i.e. an instance from the set + `MsgType`-with-payload subtype (i.e. an instance from the set of msgs in `.msg.types._payload_msgs`) which failed validation. ''' - msg_dict: dict = self.msg_dict.copy() - name: str = msg_dict.pop('msg_type') - msg_type: Msg = getattr( - msgtypes, - name, - Msg, - ) - return msg_type(**msg_dict) + if msg_dict := self.msg_dict.copy(): + return msgtypes.from_dict_msg( + dict_msg=msg_dict, + ) + return None @property def cid(self) -> str: @@ -908,7 +925,7 @@ def is_multi_cancelled(exc: BaseException) -> bool: def _raise_from_no_key_in_msg( ctx: Context, - msg: Msg, + msg: MsgType, src_err: KeyError, log: StackLevelAdapter, # caller specific `log` obj