def test_check_fp(self): obs = check_fp(1, 'uploaded_file.txt') _, base_fp = get_mountpoint("uploads")[0] exp = {'status': 'success', 'message': '', 'file': join(base_fp, '1', 'uploaded_file.txt')} self.assertEqual(obs, exp)
def test_check_fp_bad_fp(self): obs = check_fp(1, 'badfile') exp = { 'status': 'error', 'message': 'file does not exist', 'file': 'badfile' } self.assertEqual(obs, exp)
def sample_template_post_req(study_id, user_id, data_type, sample_template): """Creates the sample template from the given file Parameters ---------- study_id : int The current study object id user_id : str The current user object id data_type : str Data type for the sample template sample_template : str filename to use for creation Returns ------- dict results dictonary in the format {'status': status, 'message': msg, 'file': sample_template} status can be success, warning, or error depending on result message has the warnings or errors file has the file name """ access_error = check_access(int(study_id), user_id) if access_error: return access_error fp_rsp = check_fp(study_id, sample_template) if fp_rsp['status'] != 'success': # Unknown filepath, so return the error message return fp_rsp fp_rsp = fp_rsp['file'] # Define here the message and message level in case of success msg = '' status = 'success' is_mapping_file = looks_like_qiime_mapping_file(fp_rsp) if is_mapping_file and not data_type: return {'status': 'error', 'message': 'Please, choose a data type if uploading a ' 'QIIME mapping file', 'file': sample_template} study = Study(int(study_id)) # Offload the creation of the sample template to the cluster job_id = safe_submit(user_id, create_sample_template, fp_rsp, study, is_mapping_file, data_type) # Store the job id attaching it to the sample template id r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study.id, dumps({'job_id': job_id})) return {'status': status, 'message': msg, 'file': sample_template}
def test_check_fp(self): obs = check_fp(1, 'uploaded_file.txt') _, base_fp = get_mountpoint("uploads")[0] exp = { 'status': 'success', 'message': '', 'file': join(base_fp, '1', 'uploaded_file.txt') } self.assertEqual(obs, exp)
def sample_template_post_req(study_id, user_id, data_type, sample_template): """Creates the sample template from the given file Parameters ---------- study_id : int The current study object id user_id : str The current user object id data_type : str Data type for the sample template sample_template : str filename to use for creation Returns ------- dict results dictonary in the format {'status': status, 'message': msg, 'file': sample_template} status can be success, warning, or error depending on result message has the warnings or errors file has the file name """ access_error = check_access(int(study_id), user_id) if access_error: return access_error fp_rsp = check_fp(study_id, sample_template) if fp_rsp['status'] != 'success': # Unknown filepath, so return the error message return fp_rsp fp_rsp = fp_rsp['file'] # Define here the message and message level in case of success msg = '' status = 'success' is_mapping_file = looks_like_qiime_mapping_file(fp_rsp) if is_mapping_file and not data_type: return { 'status': 'error', 'message': 'Please, choose a data type if uploading a ' 'QIIME mapping file', 'file': sample_template } study = Study(int(study_id)) # Offload the creation of the sample template to the cluster job_id = safe_submit(user_id, create_sample_template, fp_rsp, study, is_mapping_file, data_type) # Store the job id attaching it to the sample template id r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study.id, dumps({'job_id': job_id})) return {'status': status, 'message': msg, 'file': sample_template}
def sample_template_put_req(study_id, user_id, sample_template): """Updates a sample template using the given file Parameters ---------- study_id : int The current study object id user_id : str The current user object id sample_template : str filename to use for updating Returns ------- dict results dictonary in the format {'status': status, 'message': msg, 'file': sample_template} status can be success, warning, or error depending on result message has the warnings or errors file has the file name """ exists = _check_sample_template_exists(int(study_id)) if exists['status'] != 'success': return exists access_error = check_access(int(study_id), user_id) if access_error: return access_error fp_rsp = check_fp(study_id, sample_template) if fp_rsp['status'] != 'success': # Unknown filepath, so return the error message return fp_rsp fp_rsp = fp_rsp['file'] msg = '' status = 'success' # Offload the update of the sample template to the cluster qiita_plugin = Software.from_name_and_version('Qiita', 'alpha') cmd = qiita_plugin.get_command('update_sample_template') params = Parameters.load(cmd, values_dict={ 'study': int(study_id), 'template_fp': fp_rsp }) job = ProcessingJob.create(User(user_id), params) # Store the job id attaching it to the sample template id r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study_id, dumps({'job_id': job.id})) job.submit() return {'status': status, 'message': msg, 'file': sample_template}
def sample_template_put_req(study_id, user_id, sample_template): """Updates a sample template using the given file Parameters ---------- study_id : int The current study object id user_id : str The current user object id sample_template : str filename to use for updating Returns ------- dict results dictonary in the format {'status': status, 'message': msg, 'file': sample_template} status can be success, warning, or error depending on result message has the warnings or errors file has the file name """ exists = _check_sample_template_exists(int(study_id)) if exists['status'] != 'success': return exists access_error = check_access(int(study_id), user_id) if access_error: return access_error fp_rsp = check_fp(study_id, sample_template) if fp_rsp['status'] != 'success': # Unknown filepath, so return the error message return fp_rsp fp_rsp = fp_rsp['file'] msg = '' status = 'success' # Offload the update of the sample template to the cluster job_id = safe_submit(user_id, update_sample_template, int(study_id), fp_rsp) # Store the job id attaching it to the sample template id r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study_id, dumps({'job_id': job_id})) return {'status': status, 'message': msg, 'file': sample_template}
def sample_template_post_req(study_id, user_id, data_type, sample_template): """Creates the sample template from the given file Parameters ---------- study_id : int The current study object id user_id : str The current user object id data_type : str Data type for the sample template sample_template : str filename to use for creation Returns ------- dict results dictonary in the format {'status': status, 'message': msg, 'file': sample_template} status can be success, warning, or error depending on result message has the warnings or errors file has the file name """ study_id = int(study_id) access_error = check_access(study_id, user_id) if access_error: return access_error fp_rsp = check_fp(study_id, sample_template) if fp_rsp['status'] != 'success': # Unknown filepath, so return the error message return fp_rsp fp_rsp = fp_rsp['file'] # Define here the message and message level in case of success is_mapping_file = looks_like_qiime_mapping_file(fp_rsp) if is_mapping_file and not data_type: return { 'status': 'error', 'message': 'Please, choose a data type if uploading a ' 'QIIME mapping file', 'file': sample_template } qiita_plugin = Software.from_name_and_version('Qiita', 'alpha') cmd = qiita_plugin.get_command('create_sample_template') params = Parameters.load(cmd, values_dict={ 'fp': fp_rsp, 'study_id': study_id, 'is_mapping_file': is_mapping_file, 'data_type': data_type }) job = ProcessingJob.create(User(user_id), params) r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study_id, dumps({'job_id': job.id})) # Store the job id attaching it to the sample template id job.submit() return {'status': 'success', 'message': '', 'file': sample_template}
def artifact_post_req(user_id, filepaths, artifact_type, name, prep_template_id, artifact_id=None): """Creates the initial artifact for the prep template Parameters ---------- user_id : str User adding the atrifact filepaths : dict of str Comma-separated list of files to attach to the artifact, keyed by file type artifact_type : str The type of the artifact name : str Name to give the artifact prep_template_id : int or str castable to int Prep template to attach the artifact to artifact_id : int or str castable to int, optional The id of the imported artifact Returns ------- dict of objects A dictionary containing the new artifact ID {'status': status, 'message': message, 'artifact': id} """ prep = PrepTemplate(int(prep_template_id)) study_id = prep.study_id # First check if the user has access to the study access_error = check_access(study_id, user_id) if access_error: return access_error 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) else: uploads_path = get_mountpoint('uploads')[0][1] path_builder = partial(join, uploads_path, str(study_id)) cleaned_filepaths = [] for ftype, file_list in viewitems(filepaths): # JavaScript sends us this list as a comma-separated list for fp in file_list.split(','): # JavaScript will send this value as an empty string if the # list of files was empty. In such case, the split will # generate a single element containing the empty string. Check # for that case here and, if fp is not the empty string, # proceed to check if the file exists if fp: # Check if filepath being passed exists for study full_fp = path_builder(fp) exists = check_fp(study_id, full_fp) if exists['status'] != 'success': return {'status': 'error', 'message': 'File does not exist: %s' % fp} cleaned_filepaths.append((full_fp, ftype)) # This should never happen, but it doesn't hurt to actually have # a explicit check, in case there is something odd with the JS if not cleaned_filepaths: return {'status': 'error', 'message': "Can't create artifact, no files provided."} job_id = safe_submit(user_id, create_raw_data, artifact_type, prep, cleaned_filepaths, name=name) r_client.set(PREP_TEMPLATE_KEY_FORMAT % prep.id, dumps({'job_id': job_id})) return {'status': 'success', 'message': ''}
def artifact_post_req(user_id, filepaths, artifact_type, name, prep_template_id, artifact_id=None): """Creates the initial artifact for the prep template Parameters ---------- user_id : str User adding the atrifact filepaths : dict of str Comma-separated list of files to attach to the artifact, keyed by file type artifact_type : str The type of the artifact name : str Name to give the artifact prep_template_id : int or str castable to int Prep template to attach the artifact to artifact_id : int or str castable to int, optional The id of the imported artifact Returns ------- dict of objects A dictionary containing the new artifact ID {'status': status, 'message': message, 'artifact': id} """ prep = PrepTemplate(int(prep_template_id)) study_id = prep.study_id # First check if the user has access to the study access_error = check_access(study_id, user_id) if access_error: return access_error if artifact_id: # if the artifact id has been provided, import the artifact try: artifact = Artifact.copy(Artifact(artifact_id), prep) 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': 'error', 'message': "Error creating artifact: %s" % str(e)} else: uploads_path = get_mountpoint('uploads')[0][1] path_builder = partial(join, uploads_path, str(study_id)) cleaned_filepaths = [] for ftype, file_list in viewitems(filepaths): # JavaScript sends us this list as a comma-separated list for fp in file_list.split(','): # JavaScript will send this value as an empty string if the # list of files was empty. In such case, the split will # generate a single element containing the empty string. Check # for that case here and, if fp is not the empty string, # proceed to check if the file exists if fp: # Check if filepath being passed exists for study full_fp = path_builder(fp) exists = check_fp(study_id, full_fp) if exists['status'] != 'success': return {'status': 'error', 'message': 'File does not exist: %s' % fp} cleaned_filepaths.append((full_fp, ftype)) # This should never happen, but it doesn't hurt to actually have # a explicit check, in case there is something odd with the JS if not cleaned_filepaths: return {'status': 'error', 'message': "Can't create artifact, no files provided."} try: artifact = Artifact.create(cleaned_filepaths, artifact_type, name=name, prep_template=prep) 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': 'error', 'message': "Error creating artifact: %s" % str(e)} return {'status': 'success', 'message': '', 'artifact': artifact.id}
def prep_template_patch_req(user_id, req_op, req_path, req_value=None, req_from=None): """Modifies an attribute of the prep template Parameters ---------- user_id : str The id of the user performing the patch operation req_op : str The operation to perform on the prep information req_path : str The prep information and attribute to patch req_value : str, optional The value that needs to be modified req_from : str, optional The original path of the element Returns ------- dict of {str, str} A dictionary with the following keys: - status: str, whether if the request is successful or not - message: str, if the request is unsuccessful, a human readable error """ if req_op == 'replace': req_path = [v for v in req_path.split('/') if v] # The structure of the path should be /prep_id/attribute_to_modify/ # so if we don't have those 2 elements, we should return an error if len(req_path) != 2: return {'status': 'error', 'message': 'Incorrect path parameter'} prep_id = int(req_path[0]) attribute = req_path[1] # Check if the user actually has access to the prep template prep = PrepTemplate(prep_id) access_error = check_access(prep.study_id, user_id) if access_error: return access_error status = 'success' msg = '' if attribute == 'investigation_type': prep.investigation_type = req_value elif attribute == 'data': fp = check_fp(prep.study_id, req_value) if fp['status'] != 'success': return fp fp = fp['file'] job_id = safe_submit(user_id, update_prep_template, prep_id, fp) r_client.set(PREP_TEMPLATE_KEY_FORMAT % prep_id, job_id) else: # We don't understand the attribute so return an error return {'status': 'error', 'message': 'Attribute "%s" not found. ' 'Please, check the path parameter' % attribute} return {'status': status, 'message': msg} else: return {'status': 'error', 'message': 'Operation "%s" not supported. ' 'Current supported operations: replace' % req_op}
def artifact_post_req(user_id, filepaths, artifact_type, name, prep_template_id, artifact_id=None): """Creates the initial artifact for the prep template Parameters ---------- user_id : str User adding the atrifact filepaths : dict of str Comma-separated list of files to attach to the artifact, keyed by file type artifact_type : str The type of the artifact name : str Name to give the artifact prep_template_id : int or str castable to int Prep template to attach the artifact to artifact_id : int or str castable to int, optional The id of the imported artifact Returns ------- dict of objects A dictionary containing the new artifact ID {'status': status, 'message': message, 'artifact': id} """ prep_template_id = int(prep_template_id) prep = PrepTemplate(prep_template_id) study_id = prep.study_id # First check if the user has access to the study access_error = check_access(study_id, user_id) if access_error: return access_error user = User(user_id) if artifact_id: # if the artifact id has been provided, import the artifact 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, True) else: uploads_path = get_mountpoint('uploads')[0][1] path_builder = partial(join, uploads_path, str(study_id)) cleaned_filepaths = {} for ftype, file_list in filepaths.items(): # JavaScript sends us this list as a comma-separated list for fp in file_list.split(','): # JavaScript will send this value as an empty string if the # list of files was empty. In such case, the split will # generate a single element containing the empty string. Check # for that case here and, if fp is not the empty string, # proceed to check if the file exists if fp: # Check if filepath being passed exists for study full_fp = path_builder(fp) exists = check_fp(study_id, full_fp) if exists['status'] != 'success': return { 'status': 'error', 'message': 'File does not exist: %s' % fp } if ftype not in cleaned_filepaths: cleaned_filepaths[ftype] = [] cleaned_filepaths[ftype].append(full_fp) # This should never happen, but it doesn't hurt to actually have # a explicit check, in case there is something odd with the JS if not cleaned_filepaths: return { 'status': 'error', 'message': "Can't create artifact, no files provided." } # This try/except will catch the case when the plugins are not # activated so there is no Validate for the given artifact_type try: command = Command.get_validator(artifact_type) except QiitaDBError as e: return {'status': 'error', 'message': str(e)} job = ProcessingJob.create( user, Parameters.load(command, values_dict={ 'template': prep_template_id, 'files': dumps(cleaned_filepaths), 'artifact_type': artifact_type, 'name': name, 'analysis': None, }), True) # Submit the job job.submit() r_client.set(PREP_TEMPLATE_KEY_FORMAT % prep.id, dumps({ 'job_id': job.id, 'is_qiita_job': True })) return {'status': 'success', 'message': ''}
def prep_template_patch_req(user_id, req_op, req_path, req_value=None, req_from=None): """Modifies an attribute of the prep template Parameters ---------- user_id : str The id of the user performing the patch operation req_op : str The operation to perform on the prep information req_path : str The prep information and attribute to patch req_value : str, optional The value that needs to be modified req_from : str, optional The original path of the element Returns ------- dict of {str, str} A dictionary with the following keys: - status: str, whether if the request is successful or not - message: str, if the request is unsuccessful, a human readable error """ req_path = [v for v in req_path.split('/') if v] if req_op == 'replace': # The structure of the path should be /prep_id/attribute_to_modify/ # so if we don't have those 2 elements, we should return an error if len(req_path) != 2: return {'status': 'error', 'message': 'Incorrect path parameter'} prep_id = int(req_path[0]) attribute = req_path[1] # Check if the user actually has access to the prep template prep = PrepTemplate(prep_id) access_error = check_access(prep.study_id, user_id) if access_error: return access_error status = 'success' msg = '' if attribute == 'investigation_type': prep.investigation_type = req_value elif attribute == 'data': fp = check_fp(prep.study_id, req_value) if fp['status'] != 'success': return fp fp = fp['file'] job_id = safe_submit(user_id, update_prep_template, prep_id, fp) r_client.set(PREP_TEMPLATE_KEY_FORMAT % prep_id, dumps({'job_id': job_id})) else: # We don't understand the attribute so return an error return {'status': 'error', 'message': 'Attribute "%s" not found. ' 'Please, check the path parameter' % attribute} return {'status': status, 'message': msg} elif req_op == 'remove': # The structure of the path should be /prep_id/{columns|samples}/name if len(req_path) != 3: return {'status': 'error', 'message': 'Incorrect path parameter'} prep_id = int(req_path[0]) attribute = req_path[1] attr_id = req_path[2] # Check if the user actually has access to the study pt = PrepTemplate(prep_id) access_error = check_access(pt.study_id, user_id) if access_error: return access_error # Offload the deletion of the column to the cluster job_id = safe_submit(user_id, delete_sample_or_column, PrepTemplate, prep_id, attribute, attr_id) # Store the job id attaching it to the sample template id r_client.set(PREP_TEMPLATE_KEY_FORMAT % prep_id, dumps({'job_id': job_id})) return {'status': 'success', 'message': ''} else: return {'status': 'error', 'message': 'Operation "%s" not supported. ' 'Current supported operations: replace, remove' % req_op}
def prep_template_post_req(study_id, user_id, prep_template, data_type, investigation_type=None, user_defined_investigation_type=None, new_investigation_type=None): """Adds a prep template to the system Parameters ---------- study_id : int Study to attach the prep template to user_id : str User adding the prep template prep_template : str Filepath to the prep template being added data_type : str Data type of the processed samples investigation_type: str, optional Existing investigation type to attach to the prep template user_defined_investigation_type: str, optional Existing user added investigation type to attach to the prep template new_investigation_type: str, optional Investigation type to add to the system Returns ------- dict of str {'status': status, 'message': message, 'file': prep_template, 'id': id} """ access_error = check_access(study_id, user_id) if access_error: return access_error fp_rpt = check_fp(study_id, prep_template) if fp_rpt['status'] != 'success': # Unknown filepath, so return the error message return fp_rpt fp_rpt = fp_rpt['file'] # Add new investigation type if needed investigation_type = _process_investigation_type( investigation_type, user_defined_investigation_type, new_investigation_type) msg = '' status = 'success' prep = None try: with warnings.catch_warnings(record=True) as warns: # deleting previous uploads and inserting new one prep = PrepTemplate.create( load_template_to_dataframe(fp_rpt), Study(study_id), data_type, investigation_type=investigation_type) remove(fp_rpt) # join all the warning messages into one. Note that this info # will be ignored if an exception is raised if warns: msg = '\n'.join(set(str(w.message) for w in warns)) status = 'warning' except Exception as e: # Some error occurred while processing the prep template # Show the error to the user so he can fix the template status = 'error' msg = str(e) info = {'status': status, 'message': msg, 'file': prep_template, 'id': prep.id if prep is not None else None} return info
def artifact_post_req(user_id, filepaths, artifact_type, name, prep_template_id, artifact_id=None): """Creates the initial artifact for the prep template Parameters ---------- user_id : str User adding the atrifact filepaths : dict of str Comma-separated list of files to attach to the artifact, keyed by file type artifact_type : str The type of the artifact name : str Name to give the artifact prep_template_id : int or str castable to int Prep template to attach the artifact to artifact_id : int or str castable to int, optional The id of the imported artifact Returns ------- dict of objects A dictionary containing the new artifact ID {'status': status, 'message': message, 'artifact': id} """ prep = PrepTemplate(int(prep_template_id)) study_id = prep.study_id # First check if the user has access to the study access_error = check_access(study_id, user_id) if access_error: return access_error 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) else: uploads_path = get_mountpoint('uploads')[0][1] path_builder = partial(join, uploads_path, str(study_id)) cleaned_filepaths = [] for ftype, file_list in viewitems(filepaths): # JavaScript sends us this list as a comma-separated list for fp in file_list.split(','): # JavaScript will send this value as an empty string if the # list of files was empty. In such case, the split will # generate a single element containing the empty string. Check # for that case here and, if fp is not the empty string, # proceed to check if the file exists if fp: # Check if filepath being passed exists for study full_fp = path_builder(fp) exists = check_fp(study_id, full_fp) if exists['status'] != 'success': return { 'status': 'error', 'message': 'File does not exist: %s' % fp } cleaned_filepaths.append((full_fp, ftype)) # This should never happen, but it doesn't hurt to actually have # a explicit check, in case there is something odd with the JS if not cleaned_filepaths: return { 'status': 'error', 'message': "Can't create artifact, no files provided." } job_id = safe_submit(user_id, create_raw_data, artifact_type, prep, cleaned_filepaths, name=name) r_client.set(PREP_TEMPLATE_KEY_FORMAT % prep.id, dumps({'job_id': job_id})) return {'status': 'success', 'message': ''}
def prep_template_post_req(study_id, user_id, prep_template, data_type, investigation_type=None, user_defined_investigation_type=None, new_investigation_type=None, name=None): """Adds a prep template to the system Parameters ---------- study_id : int Study to attach the prep template to user_id : str User adding the prep template prep_template : str Filepath to the prep template being added data_type : str Data type of the processed samples investigation_type: str, optional Existing investigation type to attach to the prep template user_defined_investigation_type: str, optional Existing user added investigation type to attach to the prep template new_investigation_type: str, optional Investigation type to add to the system name : str, optional The name of the new prep template Returns ------- dict of str {'status': status, 'message': message, 'file': prep_template, 'id': id} """ access_error = check_access(study_id, user_id) if access_error: return access_error fp_rpt = check_fp(study_id, prep_template) if fp_rpt['status'] != 'success': # Unknown filepath, so return the error message return fp_rpt fp_rpt = fp_rpt['file'] # Add new investigation type if needed investigation_type = _process_investigation_type( investigation_type, user_defined_investigation_type, new_investigation_type) msg = '' status = 'success' prep = None if name: name = name if name.strip() else None try: with warnings.catch_warnings(record=True) as warns: # deleting previous uploads and inserting new one prep = PrepTemplate.create( load_template_to_dataframe(fp_rpt), Study(study_id), data_type, investigation_type=investigation_type, name=name) remove(fp_rpt) # join all the warning messages into one. Note that this info # will be ignored if an exception is raised if warns: msg = '\n'.join(set(str(w.message) for w in warns)) status = 'warning' except Exception as e: # Some error occurred while processing the prep template # Show the error to the user so he can fix the template status = 'error' msg = str(e) info = {'status': status, 'message': msg, 'file': prep_template, 'id': prep.id if prep is not None else None} return info
def prep_template_patch_req(user_id, req_op, req_path, req_value=None, req_from=None): """Modifies an attribute of the prep template Parameters ---------- user_id : str The id of the user performing the patch operation req_op : str The operation to perform on the prep information req_path : str The prep information and attribute to patch req_value : str, optional The value that needs to be modified req_from : str, optional The original path of the element Returns ------- dict of {str, str, str} A dictionary with the following keys: - status: str, whether if the request is successful or not - message: str, if the request is unsuccessful, a human readable error - row_id: str, the row_id that we tried to delete """ req_path = [v for v in req_path.split('/') if v] if req_op == 'replace': # The structure of the path should be /prep_id/attribute_to_modify/ # so if we don't have those 2 elements, we should return an error if len(req_path) != 2: return {'status': 'error', 'message': 'Incorrect path parameter'} prep_id = int(req_path[0]) attribute = req_path[1] # Check if the user actually has access to the prep template prep = PrepTemplate(prep_id) access_error = check_access(prep.study_id, user_id) if access_error: return access_error status = 'success' msg = '' if attribute == 'investigation_type': prep.investigation_type = req_value elif attribute == 'data': fp = check_fp(prep.study_id, req_value) if fp['status'] != 'success': return fp fp = fp['file'] qiita_plugin = Software.from_name_and_version('Qiita', 'alpha') cmd = qiita_plugin.get_command('update_prep_template') params = Parameters.load( cmd, values_dict={'prep_template': prep_id, 'template_fp': fp}) job = ProcessingJob.create(User(user_id), params, True) r_client.set(PREP_TEMPLATE_KEY_FORMAT % prep_id, dumps({'job_id': job.id})) job.submit() elif attribute == 'name': prep.name = req_value.strip() else: # We don't understand the attribute so return an error return {'status': 'error', 'message': 'Attribute "%s" not found. ' 'Please, check the path parameter' % attribute} return {'status': status, 'message': msg} elif req_op == 'remove': # The structure of the path should be: # /prep_id/row_id/{columns|samples}/name if len(req_path) != 4: return {'status': 'error', 'message': 'Incorrect path parameter'} prep_id = int(req_path[0]) row_id = req_path[1] attribute = req_path[2] attr_id = req_path[3] # Check if the user actually has access to the study pt = PrepTemplate(prep_id) access_error = check_access(pt.study_id, user_id) if access_error: return access_error qiita_plugin = Software.from_name_and_version('Qiita', 'alpha') cmd = qiita_plugin.get_command('delete_sample_or_column') params = Parameters.load( cmd, values_dict={'obj_class': 'PrepTemplate', 'obj_id': prep_id, 'sample_or_col': attribute, 'name': attr_id}) job = ProcessingJob.create(User(user_id), params, True) # Store the job id attaching it to the sample template id r_client.set(PREP_TEMPLATE_KEY_FORMAT % prep_id, dumps({'job_id': job.id})) job.submit() return {'status': 'success', 'message': '', 'row_id': row_id} else: return {'status': 'error', 'message': 'Operation "%s" not supported. ' 'Current supported operations: replace, remove' % req_op, 'row_id': '0'}
def test_check_fp_bad_fp(self): obs = check_fp(1, 'badfile') exp = {'status': 'error', 'message': 'file does not exist', 'file': 'badfile'} self.assertEqual(obs, exp)
def artifact_post_req(user_id, filepaths, artifact_type, name, prep_template_id, artifact_id=None): """Creates the initial artifact for the prep template Parameters ---------- user_id : str User adding the atrifact filepaths : dict of str Comma-separated list of files to attach to the artifact, keyed by file type artifact_type : str The type of the artifact name : str Name to give the artifact prep_template_id : int or str castable to int Prep template to attach the artifact to artifact_id : int or str castable to int, optional The id of the imported artifact Returns ------- dict of objects A dictionary containing the new artifact ID {'status': status, 'message': message, 'artifact': id} """ prep_template_id = int(prep_template_id) prep = PrepTemplate(prep_template_id) study_id = prep.study_id # First check if the user has access to the study access_error = check_access(study_id, user_id) if access_error: return access_error user = User(user_id) if artifact_id: # if the artifact id has been provided, import the artifact 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, True) else: uploads_path = get_mountpoint('uploads')[0][1] path_builder = partial(join, uploads_path, str(study_id)) cleaned_filepaths = {} for ftype, file_list in viewitems(filepaths): # JavaScript sends us this list as a comma-separated list for fp in file_list.split(','): # JavaScript will send this value as an empty string if the # list of files was empty. In such case, the split will # generate a single element containing the empty string. Check # for that case here and, if fp is not the empty string, # proceed to check if the file exists if fp: # Check if filepath being passed exists for study full_fp = path_builder(fp) exists = check_fp(study_id, full_fp) if exists['status'] != 'success': return {'status': 'error', 'message': 'File does not exist: %s' % fp} if ftype not in cleaned_filepaths: cleaned_filepaths[ftype] = [] cleaned_filepaths[ftype].append(full_fp) # This should never happen, but it doesn't hurt to actually have # a explicit check, in case there is something odd with the JS if not cleaned_filepaths: return {'status': 'error', 'message': "Can't create artifact, no files provided."} # This try/except will catch the case when the plugins are not # activated so there is no Validate for the given artifact_type try: command = Command.get_validator(artifact_type) except QiitaDBError as e: return {'status': 'error', 'message': str(e)} job = ProcessingJob.create( user, Parameters.load(command, values_dict={ 'template': prep_template_id, 'files': dumps(cleaned_filepaths), 'artifact_type': artifact_type, 'name': name, 'analysis': None, }), True) # Submit the job job.submit() r_client.set(PREP_TEMPLATE_KEY_FORMAT % prep.id, dumps({'job_id': job.id, 'is_qiita_job': True})) return {'status': 'success', 'message': ''}