(self, request, project, preannotated_from_fields, commit_to_project, return_task_ids)
| 281 | return task_instances, serializer |
| 282 | |
| 283 | def sync_import(self, request, project, preannotated_from_fields, commit_to_project, return_task_ids): |
| 284 | start = time.time() |
| 285 | tasks = None |
| 286 | # upload files from request, and parse all tasks |
| 287 | # TODO: Stop passing request to load_tasks function, make all validation before |
| 288 | parsed_data, file_upload_ids, could_be_tasks_list, found_formats, data_columns = load_tasks(request, project) |
| 289 | |
| 290 | if preannotated_from_fields: |
| 291 | # turn flat task JSONs {"column1": value, "column2": value} into {"data": {"column1"..}, "predictions": [{..."column2"}] |
| 292 | raise_errors = flag_set('fflag_feat_utc_210_prediction_validation_15082025', user='auto') |
| 293 | logger.info(f'Reformatting predictions with raise_errors: {raise_errors}') |
| 294 | parsed_data = reformat_predictions(parsed_data, preannotated_from_fields, project, raise_errors) |
| 295 | |
| 296 | # Conditionally validate predictions: skip when label config is default during project creation |
| 297 | if project.label_config_is_not_default: |
| 298 | validation_errors = [] |
| 299 | li = LabelInterface(project.label_config) |
| 300 | |
| 301 | for i, task in enumerate(parsed_data): |
| 302 | if 'predictions' in task: |
| 303 | for j, prediction in enumerate(task['predictions']): |
| 304 | try: |
| 305 | validation_errors_list = li.validate_prediction(prediction, return_errors=True) |
| 306 | if validation_errors_list: |
| 307 | for error in validation_errors_list: |
| 308 | validation_errors.append(f'Task {i}, prediction {j}: {error}') |
| 309 | except Exception as e: |
| 310 | error_msg = f'Task {i}, prediction {j}: Error validating prediction - {extract_message(e)}' |
| 311 | validation_errors.append(error_msg) |
| 312 | |
| 313 | if validation_errors: |
| 314 | error_message = f'Prediction validation failed ({len(validation_errors)} errors):\n' |
| 315 | for error in validation_errors: |
| 316 | error_message += f'- {error}\n' |
| 317 | |
| 318 | if flag_set('fflag_feat_utc_210_prediction_validation_15082025', user='auto'): |
| 319 | raise ValidationError({'predictions': [error_message]}) |
| 320 | else: |
| 321 | logger.error( |
| 322 | f'Prediction validation failed, not raising error - ({len(validation_errors)} errors):\n{error_message}' |
| 323 | ) |
| 324 | |
| 325 | if commit_to_project: |
| 326 | # Immediately create project tasks and update project states and counters |
| 327 | tasks, serializer = self._save(parsed_data) |
| 328 | task_count = len(tasks) |
| 329 | annotation_count = len(serializer.db_annotations) |
| 330 | prediction_count = len(serializer.db_predictions) |
| 331 | |
| 332 | recalculate_stats_counts = { |
| 333 | 'task_count': task_count, |
| 334 | 'annotation_count': annotation_count, |
| 335 | 'prediction_count': prediction_count, |
| 336 | } |
| 337 | |
| 338 | # Update counters (like total_annotations) for new tasks and after bulk update tasks stats. It should be a |
| 339 | # single operation as counters affect bulk is_labeled update |
| 340 | project.update_tasks_counters_and_task_states( |
no test coverage detected