forked from goodboy/tractor
1
0
Fork 0

Add a specially handled `ContextCancelled` error

try_msgspec
Tyler Goodlet 2021-06-13 18:01:49 -04:00
parent 25c159961b
commit 4ed38281b3
1 changed files with 40 additions and 14 deletions

View File

@ -1,7 +1,7 @@
""" """
Our classy exception set. Our classy exception set.
""" """
from typing import Dict, Any from typing import Dict, Any, Optional
import importlib import importlib
import builtins import builtins
import traceback import traceback
@ -15,17 +15,16 @@ _this_mod = importlib.import_module(__name__)
class RemoteActorError(Exception): class RemoteActorError(Exception):
# TODO: local recontruction of remote exception deats # TODO: local recontruction of remote exception deats
"Remote actor exception bundled locally" "Remote actor exception bundled locally"
def __init__(self, message, type_str, **msgdata) -> None: def __init__(
super().__init__(message) self,
for ns in [builtins, _this_mod, trio]: message: str,
try: suberror_type: Optional[Exception] = None,
self.type = getattr(ns, type_str) **msgdata
break
except AttributeError:
continue
else:
self.type = Exception
) -> None:
super().__init__(message)
self.type = suberror_type
self.msgdata = msgdata self.msgdata = msgdata
# TODO: a trio.MultiError.catch like context manager # TODO: a trio.MultiError.catch like context manager
@ -38,6 +37,10 @@ class InternalActorError(RemoteActorError):
""" """
class ContextCancelled(RemoteActorError):
"Inter-actor task context cancelled itself on the callee side."
class NoResult(RuntimeError): class NoResult(RuntimeError):
"No final result is expected for this actor" "No final result is expected for this actor"
@ -70,12 +73,35 @@ def unpack_error(
"""Unpack an 'error' message from the wire """Unpack an 'error' message from the wire
into a local ``RemoteActorError``. into a local ``RemoteActorError``.
""" """
tb_str = msg['error'].get('tb_str', '') error = msg['error']
return err_type(
f"{chan.uid}\n" + tb_str, tb_str = error.get('tb_str', '')
message = f"{chan.uid}\n" + tb_str
type_name = error['type_str']
suberror_type = Exception
if type_name == 'ContextCancelled':
err_type = ContextCancelled
suberror_type = trio.Cancelled
else: # try to lookup a suitable local error type
for ns in [builtins, _this_mod, trio]:
try:
suberror_type = getattr(ns, type_name)
break
except AttributeError:
continue
exc = err_type(
message,
suberror_type=suberror_type,
# unpack other fields into error type init
**msg['error'], **msg['error'],
) )
return exc
def is_multi_cancelled(exc: BaseException) -> bool: def is_multi_cancelled(exc: BaseException) -> bool:
"""Predicate to determine if a ``trio.MultiError`` contains only """Predicate to determine if a ``trio.MultiError`` contains only