Skip to content

Commit 02dbb4d

Browse files
authored
Merge pull request #1960 from josenavas/plugin-installation-activate-cmd
Adds missing bits
2 parents a5d1556 + afc8707 commit 02dbb4d

File tree

11 files changed

+298
-24
lines changed

11 files changed

+298
-24
lines changed

qiita_db/artifact.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,57 @@ def types():
100100
qdb.sql_connection.TRN.add(sql)
101101
return qdb.sql_connection.TRN.execute_fetchindex()
102102

103+
@staticmethod
104+
def create_type(name, description, can_be_submitted_to_ebi,
105+
can_be_submitted_to_vamps, filepath_types):
106+
"""Creates a new artifact type in the system
107+
108+
Parameters
109+
----------
110+
name : str
111+
The artifact type name
112+
description : str
113+
The artifact type description
114+
can_be_submitted_to_ebi : bool
115+
Whether the artifact type can be submitted to EBI or not
116+
can_be_submitted_to_vamps : bool
117+
Whether the artifact type can be submitted to VAMPS or not
118+
filepath_types : list of (str, bool)
119+
The list filepath types that the new artifact type supports, and
120+
if they're required or not in an artifact instance of this type
121+
122+
Raises
123+
------
124+
qiita_db.exceptions.QiitaDBDuplicateError
125+
If an artifact type with the same name already exists
126+
"""
127+
with qdb.sql_connection.TRN:
128+
sql = """SELECT EXISTS(
129+
SELECT *
130+
FROM qiita.artifact_type
131+
WHERE artifact_type=%s)"""
132+
qdb.sql_connection.TRN.add(sql, [name])
133+
if qdb.sql_connection.TRN.execute_fetchlast():
134+
raise qdb.exceptions.QiitaDBDuplicateError(
135+
'artifact type', 'name: %s' % name)
136+
sql = """INSERT INTO qiita.artifact_type
137+
(artifact_type, description, can_be_submitted_to_ebi,
138+
can_be_submitted_to_vamps)
139+
VALUES (%s, %s, %s, %s)
140+
RETURNING artifact_type_id"""
141+
qdb.sql_connection.TRN.add(
142+
sql, [name, description, can_be_submitted_to_ebi,
143+
can_be_submitted_to_vamps])
144+
at_id = qdb.sql_connection.TRN.execute_fetchlast()
145+
sql = """INSERT INTO qiita.artifact_type_filepath_type
146+
(artifact_type_id, filepath_type_id, required)
147+
VALUES (%s, %s, %s)"""
148+
sql_args = [
149+
[at_id, qdb.util.convert_to_id(fpt, 'filepath_type'), req]
150+
for fpt, req in filepath_types]
151+
qdb.sql_connection.TRN.add(sql, sql_args, many=True)
152+
qdb.sql_connection.TRN.execute()
153+
103154
@classmethod
104155
def copy(cls, artifact, prep_template):
105156
"""Creates a copy of `artifact` and attaches it to `prep_template`

qiita_db/handlers/artifact.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,42 @@ def post(self):
177177
filepaths, artifact_type, name=name, prep_template=prep_template)
178178

179179
self.write({'artifact': a.id})
180+
181+
182+
class ArtifactTypeHandler(OauthBaseHandler):
183+
@authenticate_oauth
184+
def post(self):
185+
"""Creates a new artifact type
186+
187+
Parameters
188+
----------
189+
name : str
190+
The artifact type name
191+
description : str
192+
The artifact type description
193+
can_be_submitted_to_ebi : bool
194+
Whether the artifact type can be submitted to EBI or not
195+
can_be_submitted_to_vamps : bool
196+
Whether the artifact type can be submitted to VAMPS or not
197+
filepath_types : list of (str, bool)
198+
The list filepath types that the new artifact type supports, and
199+
if they're required or not in an artifact instance of this type
200+
201+
Raises
202+
------
203+
HTTPError
204+
If the artifact type already exists, with error code 400
205+
"""
206+
a_type = self.get_argument('type_name')
207+
a_desc = self.get_argument('description')
208+
ebi = self.get_argument('can_be_submitted_to_ebi')
209+
vamps = self.get_argument('can_be_submitted_to_vamps')
210+
fp_types = loads(self.get_argument('filepath_types'))
211+
212+
try:
213+
qdb.artifact.Artifact.create_type(a_type, a_desc, ebi, vamps,
214+
fp_types)
215+
except qdb.exceptions.QiitaDBDuplicateError as e:
216+
raise HTTPError(400, str(e))
217+
218+
self.finish()

qiita_db/handlers/plugin.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
# -----------------------------------------------------------------------------
88

99
from json import loads
10+
from glob import glob
11+
from os.path import join
1012

1113
from tornado.web import HTTPError
1214

1315
from .oauth2 import OauthBaseHandler, authenticate_oauth
16+
from qiita_core.qiita_settings import qiita_config
1417
import qiita_db as qdb
1518

1619

@@ -97,17 +100,20 @@ def post(self, name, version):
97100
cmd_desc = self.get_argument('description')
98101
req_params = loads(self.get_argument('required_parameters'))
99102
opt_params = loads(self.get_argument('optional_parameters'))
103+
outputs = self.get_argument('outputs', None)
104+
if outputs:
105+
outputs = loads(outputs)
100106
dflt_param_set = loads(self.get_argument('default_parameter_sets'))
101107

102108
parameters = req_params
103109
parameters.update(opt_params)
104110

105111
cmd = qdb.software.Command.create(
106-
plugin, cmd_name, cmd_desc, parameters)
112+
plugin, cmd_name, cmd_desc, parameters, outputs)
107113

108-
# params = opt_params
109-
for name, vals in dflt_param_set.items():
110-
qdb.software.DefaultParameters.create(name, cmd, **vals)
114+
if dflt_param_set is not None:
115+
for name, vals in dflt_param_set.items():
116+
qdb.software.DefaultParameters.create(name, cmd, **vals)
111117

112118
self.finish()
113119

@@ -184,3 +190,35 @@ def get(self, plugin_name, plugin_version, cmd_name):
184190
'default_parameter_sets': {
185191
p.name: p.values for p in cmd.default_parameter_sets}}
186192
self.write(response)
193+
194+
195+
class CommandActivateHandler(OauthBaseHandler):
196+
@authenticate_oauth
197+
def post(self, plugin_name, plugin_version, cmd_name):
198+
"""Activates the command
199+
200+
Parameters
201+
----------
202+
plugin_name : str
203+
The plugin name
204+
plugin_version : str
205+
The plugin version
206+
cmd_name : str
207+
The command name
208+
"""
209+
with qdb.sql_connection.TRN:
210+
cmd = _get_command(plugin_name, plugin_version, cmd_name)
211+
cmd.activate()
212+
213+
self.finish()
214+
215+
216+
class ReloadPluginAPItestHandler(OauthBaseHandler):
217+
@authenticate_oauth
218+
def post(self):
219+
"""Reloads the plugins"""
220+
conf_files = glob(join(qiita_config.plugin_dir, "*.conf"))
221+
for fp in conf_files:
222+
s = qdb.software.Software.from_file(fp, update=True)
223+
s.activate()
224+
self.finish()

qiita_db/handlers/processing_job.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,14 @@ class ProcessingJobAPItestHandler(OauthBaseHandler):
153153
@authenticate_oauth
154154
def post(self):
155155
user = self.get_argument('user', 'test@foo.bar')
156-
cmd = self.get_argument('command')
156+
s_name, s_version, cmd_name = loads(self.get_argument('command'))
157157
params_dict = self.get_argument('parameters')
158158
status = self.get_argument('status', None)
159159

160-
params = qdb.software.Parameters.load(
161-
qdb.software.Command(cmd),
162-
json_str=params_dict)
160+
cmd = qdb.software.Software.from_name_and_version(
161+
s_name, s_version).get_command(cmd_name)
162+
163+
params = qdb.software.Parameters.load(cmd, json_str=params_dict)
163164

164165
job = qdb.processing_job.ProcessingJob.create(
165166
qdb.user.User(user), params)

qiita_db/handlers/tests/test_artifact.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,5 +191,28 @@ def test_post_error(self):
191191
obs.body)
192192

193193

194+
class ArtifactTypeHandlerTests(OauthTestingBase):
195+
def test_post_no_header(self):
196+
obs = self.post('/qiita_db/artifacts/types/', data={})
197+
self.assertEqual(obs.code, 400)
198+
199+
def test_post(self):
200+
data = {'type_name': 'new_type',
201+
'description': 'some_description',
202+
'can_be_submitted_to_ebi': False,
203+
'can_be_submitted_to_vamps': False,
204+
'filepath_types': dumps([("log", False),
205+
("raw_forward_seqs", True)])}
206+
obs = self.post('/qiita_db/artifacts/types/', headers=self.header,
207+
data=data)
208+
self.assertEqual(obs.code, 200)
209+
self.assertIn(['new_type', 'some_description'],
210+
qdb.artifact.Artifact.types())
211+
212+
obs = self.post('/qiita_db/artifacts/types/', headers=self.header,
213+
data=data)
214+
self.assertEqual(obs.code, 400)
215+
self.assertIn('already exists', obs.body)
216+
194217
if __name__ == '__main__':
195218
main()

qiita_db/handlers/tests/test_plugin.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ def test_post(self):
7777
'optional_parameters': dumps({'param1': ['string', ''],
7878
'param2': ['float', '1.5'],
7979
'param3': ['boolean', 'True']}),
80+
'outputs': dumps({'out1': 'BIOM'}),
8081
'default_parameter_sets': dumps(
8182
{'dflt1': {'param1': 'test',
8283
'param2': '2.4',
@@ -164,5 +165,37 @@ def test_get(self):
164165
self.assertEqual(loads(obs.body), exp)
165166

166167

168+
class CommandActivateHandlerTests(OauthTestingBase):
169+
def test_post_command_does_not_exist(self):
170+
obs = self.post('/qiita_db/plugins/QIIME/1.9.1/commands/'
171+
'UNKNOWN/activate/',
172+
headers=self.header, data={})
173+
self.assertEqual(obs.code, 404)
174+
175+
def test_post_no_header(self):
176+
obs = self.post('/qiita_db/plugins/QIIME/1.9.1/commands/'
177+
'Split%20libraries/activate/', data={})
178+
self.assertEqual(obs.code, 400)
179+
180+
def test_post(self):
181+
qdb.software.Software.deactivate_all()
182+
self.assertFalse(qdb.software.Command(2).active)
183+
obs = self.post('/qiita_db/plugins/QIIME/1.9.1/commands/'
184+
'Split%20libraries/activate/', headers=self.header,
185+
data={})
186+
self.assertEqual(obs.code, 200)
187+
self.assertTrue(qdb.software.Command(2).active)
188+
189+
190+
class ReloadPluginAPItestHandlerTests(OauthTestingBase):
191+
def test_post_no_header(self):
192+
obs = self.post('/apitest/reload_plugins/', data={})
193+
self.assertEqual(obs.code, 400)
194+
195+
def test_post(self):
196+
obs = self.post('/apitest/reload_plugins/', headers=self.header,
197+
data={})
198+
self.assertEqual(obs.code, 200)
199+
167200
if __name__ == '__main__':
168201
main()

qiita_db/handlers/tests/test_processing_job.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ class ProcessingJobAPItestHandlerTests(OauthTestingBase):
204204
def test_post_processing_job(self):
205205
data = {
206206
'user': 'demo@microbio.me',
207-
'command': 3,
207+
'command': dumps(['QIIME', '1.9.1', 'Pick closed-reference OTUs']),
208208
'parameters': dumps({"reference": 1,
209209
"sortmerna_e_value": 1,
210210
"sortmerna_max_pos": 10000,
@@ -225,7 +225,7 @@ def test_post_processing_job(self):
225225
def test_post_processing_job_status(self):
226226
data = {
227227
'user': 'demo@microbio.me',
228-
'command': 3,
228+
'command': dumps(['QIIME', '1.9.1', 'Pick closed-reference OTUs']),
229229
'status': 'running',
230230
'parameters': dumps({"reference": 1,
231231
"sortmerna_e_value": 1,

qiita_db/software.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def exists(cls, software, name):
147147
return qdb.sql_connection.TRN.execute_fetchlast()
148148

149149
@classmethod
150-
def create(cls, software, name, description, parameters):
150+
def create(cls, software, name, description, parameters, outputs=None):
151151
r"""Creates a new command in the system
152152
153153
The supported types for the parameters are:
@@ -175,6 +175,9 @@ def create(cls, software, name, description, parameters):
175175
format is: {parameter_name: (parameter_type, default)},
176176
where parameter_name, parameter_type and default are strings. If
177177
default is None.
178+
outputs : dict, optional
179+
The description of the outputs that this command generated. The
180+
format is: {output_name: artifact_type}
178181
179182
Returns
180183
-------
@@ -216,7 +219,7 @@ def create(cls, software, name, description, parameters):
216219
ptype, dflt = vals
217220
# Check that the type is one of the supported types
218221
supported_types = ['string', 'integer', 'float', 'reference',
219-
'boolean']
222+
'boolean', 'prep_template']
220223
if ptype not in supported_types and not ptype.startswith(
221224
('choice', 'artifact')):
222225
supported_types.extend(['choice', 'artifact'])
@@ -281,6 +284,17 @@ def create(cls, software, name, description, parameters):
281284
for at in atypes]
282285
qdb.sql_connection.TRN.add(sql_type, sql_params, many=True)
283286

