diff --git a/libs/labelbox/pyproject.toml b/libs/labelbox/pyproject.toml index ad581245b..835e168c3 100644 --- a/libs/labelbox/pyproject.toml +++ b/libs/labelbox/pyproject.toml @@ -12,7 +12,7 @@ dependencies = [ "tqdm>=4.66.2", "geojson>=3.1.0", "mypy==1.10.1", - "lbox-clients==1.0.0", + "lbox-clients==1.1.0", ] readme = "README.md" requires-python = ">=3.8" diff --git a/libs/labelbox/src/labelbox/client.py b/libs/labelbox/src/labelbox/client.py index 78ebe53c6..cccd23be1 100644 --- a/libs/labelbox/src/labelbox/client.py +++ b/libs/labelbox/src/labelbox/client.py @@ -8,7 +8,7 @@ import urllib.parse from collections import defaultdict from types import MappingProxyType -from typing import Any, Dict, List, Optional, Union, overload +from typing import Any, Callable, Dict, List, Optional, Union, overload import lbox.exceptions import requests @@ -159,6 +159,9 @@ def execute( experimental=False, error_log_key="message", raise_return_resource_not_found=False, + error_handlers: Optional[ + Dict[str, Callable[[requests.models.Response], None]] + ] = None, ) -> Dict[str, Any]: """Executes a GraphQL query. @@ -167,6 +170,8 @@ def execute( variables (dict): Variables to pass to the query. raise_return_resource_not_found (bool): If True, raise a ResourceNotFoundError if the query returns None. + error_handlers (dict): A dictionary mapping graphql error code to handler functions. + Allows a caller to handle specific errors reporting in a custom way or produce more user-friendly readable messages Returns: dict: The response from the server. @@ -180,6 +185,7 @@ def execute( experimental=experimental, error_log_key=error_log_key, raise_return_resource_not_found=raise_return_resource_not_found, + error_handlers=error_handlers, ) def upload_file(self, path: str) -> str: diff --git a/libs/labelbox/src/labelbox/schema/labeling_service.py b/libs/labelbox/src/labelbox/schema/labeling_service.py index 571ef8099..0b7dab6bd 100644 --- a/libs/labelbox/src/labelbox/schema/labeling_service.py +++ b/libs/labelbox/src/labelbox/schema/labeling_service.py @@ -1,7 +1,8 @@ +import json from datetime import datetime from typing import Any -from lbox.exceptions import ResourceNotFoundError +from lbox.exceptions import LabelboxError, ResourceNotFoundError from labelbox.schema.labeling_service_dashboard import LabelingServiceDashboard from labelbox.schema.labeling_service_status import LabelingServiceStatus @@ -105,12 +106,24 @@ def request(self) -> "LabelingService": query_str, {"projectId": self.project_id}, raise_return_resource_not_found=True, + error_handlers={"MALFORMED_REQUEST": self._raise_readable_errors}, ) success = result["validateAndRequestProjectBoostWorkforce"]["success"] if not success: raise Exception("Failed to start labeling service") return LabelingService.get(self.client, self.project_id) + def _raise_readable_errors(self, response): + errors = response.json().get("errors", []) + if errors: + message = errors[0].get( + "errors", json.dumps([{"error": "Unknown error"}]) + ) + error_messages = [error["error"] for error in message] + else: + error_messages = ["Uknown error"] + raise LabelboxError(". ".join(error_messages)) + @classmethod def getOrCreate(cls, client, project_id: Cuid) -> "LabelingService": """ diff --git a/libs/lbox-clients/pyproject.toml b/libs/lbox-clients/pyproject.toml index 1ad53b2c9..91ee3ac79 100644 --- a/libs/lbox-clients/pyproject.toml +++ b/libs/lbox-clients/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lbox-clients" -version = "1.0.0" +version = "1.1.0" description = "This module contains client sdk uses to conntect to the Labelbox API and backends" authors = [ { name = "Labelbox", email = "engineering@labelbox.com" } diff --git a/libs/lbox-clients/src/lbox/request_client.py b/libs/lbox-clients/src/lbox/request_client.py index 35464f812..5e32f90dd 100644 --- a/libs/lbox-clients/src/lbox/request_client.py +++ b/libs/lbox-clients/src/lbox/request_client.py @@ -304,7 +304,13 @@ def get_error_status_code(error: dict) -> int: malformed_request_error = check_errors( ["MALFORMED_REQUEST"], "extensions", "code" ) + + error_code = "MALFORMED_REQUEST" if malformed_request_error is not None: + if error_handlers and error_code in error_handlers: + handler = error_handlers[error_code] + handler(response) + return None raise exceptions.MalformedQueryException( malformed_request_error[error_log_key] )