1- from typing import Any , List , Set
1+ import importlib
2+ import json
3+ import logging
4+ from typing import Any , List , Optional , Set
25
36from colorama import Fore , Style
47from fastapi import status as HttpStatusCode
58from grpc import StatusCode as GrpcStatusCode
69
710from feast .field import Field
811
12+ logger = logging .getLogger (__name__ )
13+
914
1015class FeastError (Exception ):
1116 pass
1217
13- def rpc_status_code (self ) -> GrpcStatusCode :
18+ def grpc_status_code (self ) -> GrpcStatusCode :
1419 return GrpcStatusCode .INTERNAL
1520
1621 def http_status_code (self ) -> int :
1722 return HttpStatusCode .HTTP_500_INTERNAL_SERVER_ERROR
1823
24+ def __str__ (self ) -> str :
25+ if hasattr (self , "__overridden_message__" ):
26+ return str (getattr (self , "__overridden_message__" ))
27+ return super ().__str__ ()
28+
29+ def __repr__ (self ) -> str :
30+ if hasattr (self , "__overridden_message__" ):
31+ return f"{ type (self ).__name__ } ('{ getattr (self ,'__overridden_message__' )} ')"
32+ return super ().__repr__ ()
33+
34+ def to_error_detail (self ) -> str :
35+ """
36+ Returns a JSON representation of the error for serialization purposes.
37+
38+ Returns:
39+ str: a string representation of a JSON document including `module`, `class` and `message` fields.
40+ """
41+
42+ m = {
43+ "module" : f"{ type (self ).__module__ } " ,
44+ "class" : f"{ type (self ).__name__ } " ,
45+ "message" : f"{ str (self )} " ,
46+ }
47+ return json .dumps (m )
48+
49+ @staticmethod
50+ def from_error_detail (detail : str ) -> Optional ["FeastError" ]:
51+ try :
52+ m = json .loads (detail )
53+ if all (f in m for f in ["module" , "class" , "message" ]):
54+ module_name = m ["module" ]
55+ class_name = m ["class" ]
56+ message = m ["message" ]
57+ module = importlib .import_module (module_name )
58+ class_reference = getattr (module , class_name )
59+
60+ instance = class_reference (message )
61+ setattr (instance , "__overridden_message__" , message )
62+ return instance
63+ except Exception as e :
64+ logger .warning (f"Invalid error detail: { detail } : { e } " )
65+ return None
66+
1967
2068class DataSourceNotFoundException (FeastError ):
2169 def __init__ (self , path ):
@@ -41,7 +89,7 @@ def __init__(self, ds_name: str):
4189class FeastObjectNotFoundException (FeastError ):
4290 pass
4391
44- def rpc_status_code (self ) -> GrpcStatusCode :
92+ def grpc_status_code (self ) -> GrpcStatusCode :
4593 return GrpcStatusCode .NOT_FOUND
4694
4795 def http_status_code (self ) -> int :
@@ -443,7 +491,7 @@ class FeastPermissionError(FeastError, PermissionError):
443491 def __init__ (self , details : str ):
444492 super ().__init__ (f"Permission error:\n { details } " )
445493
446- def rpc_status_code (self ) -> GrpcStatusCode :
494+ def grpc_status_code (self ) -> GrpcStatusCode :
447495 return GrpcStatusCode .PERMISSION_DENIED
448496
449497 def http_status_code (self ) -> int :
0 commit comments