Skip to content

Commit b4466be

Browse files
feat: Adding reason, domain, metadata & error_details fields in DBAPI custom exceptions.
1 parent 7fad8d8 commit b4466be

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

google/cloud/spanner_dbapi/cursor.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,11 +281,11 @@ def execute(self, sql, args=None):
281281
self._do_execute_update, sql, args or None
282282
)
283283
except (AlreadyExists, FailedPrecondition, OutOfRange) as e:
284-
raise IntegrityError(getattr(e, "details", e))
284+
raise IntegrityError(getattr(e, "details", e)) from e
285285
except InvalidArgument as e:
286-
raise ProgrammingError(getattr(e, "details", e))
286+
raise ProgrammingError(getattr(e, "details", e)) from e
287287
except InternalServerError as e:
288-
raise OperationalError(getattr(e, "details", e))
288+
raise OperationalError(getattr(e, "details", e)) from e
289289

290290
@check_not_closed
291291
def executemany(self, operation, seq_of_params):

google/cloud/spanner_dbapi/exceptions.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
"""Spanner DB API exceptions."""
1616

17+
from google.api_core.exceptions import GoogleAPICallError
18+
1719

1820
class Warning(Exception):
1921
"""Important DB API warning."""
@@ -27,7 +29,49 @@ class Error(Exception):
2729
Does not include :class:`Warning`.
2830
"""
2931

30-
pass
32+
def _is_error_cause_instance_of_google_api_exception(self):
33+
return isinstance(self.__cause__, GoogleAPICallError)
34+
35+
@property
36+
def reason(self):
37+
"""The reason of the error.
38+
Reference:
39+
https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112
40+
Returns:
41+
Union[str, None]: An optional string containing reason of the error.
42+
"""
43+
return self.__cause__.reason if self._is_error_cause_instance_of_google_api_exception() else None
44+
45+
@property
46+
def domain(self):
47+
"""The logical grouping to which the "reason" belongs.
48+
Reference:
49+
https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112
50+
Returns:
51+
Union[str, None]: An optional string containing a logical grouping to which the "reason" belongs.
52+
"""
53+
return self.__cause__.domain if self._is_error_cause_instance_of_google_api_exception() else None
54+
55+
@property
56+
def metadata(self):
57+
"""Additional structured details about this error.
58+
Reference:
59+
https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112
60+
Returns:
61+
Union[Dict[str, str], None]: An optional object containing structured details about the error.
62+
"""
63+
return self.__cause__.metadata if self._is_error_cause_instance_of_google_api_exception() else None
64+
65+
@property
66+
def details(self):
67+
"""Information contained in google.rpc.status.details.
68+
Reference:
69+
https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto
70+
https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto
71+
Returns:
72+
Sequence[Any]: A list of structured objects from error_details.proto
73+
"""
74+
return self.__cause__.details if self._is_error_cause_instance_of_google_api_exception() else None
3175

3276

3377
class InterfaceError(Error):

0 commit comments

Comments
 (0)