def _copy_input_files(self, writer): for file in self._input_files: dest_file = "/tmp/submission-src" put_file(container=writer, src=file, dest=dest_file) if hasattr(file, "content_type"): mimetype = file.content_type else: with file.open("rb") as f: mimetype = get_file_mimetype(f) if mimetype.lower() == "application/zip": # Unzip the file in the container rather than in the python # process. With resource limits this should provide some # protection against zip bombs etc. writer.exec_run( f"unzip {dest_file} -d /input/ -x '__MACOSX/*'") # Remove a duplicated directory input_files = (writer.exec_run( "ls -1 /input/").output.decode().splitlines()) if (len(input_files) == 1 and not writer.exec_run( f"ls -d /input/{input_files[0]}/").exit_code): writer.exec_run( f'/bin/sh -c "mv /input/{input_files[0]}/* /input/ ' f'&& rm -r /input/{input_files[0]}/"') elif mimetype.lower() == "application/json": writer.exec_run(f"mv {dest_file} /input/predictions.json") else: # Not a zip file, so must be a csv writer.exec_run(f"mv {dest_file} /input/submission.csv")
def create_evaluation(self): method = self.latest_ready_method if not method: # TODO Email admins return e = Evaluation.objects.create(submission=self, method=self.latest_ready_method) mimetype = get_file_mimetype(self.file) if mimetype == "application/zip": interface = ComponentInterface.objects.get( slug="predictions-zip-file") elif mimetype == "text/plain": interface = ComponentInterface.objects.get( slug="predictions-csv-file") else: raise NotImplementedError( f"Interface is not defined for {mimetype} files") e.inputs.set([ ComponentInterfaceValue.objects.create(interface=interface, file=self.file) ]) e.schedule_job()
def create_evaluation(self): method = self.latest_ready_method if not method: send_missing_method_email(self) return evaluation = Evaluation.objects.create(submission=self, method=method) if self.algorithm_image: on_commit(lambda: create_algorithm_jobs_for_evaluation.apply_async( kwargs={"evaluation_pk": evaluation.pk})) else: mimetype = get_file_mimetype(self.predictions_file) if mimetype == "application/zip": interface = ComponentInterface.objects.get( slug="predictions-zip-file") elif mimetype == "text/plain": interface = ComponentInterface.objects.get( slug="predictions-csv-file") else: evaluation.update_status( status=Evaluation.FAILURE, stderr=f"{mimetype} files are not supported.", error_message=f"{mimetype} files are not supported.", ) return evaluation.inputs.set([ ComponentInterfaceValue.objects.create( interface=interface, file=self.predictions_file) ]) on_commit(evaluation.signature.apply_async)
def create_evaluation(self): method = self.latest_ready_method if not method: # TODO Email admins return evaluation = Evaluation.objects.create(submission=self, method=method) if self.algorithm_image: create_algorithm_jobs_for_evaluation.apply_async( kwargs={"evaluation_pk": evaluation.pk}) else: mimetype = get_file_mimetype(self.predictions_file) if mimetype == "application/zip": interface = ComponentInterface.objects.get( slug="predictions-zip-file") elif mimetype == "text/plain": interface = ComponentInterface.objects.get( slug="predictions-csv-file") else: raise NotImplementedError( f"Interface is not defined for {mimetype} files") evaluation.inputs.set([ ComponentInterfaceValue.objects.create( interface=interface, file=self.predictions_file) ]) evaluation.signature.apply_async()
def create_evaluation(self): method = self.latest_ready_method if not method: # TODO Email admins return evaluation = Evaluation.objects.create(submission=self, method=method) if self.algorithm_image: default_input_interface = ComponentInterface.objects.get( slug=DEFAULT_INPUT_INTERFACE_SLUG) jobs = [] for image in self.phase.archive.images.all(): if not ComponentInterfaceValue.objects.filter( interface=default_input_interface, image=image, evaluation_algorithmevaluations_as_input__submission= self, ).exists(): j = AlgorithmEvaluation.objects.create(submission=self) j.inputs.set([ ComponentInterfaceValue.objects.create( interface=default_input_interface, image=image) ]) jobs.append(j.signature) if jobs: (group(*jobs) | set_evaluation_inputs.signature( kwargs={"evaluation_pk": evaluation.pk}, immutable=True, )).apply_async() else: mimetype = get_file_mimetype(self.predictions_file) if mimetype == "application/zip": interface = ComponentInterface.objects.get( slug="predictions-zip-file") elif mimetype == "text/plain": interface = ComponentInterface.objects.get( slug="predictions-csv-file") else: raise NotImplementedError( f"Interface is not defined for {mimetype} files") evaluation.inputs.set([ ComponentInterfaceValue.objects.create( interface=interface, file=self.predictions_file) ]) evaluation.signature.apply_async()
def _copy_input_files(self, writer): for file in self._input_files: dest_file = '/tmp/submission-src' put_file(container=writer, src=file, dest=dest_file) with file.open('rb') as f: mimetype = get_file_mimetype(f) if mimetype.lower() == 'application/zip': # Unzip the file in the container rather than in the python # process. With resource limits this should provide some # protection against zip bombs etc. writer.exec_run(f'unzip {dest_file} -d /input/') else: # Not a zip file, so must be a csv writer.exec_run(f'mv {dest_file} /input/submission.csv')
def _copy_input_files(self, writer): for file in self._input_files: dest_file = "/tmp/submission-src" put_file(container=writer, src=file, dest=dest_file) with file.open("rb") as f: mimetype = get_file_mimetype(f) if mimetype.lower() == "application/zip": # Unzip the file in the container rather than in the python # process. With resource limits this should provide some # protection against zip bombs etc. writer.exec_run( f"unzip {dest_file} -d /input/ -x '__MACOSX/*'") self.__was_unzipped = True else: # Not a zip file, so must be a csv writer.exec_run(f"mv {dest_file} /input/submission.csv")
def _copy_input_files(self, writer): for file in self._input_files: dest_file = "/tmp/submission-src" put_file(container=writer, src=file, dest=dest_file) with file.open("rb") as f: mimetype = get_file_mimetype(f) if mimetype.lower() == "application/zip": # Unzip the file in the container rather than in the python # process. With resource limits this should provide some # protection against zip bombs etc. writer.exec_run( f"unzip {dest_file} -d /input/ -x '__MACOSX/*'" ) self.__was_unzipped = True else: # Not a zip file, so must be a csv writer.exec_run(f"mv {dest_file} /input/submission.csv")
def _copy_input_files(self, writer): for file in self._input_files: dest_file = "/tmp/submission-src" put_file(container=writer, src=file, dest=dest_file) with file.open("rb") as f: mimetype = get_file_mimetype(f) if mimetype.lower() == "application/zip": # Unzip the file in the container rather than in the python # process. With resource limits this should provide some # protection against zip bombs etc. writer.exec_run( f"unzip {dest_file} -d /input/ -x '__MACOSX/*'" ) # Remove a duplicated directory input_files = ( writer.exec_run(f"ls -1 /input/") .output.decode() .splitlines() ) if ( len(input_files) == 1 and not writer.exec_run( f"ls -d /input/{input_files[0]}/" ).exit_code ): writer.exec_run( f'/bin/sh -c "mv /input/{input_files[0]}/* /input/ ' f'&& rm -r /input/{input_files[0]}/"' ) else: # Not a zip file, so must be a csv writer.exec_run(f"mv {dest_file} /input/submission.csv")
def create_evaluation(*, submission_pk, max_initial_jobs=1): """ Creates an Evaluation for a Submission Parameters ---------- submission_pk The primary key of the Submission max_initial_jobs The maximum number of algorithm jobs to schedule first """ Submission = apps.get_model( # noqa: N806 app_label="evaluation", model_name="Submission") Evaluation = apps.get_model( # noqa: N806 app_label="evaluation", model_name="Evaluation") submission = Submission.objects.get(pk=submission_pk) if not submission.predictions_file and submission.user_upload: with transaction.atomic(): submission.user_upload.copy_object( to_field=submission.predictions_file) submission.user_upload.delete() # TODO - move this to the form and make it an input here method = submission.latest_ready_method if not method: logger.info("No method ready for this submission") Notification.send( type=NotificationType.NotificationTypeChoices.MISSING_METHOD, message="missing method", actor=submission.creator, action_object=submission, target=submission.phase, ) return evaluation, created = Evaluation.objects.get_or_create( submission=submission, method=method) if not created: logger.info("Evaluation already created for this submission") return if submission.algorithm_image: on_commit(lambda: create_algorithm_jobs_for_evaluation.apply_async( kwargs={ "evaluation_pk": evaluation.pk, "max_jobs": max_initial_jobs, })) elif submission.predictions_file: mimetype = get_file_mimetype(submission.predictions_file) if mimetype == "application/zip": interface = ComponentInterface.objects.get( slug="predictions-zip-file") elif mimetype in ["text/plain", "application/csv"]: interface = ComponentInterface.objects.get( slug="predictions-csv-file") else: evaluation.update_status( status=Evaluation.FAILURE, stderr=f"{mimetype} files are not supported.", error_message=f"{mimetype} files are not supported.", ) return civ = ComponentInterfaceValue(interface=interface, file=submission.predictions_file) civ.full_clean() civ.save() evaluation.inputs.set([civ]) on_commit(evaluation.execute) else: raise RuntimeError("No algorithm or predictions file found")