11import logging
2+ import json
23import requests
34import time
4- from typing import TYPE_CHECKING , Optional
5+ from typing import TYPE_CHECKING , TypeVar , Callable , Optional , Dict , Any , List
56
67from labelbox .exceptions import ResourceNotFoundError
78from labelbox .orm .db_object import DbObject
1011if TYPE_CHECKING :
1112 from labelbox import User
1213
14+ def lru_cache () -> Callable [..., Callable [..., Dict [str , Any ]]]:
15+ pass
16+ else :
17+ from functools import lru_cache
18+
1319logger = logging .getLogger (__name__ )
1420
1521
@@ -32,7 +38,7 @@ class Task(DbObject):
3238 name = Field .String ("name" )
3339 status = Field .String ("status" )
3440 completion_percentage = Field .Float ("completion_percentage" )
35- result = Field .String ("result" )
41+ result_url = Field .String ("result_url" , "result" )
3642 _user : Optional ["User" ] = None
3743
3844 # Relationships
@@ -68,12 +74,44 @@ def wait_till_done(self, timeout_seconds=300) -> None:
6874 time .sleep (sleep_time_seconds )
6975 self .refresh ()
7076
71- def errors (self ):
77+ @property
78+ def errors (self ) -> Optional [Dict [str , Any ]]:
7279 """ Downloads the result file from Task
7380 """
74- if self .status == "FAILED" and self .result :
75- response = requests .get (self .result )
76- response .raise_for_status ()
77- data = response .json ()
78- return data .get ('error' )
81+ if self .status == "FAILED" :
82+ result = self ._fetch_remote_json ()
83+ return result ['error' ]
7984 return None
85+
86+ @property
87+ def result (self ) -> List [Dict [str , Any ]]:
88+ """ Fetch the result for a task
89+ """
90+ if self .status == "FAILED" :
91+ raise ValueError (f"Job failed. Errors : { self .errors } " )
92+ else :
93+ result = self ._fetch_remote_json ()
94+ return [{
95+ 'id' : data_row ['id' ],
96+ 'external_id' : data_row .get ('externalId' ),
97+ 'row_data' : data_row ['rowData' ]
98+ } for data_row in result ['createdDataRows' ]]
99+
100+ @lru_cache ()
101+ def _fetch_remote_json (self ) -> Dict [str , Any ]:
102+ """ Function for fetching and caching the result data.
103+ """
104+ if self .name != 'JSON Import' :
105+ raise ValueError (
106+ "Task result is only supported for `JSON Import` tasks."
107+ " Download task.result_url manually to access the result for other tasks."
108+ )
109+ self .wait_till_done (timeout_seconds = 600 )
110+ if self .status == "IN_PROGRESS" :
111+ raise ValueError (
112+ "Job status still in `IN_PROGRESS`. The result is not available. Call task.wait_till_done() with a larger timeout or contact support."
113+ )
114+
115+ response = requests .get (self .result_url )
116+ response .raise_for_status ()
117+ return response .json ()
0 commit comments