Exemple #1
0
    def test_prep_template_graph_get_req(self):
        obs = prep_template_graph_get_req(1, '*****@*****.**')
        exp = {'edge_list': [(1, 3), (1, 2), (2, 4), (2, 5), (2, 6)],
               'node_labels': [(1, 'Raw data 1 - FASTQ'),
                               (2, 'Demultiplexed 1 - Demultiplexed'),
                               (3, 'Demultiplexed 2 - Demultiplexed'),
                               (4, 'BIOM - BIOM'),
                               (5, 'BIOM - BIOM'),
                               (6, 'BIOM - BIOM')],
               'status': 'success',
               'message': ''}
        self.assertItemsEqual(obs['edge_list'], exp['edge_list'])
        self.assertItemsEqual(obs['node_labels'], exp['node_labels'])
        self.assertEqual(obs['status'], exp['status'])
        self.assertEqual(obs['message'], exp['message'])

        Artifact(4).visibility = "public"
        obs = prep_template_graph_get_req(1, '*****@*****.**')
        exp = {'edge_list': [(1, 2), (2, 4)],
               'node_labels': [(1, 'Raw data 1 - FASTQ'),
                               (2, 'Demultiplexed 1 - Demultiplexed'),
                               (4, 'BIOM - BIOM')],
               'status': 'success',
               'message': ''}
        self.assertItemsEqual(obs['edge_list'], exp['edge_list'])
        self.assertItemsEqual(obs['node_labels'], exp['node_labels'])
        self.assertEqual(obs['status'], exp['status'])
        self.assertEqual(obs['message'], exp['message'])

        # Reset visibility of the artifacts
        for i in range(4, 0, -1):
            Artifact(i).visibility = "private"
Exemple #2
0
def artifact_get_prep_req(user_id, artifact_ids):
    """Returns all prep info sample ids for the given artifact_ids

    Parameters
    ----------
    user_id : str
        user making the request
    artifact_ids : list of int
        list of artifact ids

    Returns
    -------
    dict of objects
        A dictionary containing the artifact information
        {'status': status,
         'message': message,
         'data': {artifact_id: [prep info sample ids]}
    """
    samples = {}

    for aid in sorted(artifact_ids):
        artifact = Artifact(aid)
        access_error = check_access(artifact.study.id, user_id)
        if access_error:
            return access_error

        samples[aid] = list(
            chain(*[sorted(pt.keys()) for pt in Artifact(aid).prep_templates]))

    return {'status': 'success', 'msg': '', 'data': samples}
Exemple #3
0
    def test_artifact_post_req(self):
        # Create new prep template to attach artifact to
        pt = npt.assert_warns(QiitaDBWarning, PrepTemplate.create,
                              pd.DataFrame({'new_col': {
                                  '1.SKD6.640190': 1
                              }}), Study(1), '16S')
        self._files_to_remove.extend([fp for _, fp in pt.get_filepaths()])

        new_artifact_id = get_count('qiita.artifact') + 1
        filepaths = {
            'raw_forward_seqs': 'uploaded_file.txt',
            'raw_barcodes': 'update.txt'
        }
        obs = artifact_post_req('*****@*****.**', filepaths, 'FASTQ',
                                'New Test Artifact', pt.id)
        exp = {'status': 'success', 'message': ''}
        self.assertEqual(obs, exp)

        obs = r_client.get('prep_template_%d' % pt.id)
        self.assertIsNotNone(obs)
        redis_info = loads(r_client.get(loads(obs)['job_id']))
        while redis_info['status_msg'] == 'Running':
            sleep(0.05)
            redis_info = loads(r_client.get(loads(obs)['job_id']))

        # Instantiate the artifact to make sure it was made and
        # to clean the environment
        a = Artifact(new_artifact_id)
        self._files_to_remove.extend([fp for _, fp, _ in a.filepaths])

        # Test importing an artifact
        # Create new prep template to attach artifact to
        pt = npt.assert_warns(QiitaDBWarning, PrepTemplate.create,
                              pd.DataFrame({'new_col': {
                                  '1.SKD6.640190': 1
                              }}), Study(1), '16S')
        self._files_to_remove.extend([fp for _, fp in pt.get_filepaths()])

        new_artifact_id_2 = get_count('qiita.artifact') + 1
        obs = artifact_post_req('*****@*****.**', {}, 'FASTQ',
                                'New Test Artifact 2', pt.id, new_artifact_id)
        exp = {'status': 'success', 'message': ''}
        self.assertEqual(obs, exp)

        obs = r_client.get('prep_template_%d' % pt.id)
        self.assertIsNotNone(obs)
        redis_info = loads(r_client.get(loads(obs)['job_id']))
        while redis_info['status_msg'] == 'Running':
            sleep(0.05)
            redis_info = loads(r_client.get(loads(obs)['job_id']))
        # Instantiate the artifact to make sure it was made and
        # to clean the environment
        a = Artifact(new_artifact_id_2)
        self._files_to_remove.extend([fp for _, fp, _ in a.filepaths])
