From b4466be4c3fbf3685caca58873688d54a1cbfd43 Mon Sep 17 00:00:00 2001 From: gauravpurohit Date: Sun, 11 Sep 2022 11:33:41 +0000 Subject: [PATCH 1/3] feat: Adding reason, domain, metadata & error_details fields in DBAPI custom exceptions. --- google/cloud/spanner_dbapi/cursor.py | 6 ++-- google/cloud/spanner_dbapi/exceptions.py | 46 +++++++++++++++++++++++- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/google/cloud/spanner_dbapi/cursor.py b/google/cloud/spanner_dbapi/cursor.py index 0fc36a72a9..4ffeac1a70 100644 --- a/google/cloud/spanner_dbapi/cursor.py +++ b/google/cloud/spanner_dbapi/cursor.py @@ -281,11 +281,11 @@ def execute(self, sql, args=None): self._do_execute_update, sql, args or None ) except (AlreadyExists, FailedPrecondition, OutOfRange) as e: - raise IntegrityError(getattr(e, "details", e)) + raise IntegrityError(getattr(e, "details", e)) from e except InvalidArgument as e: - raise ProgrammingError(getattr(e, "details", e)) + raise ProgrammingError(getattr(e, "details", e)) from e except InternalServerError as e: - raise OperationalError(getattr(e, "details", e)) + raise OperationalError(getattr(e, "details", e)) from e @check_not_closed def executemany(self, operation, seq_of_params): diff --git a/google/cloud/spanner_dbapi/exceptions.py b/google/cloud/spanner_dbapi/exceptions.py index f5f85a752a..3183935d27 100644 --- a/google/cloud/spanner_dbapi/exceptions.py +++ b/google/cloud/spanner_dbapi/exceptions.py @@ -14,6 +14,8 @@ """Spanner DB API exceptions.""" +from google.api_core.exceptions import GoogleAPICallError + class Warning(Exception): """Important DB API warning.""" @@ -27,7 +29,49 @@ class Error(Exception): Does not include :class:`Warning`. """ - pass + def _is_error_cause_instance_of_google_api_exception(self): + return isinstance(self.__cause__, GoogleAPICallError) + + @property + def reason(self): + """The reason of the error. + Reference: + https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112 + Returns: + Union[str, None]: An optional string containing reason of the error. + """ + return self.__cause__.reason if self._is_error_cause_instance_of_google_api_exception() else None + + @property + def domain(self): + """The logical grouping to which the "reason" belongs. + Reference: + https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112 + Returns: + Union[str, None]: An optional string containing a logical grouping to which the "reason" belongs. + """ + return self.__cause__.domain if self._is_error_cause_instance_of_google_api_exception() else None + + @property + def metadata(self): + """Additional structured details about this error. + Reference: + https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112 + Returns: + Union[Dict[str, str], None]: An optional object containing structured details about the error. + """ + return self.__cause__.metadata if self._is_error_cause_instance_of_google_api_exception() else None + + @property + def details(self): + """Information contained in google.rpc.status.details. + Reference: + https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto + https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto + Returns: + Sequence[Any]: A list of structured objects from error_details.proto + """ + return self.__cause__.details if self._is_error_cause_instance_of_google_api_exception() else None class InterfaceError(Error): From 8bd2db256b19e0a4ab66e7bbb3ed260420432964 Mon Sep 17 00:00:00 2001 From: Astha Mohta Date: Mon, 12 Sep 2022 20:14:21 +0530 Subject: [PATCH 2/3] linting --- google/cloud/spanner_dbapi/exceptions.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/google/cloud/spanner_dbapi/exceptions.py b/google/cloud/spanner_dbapi/exceptions.py index 3183935d27..ffc42e7d8a 100644 --- a/google/cloud/spanner_dbapi/exceptions.py +++ b/google/cloud/spanner_dbapi/exceptions.py @@ -40,7 +40,11 @@ def reason(self): Returns: Union[str, None]: An optional string containing reason of the error. """ - return self.__cause__.reason if self._is_error_cause_instance_of_google_api_exception() else None + return ( + self.__cause__.reason + if self._is_error_cause_instance_of_google_api_exception() + else None + ) @property def domain(self): @@ -50,7 +54,11 @@ def domain(self): Returns: Union[str, None]: An optional string containing a logical grouping to which the "reason" belongs. """ - return self.__cause__.domain if self._is_error_cause_instance_of_google_api_exception() else None + return ( + self.__cause__.domain + if self._is_error_cause_instance_of_google_api_exception() + else None + ) @property def metadata(self): @@ -60,7 +68,11 @@ def metadata(self): Returns: Union[Dict[str, str], None]: An optional object containing structured details about the error. """ - return self.__cause__.metadata if self._is_error_cause_instance_of_google_api_exception() else None + return ( + self.__cause__.metadata + if self._is_error_cause_instance_of_google_api_exception() + else None + ) @property def details(self): @@ -71,7 +83,11 @@ def details(self): Returns: Sequence[Any]: A list of structured objects from error_details.proto """ - return self.__cause__.details if self._is_error_cause_instance_of_google_api_exception() else None + return ( + self.__cause__.details + if self._is_error_cause_instance_of_google_api_exception() + else None + ) class InterfaceError(Error): From 2ee975f86d42d4c52304522a8bad300f6f367f0c Mon Sep 17 00:00:00 2001 From: gauravpurohit Date: Mon, 26 Sep 2022 10:18:17 +0000 Subject: [PATCH 3/3] docs: Updating function docs --- google/cloud/spanner_dbapi/exceptions.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/google/cloud/spanner_dbapi/exceptions.py b/google/cloud/spanner_dbapi/exceptions.py index ffc42e7d8a..723ee34fd2 100644 --- a/google/cloud/spanner_dbapi/exceptions.py +++ b/google/cloud/spanner_dbapi/exceptions.py @@ -36,7 +36,7 @@ def _is_error_cause_instance_of_google_api_exception(self): def reason(self): """The reason of the error. Reference: - https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112 + https://cloud.google.com/apis/design/errors#error_info Returns: Union[str, None]: An optional string containing reason of the error. """ @@ -50,7 +50,7 @@ def reason(self): def domain(self): """The logical grouping to which the "reason" belongs. Reference: - https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112 + https://cloud.google.com/apis/design/errors#error_info Returns: Union[str, None]: An optional string containing a logical grouping to which the "reason" belongs. """ @@ -64,7 +64,7 @@ def domain(self): def metadata(self): """Additional structured details about this error. Reference: - https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112 + https://cloud.google.com/apis/design/errors#error_info Returns: Union[Dict[str, str], None]: An optional object containing structured details about the error. """ @@ -78,8 +78,8 @@ def metadata(self): def details(self): """Information contained in google.rpc.status.details. Reference: - https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto - https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto + https://cloud.google.com/apis/design/errors#error_model + https://cloud.google.com/apis/design/errors#error_details Returns: Sequence[Any]: A list of structured objects from error_details.proto """