From 1e489b9392e8929af000c1ddc1cd2467644bbf91 Mon Sep 17 00:00:00 2001 From: Diego Fernandez Date: Mon, 16 Jun 2025 10:03:36 -0600 Subject: [PATCH 1/6] Improve QueryFailedError --- dbtsl/api/adbc/client/base.py | 2 +- dbtsl/api/graphql/client/asyncio.py | 2 +- dbtsl/api/graphql/client/sync.py | 2 +- dbtsl/error.py | 19 +++++++++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/dbtsl/api/adbc/client/base.py b/dbtsl/api/adbc/client/base.py index 44e9643..21e7554 100644 --- a/dbtsl/api/adbc/client/base.py +++ b/dbtsl/api/adbc/client/base.py @@ -57,7 +57,7 @@ def _handle_error(self, err: Exception) -> None: raise AuthError(err.args) from err if err.status_code == AdbcStatusCode.INVALID_ARGUMENT: - raise QueryFailedError(err.args) from err + raise QueryFailedError(err.details, err.status_code) from err # TODO: timeouts are not implemented for ADBC # See: https://arrow.apache.org/adbc/current/driver/flight_sql.html#timeouts diff --git a/dbtsl/api/graphql/client/asyncio.py b/dbtsl/api/graphql/client/asyncio.py index a734c4d..645729e 100644 --- a/dbtsl/api/graphql/client/asyncio.py +++ b/dbtsl/api/graphql/client/asyncio.py @@ -157,7 +157,7 @@ async def query(self, **params: Unpack[QueryParameters]) -> "pa.Table": variables={"query_id": query_id, "page_num": 1}, ) if first_page_results.status != QueryStatus.SUCCESSFUL: - raise QueryFailedError() + raise QueryFailedError(first_page_results.error, first_page_results.status, query_id) assert first_page_results.total_pages is not None diff --git a/dbtsl/api/graphql/client/sync.py b/dbtsl/api/graphql/client/sync.py index 5ac2f50..1e996fa 100644 --- a/dbtsl/api/graphql/client/sync.py +++ b/dbtsl/api/graphql/client/sync.py @@ -148,7 +148,7 @@ def query(self, **params: Unpack[QueryParameters]) -> "pa.Table": }, ) if first_page_results.status != QueryStatus.SUCCESSFUL: - raise QueryFailedError() + raise QueryFailedError(first_page_results.error, first_page_results.status, query_id) assert first_page_results.total_pages is not None diff --git a/dbtsl/error.py b/dbtsl/error.py index 12bb955..40f7dc7 100644 --- a/dbtsl/error.py +++ b/dbtsl/error.py @@ -1,4 +1,5 @@ import json +from typing import Any class SemanticLayerError(RuntimeError): @@ -46,6 +47,24 @@ class RetryTimeoutError(TimeoutError): class QueryFailedError(SemanticLayerError): """Raise whenever a query has failed.""" + def __init__(self, message: Any, status: Any, query_id: str | None = None) -> None: + """Initialize the query failed error. + + Args: + message: The message or error details + status: The stringified status or the response + query_id: The query ID for GQL requests + """ + self.message = str(message) + self.status = str(status) + self.query_id = query_id + + def __str__(self) -> str: # noqa: D105 + content = f"message={self.message}), status={self.status}" + if self.query_id: + content += f", query_id={self.query_id}" + return f"{self.__class__.__name__}({content})" + class AuthError(SemanticLayerError): """Raise whenever there was a problem authenticating to the API.""" From 85c00cd430f67249b0caf4ff878e09e32d73ff72 Mon Sep 17 00:00:00 2001 From: Diego Fernandez Date: Mon, 16 Jun 2025 10:09:02 -0600 Subject: [PATCH 2/6] Fix typing --- dbtsl/error.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbtsl/error.py b/dbtsl/error.py index 40f7dc7..7f7a00a 100644 --- a/dbtsl/error.py +++ b/dbtsl/error.py @@ -1,5 +1,5 @@ import json -from typing import Any +from typing import Any, Optional class SemanticLayerError(RuntimeError): @@ -47,7 +47,7 @@ class RetryTimeoutError(TimeoutError): class QueryFailedError(SemanticLayerError): """Raise whenever a query has failed.""" - def __init__(self, message: Any, status: Any, query_id: str | None = None) -> None: + def __init__(self, message: Any, status: Any, query_id: Optional[str] = None) -> None: """Initialize the query failed error. Args: From 135a9f4de235b8e29bdc3fa8235c0ad30dfb882a Mon Sep 17 00:00:00 2001 From: Diego Fernandez Date: Mon, 16 Jun 2025 10:11:07 -0600 Subject: [PATCH 3/6] Changie --- .changes/unreleased/Under the Hood-20250616-101046.yaml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changes/unreleased/Under the Hood-20250616-101046.yaml diff --git a/.changes/unreleased/Under the Hood-20250616-101046.yaml b/.changes/unreleased/Under the Hood-20250616-101046.yaml new file mode 100644 index 0000000..dec0df4 --- /dev/null +++ b/.changes/unreleased/Under the Hood-20250616-101046.yaml @@ -0,0 +1,3 @@ +kind: Under the Hood +body: add error, status, and query_id to QueryFailedError +time: 2025-06-16T10:10:46.504635-06:00 From 7247e94bd3b19aae25ad6573c42713061efded15 Mon Sep 17 00:00:00 2001 From: Diego Fernandez Date: Mon, 16 Jun 2025 10:15:56 -0600 Subject: [PATCH 4/6] Improve message handling --- dbtsl/error.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dbtsl/error.py b/dbtsl/error.py index 7f7a00a..a279e45 100644 --- a/dbtsl/error.py +++ b/dbtsl/error.py @@ -55,6 +55,9 @@ def __init__(self, message: Any, status: Any, query_id: Optional[str] = None) -> status: The stringified status or the response query_id: The query ID for GQL requests """ + # extract first error message if we get a list with just 1 message + if isinstance(message, list) and len(message) == 1: + message = message[0] self.message = str(message) self.status = str(status) self.query_id = query_id From 50b7777068e648d933c1a16942174682f76053e5 Mon Sep 17 00:00:00 2001 From: Diego Fernandez Date: Mon, 16 Jun 2025 10:37:08 -0600 Subject: [PATCH 5/6] Type ignore --- dbtsl/error.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dbtsl/error.py b/dbtsl/error.py index a279e45..0e719af 100644 --- a/dbtsl/error.py +++ b/dbtsl/error.py @@ -56,9 +56,9 @@ def __init__(self, message: Any, status: Any, query_id: Optional[str] = None) -> query_id: The query ID for GQL requests """ # extract first error message if we get a list with just 1 message - if isinstance(message, list) and len(message) == 1: - message = message[0] - self.message = str(message) + if isinstance(message, list) and len(message) == 1: # pyright: ignore + message = message[0] # pyright: ignore + self.message = str(message) # pyright: ignore self.status = str(status) self.query_id = query_id From f80e6dedb635ccb9ca3df3c9045078f3d6ce6c87 Mon Sep 17 00:00:00 2001 From: Diego Fernandez Date: Wed, 18 Jun 2025 09:58:00 -0600 Subject: [PATCH 6/6] Put message in quotes --- dbtsl/error.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbtsl/error.py b/dbtsl/error.py index 0e719af..9358d67 100644 --- a/dbtsl/error.py +++ b/dbtsl/error.py @@ -63,7 +63,7 @@ def __init__(self, message: Any, status: Any, query_id: Optional[str] = None) -> self.query_id = query_id def __str__(self) -> str: # noqa: D105 - content = f"message={self.message}), status={self.status}" + content = f"message=\"{self.message}\"), status={self.status}" if self.query_id: content += f", query_id={self.query_id}" return f"{self.__class__.__name__}({content})"