Exemple #4
0
def artifact_post_req(user, artifact_id):
    """Deletes the artifact

    Parameters
    ----------
    user : qiita_db.user.User
        The user requesting the action
    artifact_id : int
        Id of the artifact being deleted
    """
    artifact_id = int(artifact_id)
    artifact = Artifact(artifact_id)
    check_artifact_access(user, artifact)

    analysis = artifact.analysis

    if analysis:
        # Do something when deleting in the analysis part to keep track of it
        redis_key = "analysis_%s" % analysis.id
    else:
        pt_id = artifact.prep_templates[0].id
        redis_key = PREP_TEMPLATE_KEY_FORMAT % pt_id

    qiita_plugin = Software.from_name_and_version('Qiita', 'alpha')
    cmd = qiita_plugin.get_command('delete_artifact')
    params = Parameters.load(cmd, values_dict={'artifact': artifact_id})
    job = ProcessingJob.create(user, params)

    r_client.set(redis_key, dumps({'job_id': job.id, 'is_qiita_job': True}))

    job.submit()
Exemple #5
0
def artifact_post_req(user, artifact_id):
    """Deletes the artifact

    Parameters
    ----------
    user : qiita_db.user.User
        The user requesting the action
    artifact_id : int
        Id of the artifact being deleted
    """
    artifact_id = int(artifact_id)
    artifact = Artifact(artifact_id)
    check_artifact_access(user, artifact)

    analysis = artifact.analysis

    if analysis:
        # Do something when deleting in the analysis part to keep track of it
        redis_key = "analysis_%s" % analysis.id
    else:
        pt_id = artifact.prep_templates[0].id
        redis_key = PREP_TEMPLATE_KEY_FORMAT % pt_id

    job_id = safe_submit(user.id, delete_artifact, artifact_id)
    r_client.set(redis_key, dumps({'job_id': job_id, 'is_qiita_job': False}))
Exemple #6
0
def artifact_delete_req(artifact_id, user_id):
    """Deletes the artifact

    Parameters
    ----------
    artifact_id : int
        Artifact being acted on
    user_id : str
        The user requesting the action

    Returns
    -------
    dict
        Status of action, in the form {'status': status, 'message': msg}
        status: status of the action, either success or error
        message: Human readable message for status
    """
    pd = Artifact(int(artifact_id))
    pt_id = pd.prep_templates[0].id
    access_error = check_access(pd.study.id, user_id)
    if access_error:
        return access_error

    job_id = safe_submit(user_id, delete_artifact, artifact_id)
    r_client.set(PREP_TEMPLATE_KEY_FORMAT % pt_id, dumps({'job_id': job_id}))

    return {'status': 'success', 'message': ''}
Exemple #7
0
    def post(self, preprocessed_data_id):
        user = self.current_user
        # make sure user is admin and can therefore actually submit to VAMPS
        if user.level != 'admin':
            raise HTTPError(403, "User %s cannot submit to VAMPS!" % user.id)
        msg = ''
        msg_level = 'success'
        study = Artifact(preprocessed_data_id).study
        study_id = study.id
        state = study.ebi_submission_status
        if state == 'submitting':
            msg = "Cannot resubmit! Current state is: %s" % state
            msg_level = 'danger'
        else:
            channel = user.id
            job_id = submit(channel, submit_to_VAMPS,
                            int(preprocessed_data_id))

            self.render(
                'compute_wait.html',
                job_id=job_id,
                title='VAMPS Submission',
                completion_redirect=('/study/description/%s?top_tab='
                                     'preprocessed_data_tab&sub_tab=%s' %
                                     (study_id, preprocessed_data_id)))
            return

        self.display_template(preprocessed_data_id, msg, msg_level)
