@@ -1229,6 +1229,102 @@ def _format_failed_rows(rows: List[str],
12291229 )
12301230 time .sleep (sleep_time )
12311231
1232+ def clear_global_keys (
1233+ self ,
1234+ global_keys : List [str ],
1235+ timeout_seconds = 60 ) -> Dict [str , Union [str , List [Any ]]]:
1236+ """
1237+ Clears global keys for the data rows tha correspond to the global keys provided.
1238+
1239+ Args:
1240+ A list of global keys
1241+ Returns:
1242+ Dictionary containing 'status', 'results' and 'errors'.
1243+
1244+ 'Status' contains the outcome of this job. It can be one of
1245+ 'Success', 'Partial Success', or 'Failure'.
1246+
1247+ 'Results' contains a list global keys that were successfully cleared.
1248+
1249+ 'Errors' contains a list of global_keys correspond to the data rows that could not be
1250+ modified, accessed by the user, or not found.
1251+ Examples:
1252+ >>> job_result = client.get_data_row_ids_for_global_keys(["key1","key2"])
1253+ >>> print(job_result['status'])
1254+ Partial Success
1255+ >>> print(job_result['results'])
1256+ ['cl7tv9wry00hlka6gai588ozv', 'cl7tv9wxg00hpka6gf8sh81bj']
1257+ >>> print(job_result['errors'])
1258+ [{'global_key': 'asdf', 'error': 'Data Row not found'}]
1259+ """
1260+
1261+ def _format_failed_rows (rows : List [str ],
1262+ error_msg : str ) -> List [Dict [str , str ]]:
1263+ return [{'global_key' : r , 'error' : error_msg } for r in rows ]
1264+
1265+ # Start get data rows for global keys job
1266+ query_str = """mutation clearGlobalKeysPyApi($globalKeys: [ID!]!) {
1267+ clearGlobalKeys(where: {ids: $globalKeys}) { jobId}}
1268+ """
1269+ params = {"globalKeys" : global_keys }
1270+ clear_global_keys_job = self .execute (query_str , params )
1271+
1272+ # Query string for retrieving job status and result, if job is done
1273+ result_query_str = """query clearGlobalKeysResultPyApi($jobId: ID!) {
1274+ clearGlobalKeysResult(jobId: {id: $jobId}) { data {
1275+ clearedGlobalKeys
1276+ failedToClearGlobalKeys
1277+ notFoundGlobalKeys
1278+ accessDeniedGlobalKeys
1279+ } jobStatus}}
1280+ """
1281+ result_params = {
1282+ "jobId" : clear_global_keys_job ["clearGlobalKeys" ]["jobId" ]
1283+ }
1284+ # Poll job status until finished, then retrieve results
1285+ sleep_time = 2
1286+ start_time = time .time ()
1287+ while True :
1288+ res = self .execute (result_query_str , result_params )
1289+ if res ["clearGlobalKeysResult" ]['jobStatus' ] == "COMPLETE" :
1290+ data = res ["clearGlobalKeysResult" ]['data' ]
1291+ results , errors = [], []
1292+ results .extend (data ['clearedGlobalKeys' ])
1293+ errors .extend (
1294+ _format_failed_rows (data ['failedToClearGlobalKeys' ],
1295+ "Clearing global key failed" ))
1296+ errors .extend (
1297+ _format_failed_rows (
1298+ data ['notFoundGlobalKeys' ],
1299+ "Failed to find data row matching provided global key" ))
1300+ errors .extend (
1301+ _format_failed_rows (
1302+ data ['accessDeniedGlobalKeys' ],
1303+ "Denied access to modify data row matching provided global key"
1304+ ))
1305+
1306+ if not errors :
1307+ status = CollectionJobStatus .SUCCESS .value
1308+ elif errors and len (results ) > 0 :
1309+ status = CollectionJobStatus .PARTIAL_SUCCESS .value
1310+ else :
1311+ status = CollectionJobStatus .FAILURE .value
1312+
1313+ if errors :
1314+ logger .warning (
1315+ "There are errors present. Please look at 'errors' in the returned dict for more details"
1316+ )
1317+
1318+ return {"status" : status , "results" : results , "errors" : errors }
1319+ elif res ["clearGlobalKeysResult" ]['jobStatus' ] == "FAILED" :
1320+ raise labelbox .exceptions .LabelboxError (
1321+ "Job clearGlobalKeys failed." )
1322+ current_time = time .time ()
1323+ if current_time - start_time > timeout_seconds :
1324+ raise labelbox .exceptions .TimeoutError (
1325+ "Timed out waiting for clear_global_keys job to complete." )
1326+ time .sleep (sleep_time )
1327+
12321328 def get_catalog_slice (self , slice_id ) -> CatalogSlice :
12331329 """
12341330 Fetches a Catalog Slice by ID.
0 commit comments