diff --git a/qiita_db/support_files/patches/python_patches/58.py b/qiita_db/support_files/patches/python_patches/58.py index 86015bd35..5e1a21f5d 100644 --- a/qiita_db/support_files/patches/python_patches/58.py +++ b/qiita_db/support_files/patches/python_patches/58.py @@ -17,3 +17,9 @@ parameters = {'artifact': ['artifact:["Demultiplexed"]', None]} Command.create(qiita_plugin, "submit_to_VAMPS", "submits an artifact to VAMPS", parameters) + + # Create the copy artifact command + parameters = {'artifact': ['artifact:["Demultiplexed"]', None], + 'prep_template': ['prep_template', None]} + Command.create(qiita_plugin, "copy_artifact", + "Creates a copy of an artifact", parameters) diff --git a/qiita_pet/handlers/api_proxy/artifact.py b/qiita_pet/handlers/api_proxy/artifact.py index 9c0be2945..af8d2e8db 100644 --- a/qiita_pet/handlers/api_proxy/artifact.py +++ b/qiita_pet/handlers/api_proxy/artifact.py @@ -15,14 +15,12 @@ from qiita_core.util import execute_as_transaction from qiita_core.qiita_settings import qiita_config, r_client from qiita_pet.handlers.api_proxy.util import check_access, check_fp -from qiita_ware.context import safe_submit -from qiita_ware.dispatchable import copy_raw_data from qiita_db.artifact import Artifact from qiita_db.user import User from qiita_db.metadata_template.prep_template import PrepTemplate from qiita_db.util import ( get_mountpoint, get_visibilities, get_artifacts_information) -from qiita_db.software import Command, Parameters +from qiita_db.software import Command, Parameters, Software from qiita_db.processing_job import ProcessingJob PREP_TEMPLATE_KEY_FORMAT = 'prep_template_%s' @@ -174,10 +172,15 @@ def artifact_post_req(user_id, filepaths, artifact_type, name, if access_error: return access_error + user = User(user_id) + if artifact_id: # if the artifact id has been provided, import the artifact - job_id = safe_submit(user_id, copy_raw_data, prep, artifact_id) - is_qiita_job = False + qiita_plugin = Software.from_name_and_version('Qiita', 'alpha') + cmd = qiita_plugin.get_command('copy_artifact') + params = Parameters.load(cmd, values_dict={'artifact': artifact_id, + 'prep_template': prep.id}) + job = ProcessingJob.create(user, params) else: uploads_path = get_mountpoint('uploads')[0][1] path_builder = partial(join, uploads_path, str(study_id)) @@ -210,18 +213,18 @@ def artifact_post_req(user_id, filepaths, artifact_type, name, command = Command.get_validator(artifact_type) job = ProcessingJob.create( - User(user_id), + user, Parameters.load(command, values_dict={ 'template': prep_template_id, 'files': dumps(cleaned_filepaths), 'artifact_type': artifact_type })) - job.submit() - job_id = job.id - is_qiita_job = True + + # Submit the job + job.submit() r_client.set(PREP_TEMPLATE_KEY_FORMAT % prep.id, - dumps({'job_id': job_id, 'is_qiita_job': is_qiita_job})) + dumps({'job_id': job.id, 'is_qiita_job': True})) return {'status': 'success', 'message': ''} diff --git a/qiita_ware/dispatchable.py b/qiita_ware/dispatchable.py index 52e94f1bf..e06592a86 100644 --- a/qiita_ware/dispatchable.py +++ b/qiita_ware/dispatchable.py @@ -13,39 +13,6 @@ def submit_to_ebi(preprocessed_data_id, submission_type): submit_EBI(preprocessed_data_id, submission_type, True) -def copy_raw_data(prep_template, artifact_id): - """Creates a new raw data by copying from artifact_id - - Parameters - ---------- - prep_template : qiita_db.metadata_template.prep_template.PrepTemplate - The template to attach the artifact - artifact_id : int - The id of the artifact to duplicate - - Returns - ------- - dict of {str: str} - A dict of the form {'status': str, 'message': str} - """ - from qiita_db.artifact import Artifact - - status = 'success' - msg = '' - - try: - Artifact.copy(Artifact(artifact_id), prep_template) - except Exception as e: - # We should hit this exception rarely (that's why it is an - # exception) since at this point we have done multiple checks. - # However, it can occur in weird cases, so better let the GUI know - # that this failed - return {'status': 'danger', - 'message': "Error creating artifact: %s" % str(e)} - - return {'status': status, 'message': msg} - - def delete_artifact(artifact_id): """Deletes an artifact from the system diff --git a/qiita_ware/private_plugin.py b/qiita_ware/private_plugin.py index 8b3abbf56..8aaff0fb2 100644 --- a/qiita_ware/private_plugin.py +++ b/qiita_ware/private_plugin.py @@ -77,11 +77,30 @@ def submit_to_VAMPS(job): """ with qdb.sql_connection.TRN: submit_VAMPS(job.parameters.values['artifact']) + job._set_status('success') + + +def copy_artifact(job): + """Creates a copy of an artifact + + Parameters + ---------- + job : qiita_db.processing_job.ProcessingJob + The processing job performing the task + """ + with qdb.sql_connection.TRN: + param_vals = job.parameters.values + orig_artifact = qdb.artifact.Artifact(param_vals['artifact']) + prep_template = qdb.metadata_template.prep_template.PrepTemplate( + param_vals['prep_template']) + qdb.artifact.Artifact.copy(orig_artifact, prep_template) + job._set_status('success') TASK_DICT = {'build_analysis_files': build_analysis_files, 'release_validators': release_validators, - 'submit_to_VAMPS': submit_to_VAMPS} + 'submit_to_VAMPS': submit_to_VAMPS, + 'copy_artifact': copy_artifact} def private_task(job_id): diff --git a/qiita_ware/test/test_dispatchable.py b/qiita_ware/test/test_dispatchable.py index 67557010e..4ff7318bc 100644 --- a/qiita_ware/test/test_dispatchable.py +++ b/qiita_ware/test/test_dispatchable.py @@ -17,8 +17,7 @@ from qiita_core.util import qiita_test_checker from qiita_ware.dispatchable import ( create_sample_template, update_sample_template, delete_sample_template, - update_prep_template, delete_artifact, copy_raw_data, - delete_sample_or_column) + update_prep_template, delete_artifact, delete_sample_or_column) from qiita_db.study import Study from qiita_db.artifact import Artifact from qiita_db.exceptions import QiitaDBUnknownIDError, QiitaDBWarning @@ -42,13 +41,6 @@ def tearDown(self): if exists(fp): remove(fp) - def test_copy_raw_data(self): - obs = copy_raw_data(PrepTemplate(1), 1) - exp = {'status': 'danger', - 'message': "Error creating artifact: Prep template 1 already " - "has an artifact associated"} - self.assertEqual(obs, exp) - def test_delete_artifact(self): obs = delete_artifact(1) exp = {'status': 'danger', diff --git a/qiita_ware/test/test_private_plugin.py b/qiita_ware/test/test_private_plugin.py new file mode 100644 index 000000000..fc26c5983 --- /dev/null +++ b/qiita_ware/test/test_private_plugin.py @@ -0,0 +1,63 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2014--, The Qiita Development Team. +# +# Distributed under the terms of the BSD 3-clause License. +# +# The full license is in the file LICENSE, distributed with this software. +# ----------------------------------------------------------------------------- + +from unittest import TestCase, main + +import pandas as pd + +from qiita_core.util import qiita_test_checker +from qiita_db.software import Software, Parameters +from qiita_db.processing_job import ProcessingJob +from qiita_db.user import User +from qiita_db.study import Study +from qiita_db.metadata_template.prep_template import PrepTemplate +from qiita_ware.private_plugin import private_task + + +@qiita_test_checker() +class TestPrivatePlugin(TestCase): + def _create_job(self, cmd, values_dict): + user = User('test@foo.bar') + qiita_plugin = Software.from_name_and_version('Qiita', 'alpha') + cmd = qiita_plugin.get_command('copy_artifact') + params = Parameters.load(cmd, values_dict=values_dict) + job = ProcessingJob.create(user, params) + job._set_status('queued') + return job + + def test_copy_artifact(self): + # Failure test + job = self._create_job('copy_artifact', + {'artifact': 1, 'prep_template': 1}) + + private_task(job.id) + self.assertEqual(job.status, 'error') + self.assertIn("Prep template 1 already has an artifact associated", + job.log.msg) + + # Success test + metadata_dict = { + 'SKB8.640193': {'center_name': 'ANL', + 'primer': 'GTGCCAGCMGCCGCGGTAA', + 'barcode': 'GTCCGCAAGTTA', + 'run_prefix': "s_G1_L001_sequences", + 'platform': 'ILLUMINA', + 'instrument_model': 'Illumina MiSeq', + 'library_construction_protocol': 'AAAA', + 'experiment_design_description': 'BBBB'}} + metadata = pd.DataFrame.from_dict(metadata_dict, orient='index', + dtype=str) + prep = PrepTemplate.create(metadata, Study(1), "16S") + job = self._create_job('copy_artifact', {'artifact': 1, + 'prep_template': prep.id}) + private_task(job.id) + self.assertEqual(job.status, 'success') + + +if __name__ == '__main__': + main()