Exemple #8
0
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 setUp(self):
        uploads_path = get_mountpoint('uploads')[0][1]
        # Create prep test file to point at
        self.update_fp = join(uploads_path, '1', 'update.txt')
        with open(self.update_fp, 'w') as f:
            f.write("""sample_name\tnew_col\n1.SKD6.640190\tnew_value\n""")

        self._files_to_remove = [self.update_fp]
        self._files_to_remove = []

        # creating temporal files and artifact
        # NOTE: we don't need to remove the artifact created cause it's
        # used to test the delete functionality
        fd, fp = mkstemp(suffix='_seqs.fna')
        close(fd)
        with open(fp, 'w') as f:
            f.write(">1.sid_r4_0 M02034:17:000000000-A5U18:1:1101:15370:1394 "
                    "1:N:0:1 orig_bc=CATGAGCT new_bc=CATGAGCT bc_diffs=0\n"
                    "GTGTGCCAGCAGCCGCGGTAATACGTAGGG\n")
        # 4 Demultiplexed
        filepaths_processed = [(fp, 4)]
        # 1 for default parameters and input data
        exp_params = Parameters.from_default_params(DefaultParameters(1),
                                                    {'input_data': 1})
        self.artifact = Artifact.create(filepaths_processed, "Demultiplexed",
                                        parents=[Artifact(1)],
                                        processing_parameters=exp_params)
Exemple #10
0
    def post(self, preprocessed_data_id):
        user = self.current_user
        # make sure user is admin and can therefore actually submit to VAMPS
        if user.level != 'admin':
            raise HTTPError(403, "User %s cannot submit to VAMPS!" % user.id)
        msg = ''
        msg_level = 'success'

        plugin = Software.from_name_and_version('Qiita', 'alpha')
        cmd = plugin.get_command('submit_to_VAMPS')
        artifact = Artifact(preprocessed_data_id)

        # Check if the artifact is already being submitted to VAMPS
        is_being_submitted = any([
            j.status in ('queued', 'running') for j in artifact.jobs(cmd=cmd)
        ])

        if is_being_submitted == 'submitting':
            msg = "Cannot resubmit! Data is already being submitted"
            msg_level = 'danger'
            self.display_template(preprocessed_data_id, msg, msg_level)
        else:
            params = Parameters.load(
                cmd, values_dict={'artifact': preprocessed_data_id})
            job = ProcessingJob.create(user, params)
            job.submit()
            self.redirect('/study/description/%s' % artifact.study.study_id)
Exemple #11
0
    def get(self):
        artifact_id = self.get_argument("artifact_id", None)

        if artifact_id is None:
            raise HTTPError(422, reason='You need to specify an artifact id')
        else:
            try:
                artifact = Artifact(artifact_id)
            except QiitaDBUnknownIDError:
                raise HTTPError(404, reason='Artifact does not exist')
            else:
                if artifact.visibility != 'public':
                    raise HTTPError(404, reason='Artifact is not public. If '
                                    'this is a mistake contact: '
                                    '*****@*****.**')
                else:
                    to_download = self._list_artifact_files_nginx(artifact)
                    if not to_download:
                        raise HTTPError(422, reason='Nothing to download. If '
                                        'this is a mistake contact: '
                                        '*****@*****.**')
                    else:
                        self._write_nginx_file_list(to_download)

                        zip_fn = 'artifact_%s_%s.zip' % (
                            artifact_id, datetime.now().strftime(
                                '%m%d%y-%H%M%S'))

                        self._set_nginx_headers(zip_fn)
        self.finish()
    def approve_study(self, study, user, callback):
        """Approves the current study if and only if the current user is admin

        Parameters
        ----------
        study : Study
            The current study object
        user : User
            The current user object
        callback : function
            The callback function to call with the results once the processing
            is done
        """
        if _approve(user.level):
            pd_id = int(self.get_argument('pd_id'))
            pd = Artifact(pd_id)
            pd.visibility = 'private'
            _propagate_visibility(pd)
            msg = "Processed data approved"
            msg_level = "success"
        else:
            msg = ("The current user does not have permission to approve "
                   "the processed data")
            msg_level = "danger"
        callback((msg, msg_level, "processed_data_tab", pd_id, None))
