22
33import pickle
44from dataclasses import dataclass
5+ from types import TracebackType
56from typing import Any
67
78import google .protobuf .any_pb2
@@ -280,7 +281,13 @@ class Error:
280281 Output.
281282 """
282283
283- def __init__ (self , status : Status , type : str | None , message : str | None ):
284+ def __init__ (
285+ self ,
286+ status : Status ,
287+ type : str | None ,
288+ message : str | None ,
289+ value : Exception | None = None ,
290+ ):
284291 """Create a new Error.
285292
286293 Args:
@@ -300,6 +307,7 @@ def __init__(self, status: Status, type: str | None, message: str | None):
300307 self .type = type
301308 self .message = message
302309 self .status = status
310+ self .value = value
303311
304312 @classmethod
305313 def from_exception (cls , ex : Exception , status : Status | None = None ) -> Error :
@@ -313,18 +321,29 @@ def from_exception(cls, ex: Exception, status: Status | None = None) -> Error:
313321 if status is None :
314322 status = status_for_error (ex )
315323
316- return Error (status , ex .__class__ .__qualname__ , str (ex ))
324+ return Error (status , ex .__class__ .__qualname__ , str (ex ), ex )
317325
318326 def to_exception (self ) -> Exception :
319- # TODO: use correct error type
320- return RuntimeError (self .message )
327+ if self .value is not None :
328+ return self .value
329+
330+ g = globals ()
331+ try :
332+ cls = g [self .type ]
333+ assert issubclass (cls , Exception )
334+ except (KeyError , AssertionError ):
335+ return RuntimeError (self .message )
336+ else :
337+ return cls (self .message )
321338
322339 @classmethod
323340 def _from_proto (cls , proto : error_pb .Error ) -> Error :
324- return cls (Status .UNSPECIFIED , proto .type , proto .message )
341+ value = pickle .loads (proto .value ) if proto .value else None
342+ return cls (Status .UNSPECIFIED , proto .type , proto .message , value )
325343
326344 def _as_proto (self ) -> error_pb .Error :
327- return error_pb .Error (type = self .type , message = self .message )
345+ value = pickle .dumps (self .value ) if self .value else None
346+ return error_pb .Error (type = self .type , message = self .message , value = value )
328347
329348
330349def _any_unpickle (any : google .protobuf .any_pb2 .Any ) -> Any :
0 commit comments