tractor/tractor
Tyler Goodlet dbebcc54cc Unify `MsgTypeError` as a `RemoteActorError` subtype
Since in the receive-side error case the source of the exception is the
sender side (normally causing a local `TypeError` at decode time), might
as well bundle the error in remote-capture-style using boxing semantics
around the causing local type error raised from the
`msgspec.msgpack.Decoder.decode()` and with a traceback packed from
`msgspec`-specific knowledge of any field-type spec matching failure.

Deats on new `MsgTypeError` interface:
- includes a `.msg_dict` to get access to any `Decoder.type`-applied
  load of the original (underlying and offending) IPC msg into
  a `dict` form using a vanilla decoder which is normally packed into
  the instance as a `._msg_dict`.
- a public getter to the "supposed offending msg" via `.payload_msg`
  which attempts to take the above `.msg_dict` and load it manually into
  the corresponding `.msg.types.MsgType` struct.
- a constructor `.from_decode()` to make it simple to build out error
  instances from a failed decode scope where the aforementioned
  `msgdict: dict` from the vanilla decode can be provided directly.
- ALSO, we now pack into `MsgTypeError` directly just like ctxc in
  `unpack_error()`

This also completes the while-standing todo for `RemoteActorError` to
contain a ref to the underlying `Error` msg as `._ipc_msg` with public
`@property` access that `defstruct()`-creates a pretty struct version
via `.ipc_msg`.

Internal tweaks for this include:
- `._ipc_msg` is the internal literal `Error`-msg instance if provided
  with `.ipc_msg` the dynamic wrapper as mentioned above.
- `.__init__()` now can still take variable `**extra_msgdata` (similar
  to the `dict`-msgdata as before) to maintain support for subtypes
  which are constructed manually (not only by `pack_error()`) and insert
  their own attrs which get placed in a `._extra_msgdata: dict` if no
  `ipc_msg: Error` is provided as input.
- the `.msgdata` is now a merge of any `._extra_msgdata` and
  a `dict`-casted form of any `._ipc_msg`.
- adjust all previous `.msgdata` field lookups to try equivalent field
  reads on `._ipc_msg: Error`.
- drop default single ws indent from `.tb_str` and do a failover lookup
  to `.msgdata` when `._ipc_msg is None` for the manually constructed
  subtype-instance case.
- add a new class attr `.extra_body_fields: list[str]` to allow subtypes
  to declare attrs they want shown in the `.__repr__()` output, eg.
  `ContextCancelled.canceller`, `StreamOverrun.sender` and
  `MsgTypeError.payload_msg`.
- ^-rework defaults pertaining to-^ with rename from
  `_msgdata_keys` -> `_ipcmsg_keys` with latter now just loading directly
  from the `Error` fields def and `_body_fields: list[str]` just taking
  that value and removing the not-so-useful-in-REPL or already shown
  (i.e. `.tb_str: str`) field names.
- add a new mod level `.pack_from_raise()` helper for auto-boxing RAE
  subtypes constructed manually into `Error`s which is normally how
  `StreamOverrun` and `MsgTypeError` get created in the runtime.
- in support of the above expose a `src_uid: tuple` override to
  `pack_error()` such that the runtime can provide any remote actor id
  when packing a locally-created yet remotely-caused RAE subtype.
- adjust all typing to expect `Error`s over `dict`-msgs.

Adjust some tests to match these changes:
- context and inter-peer-cancel tests to make their `.msgdata` related
  checks against the new `.ipc_msg` as well and `.tb_str` directly.
- toss in an extra sleep to `sleep_a_bit_then_cancel_peer()` to keep the
  'canceller' ctx child task cancelled by it's parent in the 'root' for
  the rte-raised-during-ctxc-handling case (apparently now it's
  returning too fast, cool?).
2025-03-24 14:04:51 -04:00
..
_testing Start a new `._testing.fault_simulation` 2025-03-24 14:04:51 -04:00
devx WIP porting runtime to use `Msg`-spec 2025-03-24 14:04:51 -04:00
experimental Drop now-deprecated deps on modern `trio`/Python 2025-03-16 16:06:24 -04:00
msg Flatten out RPC loop with `match:`/`case:` 2025-03-24 14:04:51 -04:00
trionics Drop now-deprecated deps on modern `trio`/Python 2025-03-16 16:06:24 -04:00
__init__.py Expose `MsgTypeError` from pkg 2025-03-24 14:04:51 -04:00
_child.py Hide `._entry`/`._child` frames, tweak some more type annots 2025-03-20 23:22:45 -04:00
_clustering.py Passthrough runtime kwargs from `open_actor_cluster()` 2022-12-11 19:56:08 -05:00
_context.py Rename `Actor._push_result()` -> `._deliver_ctx_payload()` 2025-03-24 14:04:51 -04:00
_discovery.py More spaceless union type annots 2025-03-20 19:50:31 -04:00
_entry.py WIP porting runtime to use `Msg`-spec 2025-03-24 14:04:51 -04:00
_exceptions.py Unify `MsgTypeError` as a `RemoteActorError` subtype 2025-03-24 14:04:51 -04:00
_forkserver_override.py Re-license code base for distribution under AGPL 2021-12-14 23:33:27 -05:00
_ipc.py Use `object()` when checking for error field value 2025-03-24 14:04:51 -04:00
_mp_fixup_main.py Avoid importing mp for as long as possible 2022-02-17 11:55:26 -05:00
_multiaddr.py Fix doc string "its" typo.. 2025-03-20 19:50:31 -04:00
_portal.py Drop `None`-sentinel cancels RPC loop mechanism 2025-03-24 14:04:51 -04:00
_root.py Add `enable_stack_on_sig: bool` for `stackscope` toggle 2025-03-20 23:22:45 -04:00
_rpc.py Rename `Actor._push_result()` -> `._deliver_ctx_payload()` 2025-03-24 14:04:51 -04:00
_runtime.py Rename `Actor._push_result()` -> `._deliver_ctx_payload()` 2025-03-24 14:04:51 -04:00
_spawn.py WIP porting runtime to use `Msg`-spec 2025-03-24 14:04:51 -04:00
_state.py Add defaul rtv for `use_greeback: bool = False` 2025-03-20 23:22:45 -04:00
_streaming.py Rename `Actor._push_result()` -> `._deliver_ctx_payload()` 2025-03-24 14:04:51 -04:00
_supervise.py Hide `._entry`/`._child` frames, tweak some more type annots 2025-03-20 23:22:45 -04:00
log.py Bleh, make `log.devx()` level less then cancel but > `.runtime()` 2025-03-20 23:22:45 -04:00
to_asyncio.py Provision for infected-`asyncio` debug mode support 2025-03-20 22:37:51 -04:00