Exemple #13
0
    def test_download(self):
        # check failures
        response = self.get('/public_artifact_download/')
        self.assertEqual(response.code, 422)
        self.assertEqual(response.reason, 'You need to specify an artifact id')

        response = self.get('/public_artifact_download/?artifact_id=10000')
        self.assertEqual(response.code, 404)
        self.assertEqual(response.reason, 'Artifact does not exist')

        response = self.get('/public_artifact_download/?artifact_id=3')
        self.assertEqual(response.code, 404)
        self.assertEqual(
            response.reason, 'Artifact is not public. If this is '
            'a mistake contact: [email protected]')

        # check success
        Artifact(5).visibility = 'public'
        response = self.get('/public_artifact_download/?artifact_id=5')
        self.assertEqual(response.code, 200)
        exp = ('- [0-9]* /protected/processed_data/'
               '1_study_1001_closed_reference_otu_table.biom '
               'processed_data/1_study_1001_closed_reference_otu_table.biom\n'
               '- [0-9]* /protected/templates/1_prep_1_[0-9]*-[0-9]*.txt '
               'mapping_files/5_mapping_file.txt')
        self.assertRegex(response.body.decode('ascii'), exp)
Exemple #14
0
    def post(self, preprocessed_data_id):
        # make sure user is admin and can therefore actually submit to VAMPS
        if self.current_user.level != 'admin':
            raise HTTPError(
                403, "User %s cannot submit to VAMPS!" % self.current_user.id)
        msg = ''
        msg_level = 'success'
        preprocessed_data = Artifact(preprocessed_data_id)
        state = preprocessed_data.submitted_to_vamps_status()

        demux = [
            path for _, path, ftype in preprocessed_data.get_filepaths()
            if ftype == 'preprocessed_demux'
        ]
        demux_length = len(demux)

        if state in ('submitting', 'success'):
            msg = "Cannot resubmit! Current state is: %s" % state
            msg_level = 'danger'
        elif demux_length != 1:
            msg = "The study doesn't have demux files or have too many" % state
            msg_level = 'danger'
        else:
            channel = self.current_user.id
            job_id = submit(channel, submit_to_VAMPS,
                            int(preprocessed_data_id))

            self.render('compute_wait.html',
                        job_id=job_id,
                        title='VAMPS Submission',
                        completion_redirect='/compute_complete/%s' % job_id)
            return

        self.display_template(preprocessed_data_id, msg, msg_level)
Exemple #15
0
    def get(self, analysis_id):
        analysis_id = int(analysis_id.split("/")[0])
        analysis = Analysis(analysis_id)
        check_analysis_access(self.current_user, analysis)

        jobres = defaultdict(list)
        for jobject in analysis.jobs:
            results = []
            for res in jobject.results:
                name = basename(res)
                if name.startswith('index'):
                    name = basename(dirname(res)).replace('_', ' ')
                results.append((res, name))
            jobres[jobject.datatype].append((jobject.command[0], results))

        dropped_samples = analysis.dropped_samples
        dropped = defaultdict(list)
        for proc_data_id, samples in viewitems(dropped_samples):
            if not samples:
                continue
            proc_data = Artifact(proc_data_id)
            data_type = proc_data.data_type
            dropped[data_type].append(
                (proc_data.study.title, len(samples), ', '.join(samples)))

        self.render("analysis_results.html",
                    analysis_id=analysis_id,
                    jobres=jobres,
                    aname=analysis.name,
                    dropped=dropped,
                    basefolder=get_db_files_base_dir())
