Skip to content

Commit 2a74060

Browse files
feat: Adding reason, domain, metadata & error_details fields in Custom Exceptions for additional info (#804)
* feat: Adding reason, domain, metadata & error_details fields in DBAPI custom exceptions. * linting * docs: Updating function docs Co-authored-by: Astha Mohta <asthamohta@google.com>
1 parent d88b37f commit 2a74060

File tree

2 files changed

+64
-4
lines changed

2 files changed

+64
-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: 61 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,65 @@ 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://cloud.google.com/apis/design/errors#error_info
40+
Returns:
41+
Union[str, None]: An optional string containing reason of the error.
42+
"""
43+
return (
44+
self.__cause__.reason
45+
if self._is_error_cause_instance_of_google_api_exception()
46+
else None
47+
)
48+
49+
@property
50+
def domain(self):
51+
"""The logical grouping to which the "reason" belongs.
52+
Reference:
53+
https://cloud.google.com/apis/design/errors#error_info
54+
Returns:
55+
Union[str, None]: An optional string containing a logical grouping to which the "reason" belongs.
56+
"""
57+
return (
58+
self.__cause__.domain
59+
if self._is_error_cause_instance_of_google_api_exception()
60+
else None
61+
)
62+
63+
@property
64+
def metadata(self):
65+
"""Additional structured details about this error.
66+
Reference:
67+
https://cloud.google.com/apis/design/errors#error_info
68+
Returns:
69+
Union[Dict[str, str], None]: An optional object containing structured details about the error.
70+
"""
71+
return (
72+
self.__cause__.metadata
73+
if self._is_error_cause_instance_of_google_api_exception()
74+
else None
75+
)
76+
77+
@property
78+
def details(self):
79+
"""Information contained in google.rpc.status.details.
80+
Reference:
81+
https://cloud.google.com/apis/design/errors#error_model
82+
https://cloud.google.com/apis/design/errors#error_details
83+
Returns:
84+
Sequence[Any]: A list of structured objects from error_details.proto
85+
"""
86+
return (
87+
self.__cause__.details
88+
if self._is_error_cause_instance_of_google_api_exception()
89+
else None
90+
)
3191

3292

3393
class InterfaceError(Error):

0 commit comments

Comments
 (0)