From 00e6b0efdafa7b1680c8824252db38469ce0c4bd Mon Sep 17 00:00:00 2001 From: TheLunarLogic Date: Mon, 30 Jun 2025 15:37:00 +0530 Subject: [PATCH 1/2] [LABIMP-6908] Add export status checking and download URL fetching functionality --- labellerr/client.py | 104 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/labellerr/client.py b/labellerr/client.py index 0e55ad8..55d00b4 100644 --- a/labellerr/client.py +++ b/labellerr/client.py @@ -827,7 +827,7 @@ def upload_preannotation_by_project_id(self,project_id,client_id,annotation_form raise LabellerrError(f"Failed to upload preannotation: {str(e)}") def create_local_export(self,project_id,client_id,export_config): - + unique_id = str(uuid.uuid4()) required_params = ['export_name', 'export_description', 'export_format','statuses'] if project_id is None: @@ -886,6 +886,108 @@ def create_local_export(self,project_id,client_id,export_config): logging.error(f"Failed to create local export: {str(e)}") raise LabellerrError(f"Failed to create local export: {str(e)}") + + def fetch_download_url(self, api_key, api_secret, project_id, uuid, export_id, client_id): + try: + headers = { + 'api_key': api_key, + 'api_secret': api_secret, + 'client_id': client_id, + 'origin': 'https://dev.labellerr.com', + 'source': 'sdk', + 'Content-Type': 'application/json' + } + + response = requests.get( + url="https://api.labellerr.com/exports/download", + params={ + "client_id": client_id, + "project_id": project_id, + "uuid": uuid, + "report_id": export_id + }, + headers=headers + ) + + if response.ok: + return json.dumps(response.json().get("response"), indent=2) + else: + raise LabellerrError(f" Download request failed: {response.status_code} - {response.text}") + except requests.exceptions.RequestException as e: + logging.error(f"Failed to download export: {str(e)}") + raise LabellerrError(f"Failed to download export: {str(e)}") + except Exception as e: + logging.error(f"Unexpected error in download_function: {str(e)}") + raise LabellerrError(f"Unexpected error in download_function: {str(e)}") + + + + + + def check_export_status(self, api_key, api_secret, project_id, report_ids, client_id): + request_uuid = str(uuid.uuid4()) + try: + if not project_id: + raise LabellerrError("project_id cannot be null") + if not report_ids or not isinstance(report_ids, list): + raise LabellerrError("report_ids must be a non-empty list") + + # Construct URL + url = f"https://api.labellerr.com/exports/status?project_id={project_id}&uuid={request_uuid}&client_id={client_id}" + + # Headers + headers = { + 'client_id': client_id, + 'api_key': api_key, + 'api_secret': api_secret, + 'origin': 'https://dev.labellerr.com', + 'source': 'sdk', + 'Content-Type': 'application/json' + } + + payload = json.dumps({ + "report_ids": report_ids + }) + + response = requests.post(url, headers=headers, data=payload) + + if response.status_code not in [200, 201]: + if 400 <= response.status_code < 500: + raise LabellerrError({'error': response.json(), 'code': response.status_code}) + elif response.status_code >= 500: + raise LabellerrError({ + 'status': 'internal server error', + 'message': 'Please contact support with the request tracking id', + 'request_id': request_uuid + }) + + result = response.json() + + # Now process each report_id + for status_item in result.get("status", []): + if status_item.get("is_completed"): + # Download URL if job completed + download_url = self.fetch_download_url( + api_key=api_key, + api_secret=api_secret, + project_id=project_id, + uuid=request_uuid, + export_id=status_item["report_id"], + client_id=client_id + ) + # Add download URL to response + status_item["response"] = download_url + + return json.dumps(result, indent=2) + + except requests.exceptions.RequestException as e: + logging.error(f"Failed to check export status: {str(e)}") + raise LabellerrError(f"Failed to check export status: {str(e)}") + except Exception as e: + logging.error(f"Unexpected error checking export status: {str(e)}") + raise LabellerrError(f"Unexpected error checking export status: {str(e)}") + + def create_project(self, project_name, data_type, client_id, dataset_id, annotation_template_id, rotation_config, created_by=None): """ Creates a project. From 1ee4a74aace9be4e396ef24d194034b9976a87b5 Mon Sep 17 00:00:00 2001 From: TheLunarLogic Date: Wed, 9 Jul 2025 11:58:03 +0530 Subject: [PATCH 2/2] [LABIMP-6908] Refactor error messages for consistency and update API URLs to use BASE_URL constant . --- labellerr/client.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/labellerr/client.py b/labellerr/client.py index 55d00b4..101c9d6 100644 --- a/labellerr/client.py +++ b/labellerr/client.py @@ -77,7 +77,7 @@ def get_direct_upload_url(self, file_name, client_id, purpose='pre-annotations') tracking_id = str(uuid.uuid4()) logging.exception(f"Error getting direct upload url: {response.text}") raise LabellerrError({ - 'status': 'internal server error', + 'status': 'Internal server error', 'message': 'Please contact support with the request tracking id', 'request_id': tracking_id }) @@ -899,7 +899,7 @@ def fetch_download_url(self, api_key, api_secret, project_id, uuid, export_id, c } response = requests.get( - url="https://api.labellerr.com/exports/download", + url=f"{constants.BASE_URL}/exports/download", params={ "client_id": client_id, "project_id": project_id, @@ -933,7 +933,7 @@ def check_export_status(self, api_key, api_secret, project_id, report_ids, clien raise LabellerrError("report_ids must be a non-empty list") # Construct URL - url = f"https://api.labellerr.com/exports/status?project_id={project_id}&uuid={request_uuid}&client_id={client_id}" + url = f"{constants.BASE_URL}/exports/status?project_id={project_id}&uuid={request_uuid}&client_id={client_id}" # Headers headers = { @@ -956,7 +956,7 @@ def check_export_status(self, api_key, api_secret, project_id, report_ids, clien raise LabellerrError({'error': response.json(), 'code': response.status_code}) elif response.status_code >= 500: raise LabellerrError({ - 'status': 'internal server error', + 'status': 'Internal server error', 'message': 'Please contact support with the request tracking id', 'request_id': request_uuid }) @@ -965,7 +965,7 @@ def check_export_status(self, api_key, api_secret, project_id, report_ids, clien # Now process each report_id for status_item in result.get("status", []): - if status_item.get("is_completed"): + if status_item.get("is_completed") and status_item.get("export_status") == "Created": # Download URL if job completed download_url = self.fetch_download_url( api_key=api_key, @@ -975,8 +975,9 @@ def check_export_status(self, api_key, api_secret, project_id, report_ids, clien export_id=status_item["report_id"], client_id=client_id ) + # Add download URL to response - status_item["response"] = download_url + status_item["url"] = download_url return json.dumps(result, indent=2) @@ -1028,7 +1029,7 @@ def initiate_create_project(self, payload): """ try: - result={} + result = {} # validate all the parameters required_params = ['client_id', 'dataset_name', 'dataset_description', 'data_type', 'created_by', 'project_name','annotation_guide','autolabel'] for param in required_params: @@ -1262,4 +1263,5 @@ def upload_folder_files_to_dataset(self, data_config): except LabellerrError as e: raise e except Exception as e: - raise LabellerrError(f"Failed to upload files: {str(e)}") \ No newline at end of file + raise LabellerrError(f"Failed to upload files: {str(e)}") +