Exemple #16
0
    def post(self, preprocessed_data_id):
        user = self.current_user
        # make sure user is admin and can therefore actually submit to EBI
        if user.level != 'admin':
            raise HTTPError(403, "User %s cannot submit to EBI!" %
                            user.id)
        submission_type = self.get_argument('submission_type')

        if submission_type not in ['ADD', 'MODIFY']:
            raise HTTPError(403, "User: %s, %s is not a recognized submission "
                            "type" % (user.id, submission_type))

        msg = ''
        msg_level = 'success'
        study = Artifact(preprocessed_data_id).study
        study_id = study.id
        state = study.ebi_submission_status
        if state == 'submitting':
            msg = "Cannot resubmit! Current state is: %s" % state
            msg_level = 'danger'
        else:
            channel = user.id
            job_id = submit(channel, submit_to_ebi, int(preprocessed_data_id),
                            submission_type)

            self.render('compute_wait.html',
                        job_id=job_id, title='EBI Submission',
                        completion_redirect=('/study/description/%s?top_tab='
                                             'preprocessed_data_tab&sub_tab=%s'
                                             % (study_id,
                                                preprocessed_data_id)))
            return

        self.display_template(preprocessed_data_id, msg, msg_level)
Exemple #17
0
    def get(self):
        # Format sel_data to get study IDs for the processed data
        sel_data = defaultdict(dict)
        proc_data_info = {}
        sel_samps = self.current_user.default_analysis.samples
        for pid, samps in viewitems(sel_samps):
            proc_data = Artifact(pid)
            sel_data[proc_data.study][pid] = samps
            # Also get processed data info
            parameters = proc_data.processing_parameters
            reference = Reference(parameters.values['reference'])

            proc_data_info[pid] = {
                'processed_date': str(proc_data.timestamp),
                'algorithm': parameters.command.name,
                'reference_name': reference.name,
                'reference_version': reference.version,
                'sequence_filepath': reference.sequence_fp,
                'taxonomy_filepath': reference.taxonomy_fp,
                'tree_filepath': reference.tree_fp,
                'data_type': proc_data.data_type
            }

        self.render("analysis_selected.html",
                    sel_data=sel_data,
                    proc_info=proc_data_info)
    def test_artifact_post_req(self):
        # Create new prep template to attach artifact to
        pt = npt.assert_warns(
            QiitaDBWarning, PrepTemplate.create,
            pd.DataFrame({'new_col': {'1.SKD6.640190': 1}}), Study(1), '16S')
        self._files_to_remove.extend([fp for _, fp in pt.get_filepaths()])

        filepaths = {'raw_forward_seqs': 'uploaded_file.txt',
                     'raw_barcodes': 'update.txt'}
        obs = artifact_post_req(
            '*****@*****.**', filepaths, 'FASTQ', 'New Test Artifact', pt.id)
        exp = {'status': 'success',
               'message': ''}
        self.assertEqual(obs, exp)
        wait_for_prep_information_job(pt.id)

        # Test importing an artifact
        # Create new prep template to attach artifact to
        pt = npt.assert_warns(
            QiitaDBWarning, PrepTemplate.create,
            pd.DataFrame({'new_col': {'1.SKD6.640190': 1}}), Study(1), '16S')
        self._files_to_remove.extend([fp for _, fp in pt.get_filepaths()])

        obs = artifact_post_req(
            '*****@*****.**', {}, 'Demultiplexed', 'New Test Artifact 2',
            pt.id, 3)
        exp = {'status': 'success',
               'message': ''}
        self.assertEqual(obs, exp)

        wait_for_prep_information_job(pt.id)
        # Instantiate the artifact to make sure it was made and
        # to clean the environment
        a = Artifact(pt.artifact.id)
        self._files_to_remove.extend([fp for _, fp, _ in a.filepaths])
Exemple #19
0
    def get(self):
        # Format sel_data to get study IDs for the processed data
        sel_data = defaultdict(dict)
        proc_data_info = {}
        sel_samps = self.current_user.default_analysis.samples
        for aid, samples in viewitems(sel_samps):
            a = Artifact(aid)
            sel_data[a.study][aid] = samples
            # Also get processed data info
            processing_parameters = a.processing_parameters
            if processing_parameters is None:
                params = None
                algorithm = None
            else:
                cmd = processing_parameters.command
                params = processing_parameters.values
                if 'reference' in params:
                    ref = Reference(params['reference'])
                    del params['reference']

                    params['reference_name'] = ref.name
                    params['reference_version'] = ref.version
                algorithm = '%s (%s)' % (cmd.software.name, cmd.name)

            proc_data_info[aid] = {
                'processed_date': str(a.timestamp),
                'algorithm': algorithm,
                'data_type': a.data_type,
                'params': params
            }

        self.render("analysis_selected.html", sel_data=sel_data,
                    proc_info=proc_data_info)
