Expose `MsgType` and extend `MsgCodec` API a bit
Make a new `MsgType: TypeAlias` for the union of all msg types such that it can be used in annots throughout the code base; just make `.msg.__msg_spec__` delegate to it. Add some new codec methods: - `pld_spec_str`: for the `str`-casted value of the payload spec, generally useful in logging content. - `msg_spec_items()`: to render a `dict` of msg types to their `str()`-casted values with support for singling out a specific `MsgType`, type by input `msg` instance. - `pformat_msg_spec()`: for rendering the (partial) `.msg_spec` as a formatted `str` useful in logging. Oh right, add a `Error._msg_dict: dict` in support of the previous commit (for `MsgTypeError` packing as RAEs) such that our error msg type can house a non-type-spec decoded wire-bytes for error reporting/analysis purposes.runtime_to_msgspec
parent
cf48fdecfe
commit
15549f7c26
|
@ -19,7 +19,6 @@ Built-in messaging patterns, types, APIs and helpers.
|
|||
|
||||
'''
|
||||
from typing import (
|
||||
Union,
|
||||
TypeAlias,
|
||||
)
|
||||
from .ptr import (
|
||||
|
@ -56,8 +55,9 @@ from .types import (
|
|||
|
||||
# full msg class set from above as list
|
||||
__msg_types__ as __msg_types__,
|
||||
|
||||
# type-alias for union of all msgs
|
||||
MsgType as MsgType,
|
||||
)
|
||||
# TODO: use new type declaration syntax for msg-type-spec
|
||||
# https://docs.python.org/3/library/typing.html#type-aliases
|
||||
# https://docs.python.org/3/reference/simple_stmts.html#type
|
||||
__msg_spec__: TypeAlias = Union[*__msg_types__]
|
||||
|
||||
__msg_spec__: TypeAlias = MsgType
|
||||
|
|
|
@ -57,7 +57,7 @@ from trio.lowlevel import (
|
|||
from tractor.msg.pretty_struct import Struct
|
||||
from tractor.msg.types import (
|
||||
mk_msg_spec,
|
||||
Msg,
|
||||
MsgType,
|
||||
)
|
||||
|
||||
|
||||
|
@ -87,12 +87,50 @@ class MsgCodec(Struct):
|
|||
|
||||
pld_spec: Union[Type[Struct]]|None
|
||||
|
||||
@property
|
||||
def pld_spec_str(self) -> str:
|
||||
spec: Union[Type]|Type = self.pld_spec
|
||||
|
||||
# TODO: could also use match: instead?
|
||||
if getattr(spec, '__args__', False):
|
||||
# `typing.Union` case
|
||||
return str(spec)
|
||||
else:
|
||||
return spec.__name__
|
||||
|
||||
# struct type unions
|
||||
# https://jcristharif.com/msgspec/structs.html#tagged-unions
|
||||
@property
|
||||
def msg_spec(self) -> Union[Type[Struct]]:
|
||||
return self._dec.type
|
||||
|
||||
def msg_spec_items(
|
||||
self,
|
||||
msg: MsgType|None = None,
|
||||
|
||||
) -> dict[str, MsgType]|str:
|
||||
|
||||
msgt_table: dict[str, MsgType] = {
|
||||
msgt: str(msgt)
|
||||
for msgt in self.msg_spec.__args__
|
||||
}
|
||||
if msg:
|
||||
msgt: MsgType = type(msg)
|
||||
str_repr: str = msgt_table[msgt]
|
||||
return {msgt: str_repr}
|
||||
|
||||
return msgt_table
|
||||
|
||||
# TODO: some way to make `pretty_struct.Struct` use this
|
||||
# wrapped field over the `.msg_spec` one?
|
||||
def pformat_msg_spec(
|
||||
self,
|
||||
msg: MsgType|None = None,
|
||||
) -> str:
|
||||
return '\n'.join(
|
||||
self.msg_spec_items(msg=msg).values()
|
||||
)
|
||||
|
||||
lib: ModuleType = msgspec
|
||||
|
||||
# TODO: a sub-decoder system as well?
|
||||
|
@ -108,7 +146,7 @@ class MsgCodec(Struct):
|
|||
# OR
|
||||
# ) = {
|
||||
# # pre-seed decoders for std-py-type-set for use when
|
||||
# # `Msg.pld == None|Any`.
|
||||
# # `MsgType.pld == None|Any`.
|
||||
# None: msgpack.Decoder(Any),
|
||||
# Any: msgpack.Decoder(Any),
|
||||
# }
|
||||
|
@ -303,7 +341,7 @@ def mk_codec(
|
|||
# by `tag_field: str` value key?
|
||||
# payload_msg_specs: dict[
|
||||
# str, # tag_field value as sub-decoder key
|
||||
# Union[Type[Struct]] # `Msg.pld` type spec
|
||||
# Union[Type[Struct]] # `MsgType.pld` type spec
|
||||
# ]|None = None,
|
||||
|
||||
libname: str = 'msgspec',
|
||||
|
@ -336,7 +374,7 @@ def mk_codec(
|
|||
raise RuntimeError(
|
||||
f'If a payload spec is provided,\n'
|
||||
"the builtin SC-shuttle-protocol's msg set\n"
|
||||
f'(i.e. `{Msg}`) MUST be used!\n\n'
|
||||
f'(i.e. a `{MsgType}`) MUST be used!\n\n'
|
||||
f'However both values were passed as => mk_codec(\n'
|
||||
f' ipc_msg_spec={ipc_msg_spec}`\n'
|
||||
f' ipc_pld_spec={ipc_pld_spec}`\n)\n'
|
||||
|
|
|
@ -31,6 +31,7 @@ from typing import (
|
|||
Literal,
|
||||
Type,
|
||||
TypeVar,
|
||||
TypeAlias,
|
||||
Union,
|
||||
)
|
||||
|
||||
|
@ -400,16 +401,29 @@ class CancelAck(
|
|||
pld: bool
|
||||
|
||||
|
||||
# TODO: unify this with `._exceptions.RemoteActorError`
|
||||
# such that we can have a msg which is both raisable and
|
||||
# IPC-wire ready?
|
||||
# B~o
|
||||
class Error(
|
||||
Struct,
|
||||
tag=True,
|
||||
tag_field='msg_type',
|
||||
|
||||
# TODO may omit defaults?
|
||||
# https://jcristharif.com/msgspec/structs.html#omitting-default-values
|
||||
# omit_defaults=True,
|
||||
):
|
||||
'''
|
||||
A pkt that wraps `RemoteActorError`s for relay and raising.
|
||||
|
||||
Fields are 1-to-1 meta-data as needed originally by
|
||||
`RemoteActorError.msgdata: dict`.
|
||||
`RemoteActorError.msgdata: dict` but now are defined here.
|
||||
|
||||
Note: this msg shuttles `ContextCancelled` and `StreamOverrun`
|
||||
as well is used to rewrap any `MsgTypeError` for relay-reponse
|
||||
to bad `Yield.pld` senders during an IPC ctx's streaming dialog
|
||||
phase.
|
||||
|
||||
'''
|
||||
src_uid: tuple[str, str]
|
||||
|
@ -428,6 +442,10 @@ class Error(
|
|||
# `StreamOverrun`
|
||||
sender: tuple[str, str]|None = None
|
||||
|
||||
# for the `MsgTypeError` case where the receiver side
|
||||
# decodes the underlying original `Msg`-subtype
|
||||
_msg_dict: dict|None = None
|
||||
|
||||
|
||||
# TODO: should be make a msg version of `ContextCancelled?`
|
||||
# and/or with a scope field or a full `ActorCancelled`?
|
||||
|
@ -486,6 +504,11 @@ __msg_types__: list[Msg] = (
|
|||
_payload_msgs
|
||||
)
|
||||
|
||||
# TODO: use new type declaration syntax for msg-type-spec
|
||||
# https://docs.python.org/3/library/typing.html#type-aliases
|
||||
# https://docs.python.org/3/reference/simple_stmts.html#type
|
||||
MsgType: TypeAlias = Union[*__msg_types__]
|
||||
|
||||
|
||||
def mk_msg_spec(
|
||||
payload_type_union: Union[Type] = Any,
|
||||
|
|
Loading…
Reference in New Issue