Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add artifact creation test handler #1883

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4566c7d
simplifying artifact REST api
josenavas May 18, 2016
a4a5819
Merge branch 'master' of https://github.com/biocore/qiita into simpli…
josenavas May 18, 2016
5f5b0a8
Merge branch 'master' of https://github.com/biocore/qiita into simpli…
josenavas May 24, 2016
f0df60d
Fixing oauth2 tests
josenavas May 25, 2016
41dcb0d
Fixing biom plugin
josenavas May 25, 2016
bfac6a5
Fixing tests
josenavas May 25, 2016
2a60bab
Fixing target gene type plugin
josenavas May 25, 2016
d8fd7c3
Adding docs
josenavas Jun 1, 2016
a57e869
Merge pull request #1853 from josenavas/simplify-rest-api
antgonza Jun 1, 2016
5bea2ae
Merge branch 'master' of https://github.com/biocore/qiita into simpli…
josenavas Jun 13, 2016
fe68ad5
creating is_test_environment function
josenavas Jun 14, 2016
02e84fe
Adding processing job creation handler
josenavas Jun 15, 2016
654a08d
Adding reset handler
josenavas Jun 15, 2016
d303e74
Merge branch 'master' of https://github.com/biocore/qiita into simpli…
josenavas Jun 15, 2016
d4aaf3e
Merge branch 'simplify-restAPI' of https://github.com/biocore/qiita i…
josenavas Jun 15, 2016
f150e43
Adding status optional parameter
josenavas Jun 15, 2016
6f94ecd
Merge pull request #1862 from josenavas/create-test-webserver
ElDeveloper Jun 17, 2016
bf9c525
Merge branch 'master' of https://github.com/biocore/qiita into simpli…
josenavas Jun 28, 2016
15a03de
Adding prep template data handler to REST api (#1871)
josenavas Jun 29, 2016
3932dc6
Add prep test API creation (#1872)
josenavas Jun 29, 2016
8edb83b
Adding prep template get handler
josenavas Jul 5, 2016
bd70612
Addressing @antgonza's comments
josenavas Jul 6, 2016
def0e03
Fixing reference handler
josenavas Jul 6, 2016
665160c
Fixing documentation
josenavas Jul 6, 2016
c93bcda
Adding endpoint to create new artifacts
josenavas Jul 6, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion qiita_core/tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
from unittest import TestCase, main

from qiita_core.util import (
send_email, qiita_test_checker, execute_as_transaction, get_qiita_version)
send_email, qiita_test_checker, execute_as_transaction, get_qiita_version,
is_test_environment)
import qiita_db as qdb


Expand All @@ -28,6 +29,9 @@ def test_send_email_fail(self):
send_email("antgonza@gmail.com", "This is a test",
"This is the body of the test")

def test_is_test_environment(self):
self.assertTrue(is_test_environment())

def test_qiita_test_checker(self):
"""testing qiita test checker"""
@qiita_test_checker()
Expand Down
29 changes: 23 additions & 6 deletions qiita_core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,28 @@ def send_email(to, subject, body):
smtp.close()


def is_test_environment():
"""Checks if Qiita is running in a test environment

Returns
-------
bool
Whether Qiita is running in a test environment or not

Notes
-----
Qiita is running in a test environment if:
- It is connected to a test database, AND
- The config file indicates that this is a test environment
"""
# Check that we are not in a production environment
conn_handler = qdb.sql_connection.SQLConnectionHandler()
# It is possible that we are connecting to a production database
test_db = conn_handler.execute_fetchone("SELECT test FROM settings")[0]
# Or the loaded configuration file belongs to a production environment
return qiita_config.test_environment and test_db


def qiita_test_checker(test=False):
"""Decorator that allows the execution of all methods in a test class only
and only if Qiita is set up to work in a test environment.
Expand All @@ -70,12 +92,7 @@ def qiita_test_checker(test=False):
If Qiita is set up to work in a production environment
"""
def class_modifier(cls):
# First, we check that we are not in a production environment
conn_handler = qdb.sql_connection.SQLConnectionHandler()
# It is possible that we are connecting to a production database
test_db = conn_handler.execute_fetchone("SELECT test FROM settings")[0]
# Or the loaded configuration file belongs to a production environment
if not qiita_config.test_environment or not test_db or test:
if not is_test_environment() or test:
raise RuntimeError("Working in a production environment. Not "
"executing the tests to keep the production "
"database safe.")
Expand Down
132 changes: 77 additions & 55 deletions qiita_db/handlers/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
# -----------------------------------------------------------------------------

from tornado.web import HTTPError
from collections import defaultdict
from json import loads

import qiita_db as qdb
from .oauth2 import OauthBaseHandler, authenticate_oauth
Expand Down Expand Up @@ -43,39 +45,78 @@ def _get_artifact(a_id):
return artifact


class ArtifactFilepathsHandler(OauthBaseHandler):
class ArtifactHandler(OauthBaseHandler):
@authenticate_oauth
def get(self, artifact_id):
"""Retrieves the filepath information of the given artifact
"""Retrieves the artifact information

Parameters
----------
artifact_id : str
The id of the artifact whose filepath information is being
retrieved
The id of the artifact whose information is being retrieved

Returns
-------
dict
{'filepaths': list of (str, str)}
The filepaths attached to the artifact and their filepath types
The artifact information:
'name': artifact name
'timestamp': artifact creation timestamp
'visibility': artifact visibility
'type': artifact type
'data_type': artifact data type
'can_be_submitted_to_ebi': if the artifact can be submitted to ebi
'ebi_run_accessions': dict with the EBI run accessions attached to
the artifact
'can_be_submitted_to_vamps': if the artifact can be submitted to
vamps
'is_submitted_to_vamps': whether the artifact has been submitted
to vamps or not
'prep_information': list of prep information ids
'study': the study id
'processing_parameters': dict with the processing parameters used
to generate the artifact or None
'files': dict with the artifact files, keyed by filepath type
"""
with qdb.sql_connection.TRN:
artifact = _get_artifact(artifact_id)
response = {
'filepaths': [(fp, fp_type)
for _, fp, fp_type in artifact.filepaths]}
'name': artifact.name,
'timestamp': str(artifact.timestamp),
'visibility': artifact.visibility,
'type': artifact.artifact_type,
'data_type': artifact.data_type,
'can_be_submitted_to_ebi': artifact.can_be_submitted_to_ebi,
'can_be_submitted_to_vamps':
artifact.can_be_submitted_to_vamps,
'prep_information': [p.id for p in artifact.prep_templates],
'study': artifact.study.id}
params = artifact.processing_parameters
response['processing_parameters'] = (
params.values if params is not None else None)

response['ebi_run_accessions'] = (
artifact.ebi_run_accessions
if response['can_be_submitted_to_ebi'] else None)
response['is_submitted_to_vamps'] = (
artifact.is_submitted_to_vamps
if response['can_be_submitted_to_vamps'] else None)

# Instead of sending a list of files, provide the files as a
# dictionary keyed by filepath type
response['files'] = defaultdict(list)
for _, fp, fp_type in artifact.filepaths:
response['files'][fp_type].append(fp)

self.write(response)

@authenticate_oauth
def patch(self, artifact_id):
"""Patches the filepaths of the artifact
"""Patches the artifact information

Parameter
---------
artifact_id : str
The id of the artifact whose filepaths information is being updated
The id of the artifact whose information is being updated
"""
req_op = self.get_argument('op')
req_path = self.get_argument('path')
Expand All @@ -98,60 +139,41 @@ def patch(self, artifact_id):
self.finish()


class ArtifactMappingHandler(OauthBaseHandler):
class ArtifactAPItestHandler(OauthBaseHandler):
@authenticate_oauth
def get(self, artifact_id):
"""Retrieves the mapping file information of the given artifact
def post(self):
"""Creates a new artifact

Parameters
----------
artifact_id : str
The id of the artifact whose mapping file information is being
retrieved
filepahts : str
Json string with a list of filepaths and its types
type : str
The artifact type
prep_template: int
The id of the template that the new artifact belongs to
name : str, optional
The artifact name

Returns
-------
dict
{'mapping': str}
The filepath to the mapping file
"""
with qdb.sql_connection.TRN:
artifact = _get_artifact(artifact_id)
# In the current system, we don't have any artifact that
# is the result of two other artifacts, and there is no way
# of generating such artifact. This operation will be
# eventually supported, but in interest of time we are not
# going to implement that here.
prep_templates = artifact.prep_templates
if len(prep_templates) > 1:
raise NotImplementedError(
"Artifact %d has more than one prep template")
'artifact': the id of the new artifact

fp = prep_templates[0].qiime_map_fp

response = {'mapping': fp}

self.write(response)


class ArtifactTypeHandler(OauthBaseHandler):
@authenticate_oauth
def get(self, artifact_id):
"""Retrieves the artifact type information of the given artifact
See Also
--------
qiita_db.artifact.Artifact.create
"""
filepaths = loads(self.get_argument('filepaths'))
artifact_type = self.get_argument('type')
prep_template = self.get_argument('prep')
name = self.get_argument('name', None)

Parameters
----------
artifact_id : str
The id of the artifact whose information is being retrieved
if prep_template:
prep_template = qdb.metadata_template.prep_template.PrepTemplate(
prep_template)

Returns
-------
dict
{'type': str}
The artifact type
"""
with qdb.sql_connection.TRN:
artifact = _get_artifact(artifact_id)
response = {'type': artifact.artifact_type}
a = qdb.artifact.Artifact.create(
filepaths, artifact_type, name=name, prep_template=prep_template)

self.write(response)
self.write({'artifact': a.id})
16 changes: 16 additions & 0 deletions qiita_db/handlers/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -----------------------------------------------------------------------------
# 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 .oauth2 import OauthBaseHandler, authenticate_oauth
import qiita_db as qdb


class ResetAPItestHandler(OauthBaseHandler):
@authenticate_oauth
def post(self):
qdb.environment_manager.drop_and_rebuild_tst_database()
123 changes: 123 additions & 0 deletions qiita_db/handlers/prep_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# -----------------------------------------------------------------------------
# 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 json import loads
from os.path import basename

from tornado.web import HTTPError
import pandas as pd

import qiita_db as qdb
from .oauth2 import OauthBaseHandler, authenticate_oauth


def _get_prep_template(pid):
"""Returns the prep template with the given `pid` if it exists

Parameters
----------
pid : str
The prep template id

Returns
-------
qiita_db.metadata_template.prep_template.PrepTemplate
The requested prep template

Raises
------
HTTPError
If the prep template does not exist, with error code 404
If there is a problem instantiating the template, with error code 500
"""
try:
pid = int(pid)
pt = qdb.metadata_template.prep_template.PrepTemplate(pid)
except qdb.exceptions.QiitaDBUnknownIDError:
raise HTTPError(404)
except Exception as e:
raise HTTPError(500, 'Error instantiating prep template %s: %s'
% (pid, str(e)))

return pt


class PrepTemplateDBHandler(OauthBaseHandler):
@authenticate_oauth
def get(self, prep_id):
"""Retrieves the prep template information

Parameters
----------
prep_id: str
The id of the prep template whose information is being retrieved

Returns
-------
dict
The prep information:
'data_type': prep info data type
'artifact': artifact attached to the given prep
'investigation_type': prep info investigation type
'study': study that the prep info belongs to
'status': prep info status
'qiime-map': the path to the qiime mapping file
'prep-file': the path to the prep info file
"""
with qdb.sql_connection.TRN:
pt = _get_prep_template(prep_id)
prep_files = [fp for _, fp in pt.get_filepaths()
if 'qiime' not in basename(fp)]
response = {
'data_type': pt.data_type(),
'artifact': pt.artifact.id,
'investigation_type': pt.investigation_type,
'study': pt.study_id,
'status': pt.status,
'qiime-map': pt.qiime_map_fp,
# The first element in the prep_files is the newest
# prep information file - hence the correct one
'prep-file': prep_files[0]
}

self.write(response)


class PrepTemplateDataHandler(OauthBaseHandler):
@authenticate_oauth
def get(self, prep_id):
"""Retrieves the prep contents

Parameters
----------
prep_id : str
The id of the prep template whose information is being retrieved

Returns
-------
dict
The contents of the prep information keyed by sample id
"""
with qdb.sql_connection.TRN:
pt = _get_prep_template(prep_id)
response = {'data': pt.to_dataframe().to_dict(orient='index')}

self.write(response)


class PrepTemplateAPItestHandler(OauthBaseHandler):
@authenticate_oauth
def post(self):
prep_info_dict = loads(self.get_argument('prep_info'))
study = self.get_argument('study')
data_type = self.get_argument('data_type')

metadata = pd.DataFrame.from_dict(prep_info_dict, orient='index')
pt = qdb.metadata_template.prep_template.PrepTemplate.create(
metadata, qdb.study.Study(study), data_type)
self.write({'prep': pt.id})
Loading