1010from labelbox .orm .model import Field , Relationship , Entity
1111
1212from labelbox .pagination import PaginatedCollection
13- from labelbox .schema .internal .datarow_upload_constants import MAX_DATAROW_PER_API_OPERATION
13+ from labelbox .schema .internal .datarow_upload_constants import (
14+ MAX_DATAROW_PER_API_OPERATION ,
15+ DOWNLOAD_RESULT_PAGE_SIZE ,
16+ )
1417
1518if TYPE_CHECKING :
1619 from labelbox import User
@@ -52,6 +55,10 @@ class Task(DbObject):
5255 created_by = Relationship .ToOne ("User" , False , "created_by" )
5356 organization = Relationship .ToOne ("Organization" )
5457
58+ def __eq__ (self , task ):
59+ return isinstance (
60+ task , Task ) and task .uid == self .uid and task .type == self .type
61+
5562 # Import and upsert have several instances of special casing
5663 def is_creation_task (self ) -> bool :
5764 return self .name == 'JSON Import' or self .type == 'adv-upsert-data-rows'
@@ -227,21 +234,23 @@ def __init__(self, *args, **kwargs):
227234 self ._user = None
228235
229236 @property
230- def result (self ) -> Union [List [Dict [str , Any ]]]:
237+ def result (self ) -> Optional [List [Dict [str , Any ]]]: # type: ignore
231238 if self .status == "FAILED" :
232239 raise ValueError (f"Job failed. Errors : { self .errors } " )
233240 return self ._results_as_list ()
234241
235242 @property
236- def errors (self ) -> Optional [Dict [str , Any ]]:
243+ def errors (self ) -> Optional [List [ Dict [str , Any ]]]: # type: ignore
237244 return self ._errors_as_list ()
238245
239246 @property
240- def created_data_rows (self ) -> Optional [Dict [str , Any ]]:
247+ def created_data_rows ( # type: ignore
248+ self ) -> Optional [List [Dict [str , Any ]]]:
241249 return self .result
242250
243251 @property
244- def failed_data_rows (self ) -> Optional [Dict [str , Any ]]:
252+ def failed_data_rows ( # type: ignore
253+ self ) -> Optional [List [Dict [str , Any ]]]:
245254 return self .errors
246255
247256 @property
@@ -253,7 +262,7 @@ def errors_all(self) -> PaginatedCollection:
253262 return self ._download_errors_paginated ()
254263
255264 def _download_results_paginated (self ) -> PaginatedCollection :
256- page_size = 900 # hardcode to avoid overloading the server
265+ page_size = DOWNLOAD_RESULT_PAGE_SIZE
257266 from_cursor = None
258267
259268 query_str = """query SuccessesfulDataRowImportsPyApi($taskId: ID!, $first: Int, $from: String) {
@@ -292,7 +301,7 @@ def _download_results_paginated(self) -> PaginatedCollection:
292301 )
293302
294303 def _download_errors_paginated (self ) -> PaginatedCollection :
295- page_size = 5000 # hardcode to avoid overloading the server
304+ page_size = DOWNLOAD_RESULT_PAGE_SIZE # hardcode to avoid overloading the server
296305 from_cursor = None
297306
298307 query_str = """query FailedDataRowImportsPyApi($taskId: ID!, $first: Int, $from: String) {
@@ -306,6 +315,16 @@ def _download_errors_paginated(self) -> PaginatedCollection:
306315 externalId
307316 globalKey
308317 rowData
318+ metadata {
319+ schemaId
320+ value
321+ name
322+ }
323+ attachments {
324+ type
325+ value
326+ name
327+ }
309328 }
310329 }
311330 }
@@ -318,28 +337,30 @@ def _download_errors_paginated(self) -> PaginatedCollection:
318337 'from' : from_cursor ,
319338 }
320339
340+ def convert_errors_to_legacy_format (client , data_row ):
341+ spec = data_row .get ('spec' , {})
342+ return {
343+ 'message' :
344+ data_row .get ('message' ),
345+ 'failedDataRows' : [{
346+ 'externalId' : spec .get ('externalId' ),
347+ 'rowData' : spec .get ('rowData' ),
348+ 'globalKey' : spec .get ('globalKey' ),
349+ 'metadata' : spec .get ('metadata' , []),
350+ 'attachments' : spec .get ('attachments' , []),
351+ }]
352+ }
353+
321354 return PaginatedCollection (
322355 client = self .client ,
323356 query = query_str ,
324357 params = params ,
325358 dereferencing = ['failedDataRowImports' , 'results' ],
326- obj_class = lambda _ , data_row : {
327- 'error' :
328- data_row .get ('message' ),
329- 'external_id' :
330- data_row .get ('spec' ).get ('externalId' )
331- if data_row .get ('spec' ) else None ,
332- 'row_data' :
333- data_row .get ('spec' ).get ('rowData' )
334- if data_row .get ('spec' ) else None ,
335- 'global_key' :
336- data_row .get ('spec' ).get ('globalKey' )
337- if data_row .get ('spec' ) else None ,
338- },
359+ obj_class = convert_errors_to_legacy_format ,
339360 cursor_path = ['failedDataRowImports' , 'after' ],
340361 )
341362
342- def _results_as_list (self ) -> List [Dict [str , Any ]]:
363+ def _results_as_list (self ) -> Optional [ List [Dict [str , Any ] ]]:
343364 total_downloaded = 0
344365 results = []
345366 data = self ._download_results_paginated ()
@@ -350,9 +371,12 @@ def _results_as_list(self) -> List[Dict[str, Any]]:
350371 if total_downloaded >= self .__max_donwload_size :
351372 break
352373
374+ if len (results ) == 0 :
375+ return None
376+
353377 return results
354378
355- def _errors_as_list (self ) -> List [Dict [str , Any ]]:
379+ def _errors_as_list (self ) -> Optional [ List [Dict [str , Any ] ]]:
356380 total_downloaded = 0
357381 errors = []
358382 data = self ._download_errors_paginated ()
@@ -363,4 +387,7 @@ def _errors_as_list(self) -> List[Dict[str, Any]]:
363387 if total_downloaded >= self .__max_donwload_size :
364388 break
365389
390+ if len (errors ) == 0 :
391+ return None
392+
366393 return errors
0 commit comments