1
- from typing import Any , List , Set
1
+ import importlib
2
+ import json
3
+ import logging
4
+ from typing import Any , List , Optional , Set
2
5
3
6
from colorama import Fore , Style
4
7
from fastapi import status as HttpStatusCode
5
8
from grpc import StatusCode as GrpcStatusCode
6
9
7
10
from feast .field import Field
8
11
12
+ logger = logging .getLogger (__name__ )
13
+
9
14
10
15
class FeastError (Exception ):
11
16
pass
12
17
13
- def rpc_status_code (self ) -> GrpcStatusCode :
18
+ def grpc_status_code (self ) -> GrpcStatusCode :
14
19
return GrpcStatusCode .INTERNAL
15
20
16
21
def http_status_code (self ) -> int :
17
22
return HttpStatusCode .HTTP_500_INTERNAL_SERVER_ERROR
18
23
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
+
19
67
20
68
class DataSourceNotFoundException (FeastError ):
21
69
def __init__ (self , path ):
@@ -41,7 +89,7 @@ def __init__(self, ds_name: str):
41
89
class FeastObjectNotFoundException (FeastError ):
42
90
pass
43
91
44
- def rpc_status_code (self ) -> GrpcStatusCode :
92
+ def grpc_status_code (self ) -> GrpcStatusCode :
45
93
return GrpcStatusCode .NOT_FOUND
46
94
47
95
def http_status_code (self ) -> int :
@@ -443,7 +491,7 @@ class FeastPermissionError(FeastError, PermissionError):
443
491
def __init__ (self , details : str ):
444
492
super ().__init__ (f"Permission error:\n { details } " )
445
493
446
- def rpc_status_code (self ) -> GrpcStatusCode :
494
+ def grpc_status_code (self ) -> GrpcStatusCode :
447
495
return GrpcStatusCode .PERMISSION_DENIED
448
496
449
497
def http_status_code (self ) -> int :
0 commit comments