Exemple #20
0
def process_artifact_handler_get_req(artifact_id):
    """Returns the information for the process artifact handler

    Parameters
    ----------
    artifact_id : int
        The artifact to be processed

    Returns
    -------
    dict of str
        A dictionary containing the artifact information
        {'status': str,
         'message': str,
         'name': str,
         'type': str}
    """
    artifact = Artifact(artifact_id)

    return {
        'status': 'success',
        'message': '',
        'name': artifact.name,
        'type': artifact.artifact_type,
        'study_id': artifact.study.id
    }
    def test_artifact_patch_request(self):
        obs = artifact_patch_request('*****@*****.**', 'replace',
                                     '/%d/name/' % self.artifact.id,
                                     req_value='NEW_NAME')
        exp = {'status': 'success', 'message': ''}
        self.assertEqual(obs, exp)

        self.assertEqual(Artifact(self.artifact.id).name, 'NEW_NAME')
Exemple #22
0
def artifact_graph_get_req(artifact_id, direction, user_id):
    """Creates graphs of ancestor or descendant artifacts from given one

    Parameters
    ----------
    artifact_id : int
        Artifact ID to get graph for
    direction : {'ancestors', 'descendants'}
        What direction to get the graph in

    Returns
    -------
    dict of lists of tuples
        A dictionary containing the edge list representation of the graph,
        and the node labels. Formatted as:
        {'status': status,
         'message': message,
         'edge_list': [(0, 1), (0, 2)...],
         'node_labels': [(0, 'label0'), (1, 'label1'), ...]}

    Notes
    -----
    Nodes are identified by the corresponding Artifact ID.
    """
    access_error = check_access(Artifact(artifact_id).study.id, user_id)
    if access_error:
        return access_error

    if direction == 'descendants':
        G = Artifact(int(artifact_id)).descendants
    elif direction == 'ancestors':
        G = Artifact(int(artifact_id)).ancestors
    else:
        return {
            'status': 'error',
            'message': 'Unknown directon %s' % direction
        }

    node_labels = [(n.id, ' - '.join([n.name, n.artifact_type]))
                   for n in G.nodes()]
    return {
        'edge_list': [(n.id, m.id) for n, m in G.edges()],
        'node_labels': node_labels,
        'status': 'success',
        'message': ''
    }
Exemple #23
0
    def test_download(self):
        # check success
        response = self.get('/download/1')
        self.assertEqual(response.code, 200)
        self.assertEqual(response.body.decode('ascii'), (
            "This installation of Qiita was not equipped with nginx, so it "
            "is incapable of serving files. The file you attempted to "
            "download is located at raw_data/1_s_G1_L001_sequences.fastq.gz"))
        self.assertEqual(
            response.headers['Content-Disposition'],
            "attachment; filename=1_1_s_G1_L001_sequences.fastq.gz")
        # other tests to validate the filename
        response = self.get('/download/2')
        self.assertEqual(
            response.headers['Content-Disposition'],
            "attachment; filename=1_1_s_G1_L001_sequences_barcodes.fastq.gz")
        response = self.get('/download/3')
        self.assertEqual(
            response.headers['Content-Disposition'],
            "attachment; filename=2_1_seqs.fna")
        response = self.get('/download/18')
        self.assertEqual(
            response.headers['Content-Disposition'],
            "attachment; filename=1_prep_1_19700101-000000.txt")
        response = self.get('/download/22')
        self.assertEqual(
            response.headers['Content-Disposition'],
            "attachment; filename=7_biom_table.biom")

        # failure
        response = self.get('/download/1000')
        self.assertEqual(response.code, 403)

        # directory
        a = Artifact(1)
        fd, fp = mkstemp(suffix='.html')
        close(fd)
        with open(fp, 'w') as f:
            f.write('\n')
        self._clean_up_files.append(fp)
        dirpath = mkdtemp()
        fd, fp2 = mkstemp(suffix='.txt', dir=dirpath)
        close(fd)
        with open(fp2, 'w') as f:
            f.write('\n')
        self._clean_up_files.append(dirpath)
        a.set_html_summary(fp, support_dir=dirpath)
        for x in a.filepaths:
            if x['fp_type'] == 'html_summary_dir':
                break
        response = self.get('/download/%d' % x['fp_id'])
        self.assertEqual(response.code, 200)

        fp_name = basename(fp2)
        dirname = basename(dirpath)
        self.assertEqual(response.body.decode('ascii'),
                         "- 1 /protected/FASTQ/1/%s/%s FASTQ/1/%s/%s\n" % (
                            dirname, fp_name, dirname, fp_name))
