Skip to content

Commit 6252ea9

Browse files
authored
[PLT-1359] Vb/labeling service improve message reporting plt 1359 (#1769)
1 parent 5eb500c commit 6252ea9

File tree

4 files changed

+56
-19
lines changed

4 files changed

+56
-19
lines changed

libs/labelbox/src/labelbox/client.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import urllib.parse
1010
from collections import defaultdict
1111
from datetime import datetime, timezone
12-
from typing import Any, List, Dict, Union, Optional, overload
12+
from typing import Any, List, Dict, Union, Optional, overload, Callable
1313

1414
import requests
1515
import requests.exceptions
@@ -138,15 +138,19 @@ def _default_headers(self):
138138
@retry.Retry(predicate=retry.if_exception_type(
139139
labelbox.exceptions.InternalServerError,
140140
labelbox.exceptions.TimeoutError))
141-
def execute(self,
142-
query=None,
143-
params=None,
144-
data=None,
145-
files=None,
146-
timeout=60.0,
147-
experimental=False,
148-
error_log_key="message",
149-
raise_return_resource_not_found=False):
141+
def execute(
142+
self,
143+
query=None,
144+
params=None,
145+
data=None,
146+
files=None,
147+
timeout=60.0,
148+
experimental=False,
149+
error_log_key="message",
150+
raise_return_resource_not_found=False,
151+
error_handlers: Optional[Dict[str, Callable[[requests.models.Response],
152+
None]]] = None
153+
) -> Dict[str, Any]:
150154
""" Sends a request to the server for the execution of the
151155
given query.
152156
@@ -160,6 +164,13 @@ def execute(self,
160164
files (dict): file arguments for request
161165
timeout (float): Max allowed time for query execution,
162166
in seconds.
167+
raise_return_resource_not_found: By default the client relies on the caller to raise the correct exception when a resource is not found.
168+
If this is set to True, the client will raise a ResourceNotFoundError exception automatically.
169+
This simplifies processing.
170+
We recommend to use it only of api returns a clear and well-formed error when a resource not found for a given query.
171+
error_handlers (dict): A dictionary mapping graphql error code to handler functions.
172+
Allows a caller to handle specific errors reporting in a custom way or produce more user-friendly readable messages.
173+
163174
Returns:
164175
dict, parsed JSON response.
165176
Raises:
@@ -323,7 +334,12 @@ def get_error_status_code(error: dict) -> int:
323334
# TODO: fix this in the server API
324335
internal_server_error = check_errors(["INTERNAL_SERVER_ERROR"],
325336
"extensions", "code")
337+
error_code = "INTERNAL_SERVER_ERROR"
338+
326339
if internal_server_error is not None:
340+
if error_handlers and error_code in error_handlers:
341+
handler = error_handlers[error_code]
342+
handler(response)
327343
message = internal_server_error.get("message")
328344
error_status_code = get_error_status_code(internal_server_error)
329345
if error_status_code == 400:

libs/labelbox/src/labelbox/exceptions.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ def __init__(self, message, cause=None):
1616
self.cause = cause
1717

1818
def __str__(self):
19-
return self.message + str(self.args)
19+
exception_message = self.message
20+
if self.cause is not None:
21+
exception_message += " (caused by: %s)" % self.cause
22+
return exception_message
2023

2124

2225
class AuthenticationError(LabelboxError):

libs/labelbox/src/labelbox/schema/labeling_service.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from datetime import datetime
22
from enum import Enum
3+
import json
34
from typing import Any
45
from typing_extensions import Annotated
56

6-
from labelbox.exceptions import ResourceNotFoundError
7+
from labelbox.exceptions import LabelboxError, ResourceNotFoundError
78

89
from labelbox.pydantic_compat import BaseModel, Field
910
from labelbox.utils import _CamelCaseMixin
@@ -87,12 +88,29 @@ def request(self) -> 'LabelingService':
8788
}
8889
"""
8990
result = self.client.execute(query_str, {"projectId": self.project_id},
90-
raise_return_resource_not_found=True)
91+
raise_return_resource_not_found=True,
92+
error_handlers={
93+
"INTERNAL_SERVER_ERROR":
94+
self._raise_readable_errors
95+
})
9196
success = result["validateAndRequestProjectBoostWorkforce"]["success"]
9297
if not success:
9398
raise Exception("Failed to start labeling service")
9499
return LabelingService.get(self.client, self.project_id)
95100

101+
def _raise_readable_errors(self, response):
102+
errors = response.json().get('errors', [])
103+
if errors:
104+
message = errors[0].get(
105+
'message', json.dumps([{
106+
"errorMessage": "Unknown error"
107+
}]))
108+
errors = json.loads(message)
109+
error_messages = [error['errorMessage'] for error in errors]
110+
else:
111+
error_messages = ["Uknown error"]
112+
raise LabelboxError(". ".join(error_messages))
113+
96114
@classmethod
97115
def getOrCreate(cls, client, project_id: Cuid) -> 'LabelingService':
98116
"""

libs/labelbox/tests/integration/test_labeling_service.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,8 @@ def test_request_labeling_service_moe_project(
4242
project.upsert_instructions('tests/integration/media/sample_pdf.pdf')
4343

4444
labeling_service = project.get_labeling_service()
45-
with pytest.raises(
46-
LabelboxError,
47-
match=
48-
'[{"errorType":"PROJECT_MODEL_CONFIG","errorMessage":"Project model config is not completed"}]'
49-
):
45+
with pytest.raises(LabelboxError,
46+
match='Project model config is not completed'):
5047
labeling_service.request()
5148
project.add_model_config(model_config.uid)
5249
project.set_project_model_setup_complete()
@@ -64,5 +61,8 @@ def test_request_labeling_service_incomplete_requirements(ontology, project):
6461
): # No labeling service by default
6562
labeling_service.request()
6663
project.connect_ontology(ontology)
67-
with pytest.raises(LabelboxError):
64+
with pytest.raises(
65+
LabelboxError,
66+
match=
67+
"['Data is missing', 'Ontology instructions are not completed']"):
6868
labeling_service.request()

0 commit comments

Comments
 (0)