287+
# Add the outputs to the command
288+
if outputs:
289+
sql = """INSERT INTO qiita.command_output
290+
(name, command_id, artifact_type_id)
291+
VALUES (%s, %s, %s)"""
292+
sql_args = [
293+
[pname, c_id, qdb.util.convert_to_id(at, 'artifact_type')]
294+
for pname, at in outputs.items()]
295+
qdb.sql_connection.TRN.add(sql, sql_args, many=True)
296+
qdb.sql_connection.TRN.execute()
297+
284298
return cls(c_id)
285299

286300
@property
@@ -425,6 +439,31 @@ def outputs(self):
425439
qdb.sql_connection.TRN.add(sql, [self.id])
426440
return qdb.sql_connection.TRN.execute_fetchindex()
427441

442+
@property
443+
def active(self):
444+
"""Returns if the command is active or not
445+
446+
Returns
447+
-------
448+
bool
449+
Whether the command is active or not
450+
"""
451+
with qdb.sql_connection.TRN:
452+
sql = """SELECT active
453+
FROM qiita.software_command
454+
WHERE command_id = %s"""
455+
qdb.sql_connection.TRN.add(sql, [self.id])
456+
return qdb.sql_connection.TRN.execute_fetchlast()
457+
458+
def activate(self):
459+
"""Activates the command"""
460+
with qdb.sql_connection.TRN:
461+
sql = """UPDATE qiita.software_command
462+
SET active = %s
463+
WHERE command_id = %s"""
464+
qdb.sql_connection.TRN.add(sql, [True, self.id])
465+
return qdb.sql_connection.TRN.execute()
466+
428467

429468
class Software(qdb.base.QiitaObject):
430469
r"""A software package available in the system
@@ -456,6 +495,8 @@ def deactivate_all(cls):
456495
with qdb.sql_connection.TRN:
457496
sql = "UPDATE qiita.software SET active = False"
458497
qdb.sql_connection.TRN.add(sql)
498+
sql = "UPDATE qiita.software_command SET active = False"
499+
qdb.sql_connection.TRN.add(sql)
459500
qdb.sql_connection.TRN.execute()
460501

461502
@classmethod

0 commit comments

Comments
 (0)