Exemple #24
0
def prep_template_graph_get_req(prep_id, user_id):
    """Returns graph of all artifacts created from the prep base artifact

    Parameters
    ----------
    prep_id : int
        Prep template ID to get graph for
    user_id : str
        User making the request

    Returns
    -------
    dict of lists of tuples
        A dictionary containing the edge list representation of the graph,
        and the node labels. Formatted as:
        {'status': status,
         'message': message,
         'edge_list': [(0, 1), (0, 2)...],
         'node_labels': [(0, 'label0'), (1, 'label1'), ...]}

    Notes
    -----
    Nodes are identified by the corresponding Artifact ID.
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error

    # We should filter for only the public artifacts if the user
    # doesn't have full access to the study
    full_access = Study(prep.study_id).can_edit(User(user_id))

    artifact = prep.artifact

    if artifact is None:
        return {'edges': [], 'nodes': [],
                'status': 'success', 'message': ''}

    G = artifact.descendants_with_jobs

    nodes, edges, wf_id = get_network_nodes_edges(G, full_access)
    # nodes returns [node_type, node_name, element_id]; here we are looking
    # for the node_type == artifact, and check by the element/artifact_id if
    # it's being deleted
    artifacts_being_deleted = [a[2] for a in nodes if a[0] == 'artifact' and
                               Artifact(a[2]).being_deleted_by is not None]

    return {'edges': edges,
            'nodes': nodes,
            'workflow': wf_id,
            'status': 'success',
            'artifacts_being_deleted': artifacts_being_deleted,
            'message': ''}
Exemple #25
0
    def test_public(self):
        response = self.get('/public/')
        self.assertEqual(response.code, 422)
        self.assertIn("You need to specify study_id or artifact_id",
                      response.body.decode('ascii'))

        response = self.get('/public/?study_id=100')
        self.assertEqual(response.code, 422)
        self.assertIn("Study 100 doesn't exist", response.body.decode('ascii'))

        response = self.get('/public/?artifact_id=100')
        self.assertEqual(response.code, 422)
        self.assertIn("Artifact 100 doesn't exist",
                      response.body.decode('ascii'))

        response = self.get('/public/?artifact_id=1')
        self.assertEqual(response.code, 422)
        self.assertIn("Artifact 1 is not public",
                      response.body.decode('ascii'))

        response = self.get('/public/?study_id=1')
        self.assertEqual(response.code, 422)
        self.assertIn("Not a public study", response.body.decode('ascii'))

        # artifact 1 is the first artifact within Study 1
        Artifact(1).visibility = 'public'

        response = self.get('/public/?study_id=1')
        self.assertEqual(response.code, 200)

        response = self.get('/public/?artifact_id=1')
        self.assertEqual(response.code, 200)

        response = self.get('/public/?artifact_id=7')
        self.assertEqual(response.code, 422)
        self.assertIn("Artifact 7 is not public",
                      response.body.decode('ascii'))

        # artifact 8 is part of an analysis
        Artifact(8).visibility = 'public'

        response = self.get('/public/?artifact_id=8')
        self.assertEqual(response.code, 422)
        self.assertIn("Artifact 8 doesn't belong to a study",
                      response.body.decode('ascii'))