|
a |
|
b/qiita_db/handlers/plugin.py |
|
|
1 |
# ----------------------------------------------------------------------------- |
|
|
2 |
# Copyright (c) 2014--, The Qiita Development Team. |
|
|
3 |
# |
|
|
4 |
# Distributed under the terms of the BSD 3-clause License. |
|
|
5 |
# |
|
|
6 |
# The full license is in the file LICENSE, distributed with this software. |
|
|
7 |
# ----------------------------------------------------------------------------- |
|
|
8 |
|
|
|
9 |
from json import loads |
|
|
10 |
from glob import glob |
|
|
11 |
from os.path import join |
|
|
12 |
|
|
|
13 |
from tornado.web import HTTPError |
|
|
14 |
|
|
|
15 |
from .oauth2 import OauthBaseHandler, authenticate_oauth |
|
|
16 |
from qiita_core.qiita_settings import qiita_config |
|
|
17 |
import qiita_db as qdb |
|
|
18 |
|
|
|
19 |
|
|
|
20 |
def _get_plugin(name, version): |
|
|
21 |
"""Returns the plugin with the given name and version |
|
|
22 |
|
|
|
23 |
Parameters |
|
|
24 |
---------- |
|
|
25 |
name : str |
|
|
26 |
The name of the plugin |
|
|
27 |
version : str |
|
|
28 |
The version of the plugin |
|
|
29 |
|
|
|
30 |
Returns |
|
|
31 |
------- |
|
|
32 |
qiita_db.software.Software |
|
|
33 |
The requested plugin |
|
|
34 |
|
|
|
35 |
Raises |
|
|
36 |
------ |
|
|
37 |
HTTPError |
|
|
38 |
If the plugin does not exist, with error code 404 |
|
|
39 |
If there is a problem instantiating the plugin, with error code 500 |
|
|
40 |
""" |
|
|
41 |
try: |
|
|
42 |
plugin = qdb.software.Software.from_name_and_version(name, version) |
|
|
43 |
except qdb.exceptions.QiitaDBUnknownIDError: |
|
|
44 |
raise HTTPError(404) |
|
|
45 |
except Exception as e: |
|
|
46 |
raise HTTPError(500, reason='Error instantiating plugin %s %s: %s' |
|
|
47 |
% (name, version, str(e))) |
|
|
48 |
|
|
|
49 |
return plugin |
|
|
50 |
|
|
|
51 |
|
|
|
52 |
class PluginHandler(OauthBaseHandler): |
|
|
53 |
@authenticate_oauth |
|
|
54 |
def get(self, name, version): |
|
|
55 |
"""Retrieve the plugin information |
|
|
56 |
|
|
|
57 |
Parameters |
|
|
58 |
---------- |
|
|
59 |
name : str |
|
|
60 |
The plugin name |
|
|
61 |
version : str |
|
|
62 |
The plugin version |
|
|
63 |
|
|
|
64 |
Returns |
|
|
65 |
------- |
|
|
66 |
dict |
|
|
67 |
The plugin information: |
|
|
68 |
'name': the plugin name |
|
|
69 |
'version': the plugin version |
|
|
70 |
'description': the plugin description |
|
|
71 |
'commands': list of the plugin commands |
|
|
72 |
'publications': list of publications |
|
|
73 |
'default_workflows': list of the plugin default workflows |
|
|
74 |
'type': the plugin type |
|
|
75 |
'active': whether the plugin is active or not |
|
|
76 |
""" |
|
|
77 |
with qdb.sql_connection.TRN: |
|
|
78 |
plugin = _get_plugin(name, version) |
|
|
79 |
response = { |
|
|
80 |
'name': plugin.name, |
|
|
81 |
'version': plugin.version, |
|
|
82 |
'description': plugin.description, |
|
|
83 |
'commands': [c.name for c in plugin.commands], |
|
|
84 |
'publications': [{'DOI': doi, 'PubMed': pubmed} |
|
|
85 |
for doi, pubmed in plugin.publications], |
|
|
86 |
'type': plugin.type, |
|
|
87 |
'active': plugin.active} |
|
|
88 |
self.write(response) |
|
|
89 |
|
|
|
90 |
|
|
|
91 |
class CommandListHandler(OauthBaseHandler): |
|
|
92 |
@authenticate_oauth |
|
|
93 |
def post(self, name, version): |
|
|
94 |
"""Create new command for a plugin |
|
|
95 |
|
|
|
96 |
Parameters |
|
|
97 |
---------- |
|
|
98 |
name : str |
|
|
99 |
The name of the plugin |
|
|
100 |
version : str |
|
|
101 |
The version of the plugin |
|
|
102 |
""" |
|
|
103 |
with qdb.sql_connection.TRN: |
|
|
104 |
plugin = _get_plugin(name, version) |
|
|
105 |
|
|
|
106 |
cmd_name = self.get_argument('name') |
|
|
107 |
cmd_desc = self.get_argument('description') |
|
|
108 |
req_params = loads(self.get_argument('required_parameters')) |
|
|
109 |
opt_params = loads(self.get_argument('optional_parameters')) |
|
|
110 |
|
|
|
111 |
for p_name, vals in opt_params.items(): |
|
|
112 |
if vals[0].startswith('mchoice'): |
|
|
113 |
opt_params[p_name] = [vals[0], loads(vals[1])] |
|
|
114 |
if len(vals) == 2: |
|
|
115 |
opt_params[p_name] = [vals[0], loads(vals[1])] |
|
|
116 |
elif len(vals) == 4: |
|
|
117 |
opt_params[p_name] = [vals[0], loads(vals[1]), vals[2], |
|
|
118 |
vals[3]] |
|
|
119 |
else: |
|
|
120 |
raise qdb.exceptions.QiitaDBError( |
|
|
121 |
"Malformed parameters dictionary, the format " |
|
|
122 |
"should be either {param_name: [parameter_type, " |
|
|
123 |
"default]} or {parameter_name: (parameter_type, " |
|
|
124 |
"default, name_order, check_biom_merge)}. Found: " |
|
|
125 |
"%s for parameter name %s" |
|
|
126 |
% (vals, p_name)) |
|
|
127 |
# adding an extra element to make sure the parser knows this is |
|
|
128 |
# an optional parameter |
|
|
129 |
opt_params[p_name].extend(['qiita_optional_parameter']) |
|
|
130 |
|
|
|
131 |
outputs = self.get_argument('outputs', None) |
|
|
132 |
if outputs: |
|
|
133 |
outputs = loads(outputs) |
|
|
134 |
dflt_param_set = loads(self.get_argument('default_parameter_sets')) |
|
|
135 |
analysis_only = self.get_argument('analysis_only', False) |
|
|
136 |
|
|
|
137 |
parameters = req_params |
|
|
138 |
parameters.update(opt_params) |
|
|
139 |
|
|
|
140 |
cmd = qdb.software.Command.create( |
|
|
141 |
plugin, cmd_name, cmd_desc, parameters, outputs, |
|
|
142 |
analysis_only=analysis_only) |
|
|
143 |
|
|
|
144 |
if dflt_param_set is not None: |
|
|
145 |
for name, vals in dflt_param_set.items(): |
|
|
146 |
qdb.software.DefaultParameters.create(name, cmd, **vals) |
|
|
147 |
|
|
|
148 |
self.finish() |
|
|
149 |
|
|
|
150 |
|
|
|
151 |
def _get_command(plugin_name, plugin_version, cmd_name): |
|
|
152 |
"""Returns the command with the given name within the given plugin |
|
|
153 |
|
|
|
154 |
Parameters |
|
|
155 |
---------- |
|
|
156 |
plugin_name : str |
|
|
157 |
The name of the plugin |
|
|
158 |
plugin_version : str |
|
|
159 |
The version of the plugin |
|
|
160 |
cmd_name : str |
|
|
161 |
The name of the command in the plugin |
|
|
162 |
|
|
|
163 |
Returns |
|
|
164 |
------- |
|
|
165 |
qiita_db.software.Command |
|
|
166 |
The requested command |
|
|
167 |
|
|
|
168 |
Raises |
|
|
169 |
------ |
|
|
170 |
HTTPError |
|
|
171 |
If the command does not exist, with error code 404 |
|
|
172 |
If there is a problem instantiating the command, with error code 500 |
|
|
173 |
""" |
|
|
174 |
plugin = _get_plugin(plugin_name, plugin_version) |
|
|
175 |
try: |
|
|
176 |
cmd = plugin.get_command(cmd_name) |
|
|
177 |
except qdb.exceptions.QiitaDBUnknownIDError: |
|
|
178 |
raise HTTPError(404) |
|
|
179 |
except Exception as e: |
|
|
180 |
raise HTTPError(500, reason='Error instantiating cmd %s of plugin ' |
|
|
181 |
'%s %s: %s' % (cmd_name, plugin_name, |
|
|
182 |
plugin_version, str(e))) |
|
|
183 |
|
|
|
184 |
return cmd |
|
|
185 |
|
|
|
186 |
|
|
|
187 |
class CommandHandler(OauthBaseHandler): |
|
|
188 |
@authenticate_oauth |
|
|
189 |
def get(self, plugin_name, plugin_version, cmd_name): |
|
|
190 |
"""Retrieve the command information |
|
|
191 |
|
|
|
192 |
Parameters |
|
|
193 |
---------- |
|
|
194 |
plugin_name : str |
|
|
195 |
The plugin name |
|
|
196 |
plugin_version : str |
|
|
197 |
The plugin version |
|
|
198 |
cmd_name : str |
|
|
199 |
The command name |
|
|
200 |
|
|
|
201 |
Returns |
|
|
202 |
------- |
|
|
203 |
dict |
|
|
204 |
The command information |
|
|
205 |
'name': the command name |
|
|
206 |
'description': the command description |
|
|
207 |
'required_parameters': dict with the required parameters, in the |
|
|
208 |
format {parameter_name: [type, [subtypes]]} |
|
|
209 |
'optional_parameters': dict with the optional parameters, in the |
|
|
210 |
format {parameter_name: [type, default value]} |
|
|
211 |
'default_parameter_sets': dict with the default parameter sets, in |
|
|
212 |
the format {parameter set name: {parameter_name: value}} |
|
|
213 |
""" |
|
|
214 |
with qdb.sql_connection.TRN: |
|
|
215 |
cmd = _get_command(plugin_name, plugin_version, cmd_name) |
|
|
216 |
response = { |
|
|
217 |
'name': cmd.name, |
|
|
218 |
'description': cmd.description, |
|
|
219 |
'required_parameters': cmd.required_parameters, |
|
|
220 |
'optional_parameters': cmd.optional_parameters, |
|
|
221 |
'default_parameter_sets': { |
|
|
222 |
p.name: p.values for p in cmd.default_parameter_sets}, |
|
|
223 |
'outputs': cmd.outputs} |
|
|
224 |
self.write(response) |
|
|
225 |
|
|
|
226 |
|
|
|
227 |
class CommandActivateHandler(OauthBaseHandler): |
|
|
228 |
@authenticate_oauth |
|
|
229 |
def post(self, plugin_name, plugin_version, cmd_name): |
|
|
230 |
"""Activates the command |
|
|
231 |
|
|
|
232 |
Parameters |
|
|
233 |
---------- |
|
|
234 |
plugin_name : str |
|
|
235 |
The plugin name |
|
|
236 |
plugin_version : str |
|
|
237 |
The plugin version |
|
|
238 |
cmd_name : str |
|
|
239 |
The command name |
|
|
240 |
""" |
|
|
241 |
with qdb.sql_connection.TRN: |
|
|
242 |
cmd = _get_command(plugin_name, plugin_version, cmd_name) |
|
|
243 |
cmd.activate() |
|
|
244 |
|
|
|
245 |
self.finish() |
|
|
246 |
|
|
|
247 |
|
|
|
248 |
class ReloadPluginAPItestHandler(OauthBaseHandler): |
|
|
249 |
@authenticate_oauth |
|
|
250 |
def post(self): |
|
|
251 |
"""Reloads the plugins""" |
|
|
252 |
conf_files = sorted(glob(join(qiita_config.plugin_dir, "*.conf"))) |
|
|
253 |
software = set([qdb.software.Software.from_file(fp, update=True) |
|
|
254 |
for fp in conf_files]) |
|
|
255 |
definition = set( |
|
|
256 |
[s for s in software if s.type == 'artifact definition']) |
|
|
257 |
transformation = software - definition |
|
|
258 |
for s in definition: |
|
|
259 |
s.activate() |
|
|
260 |
s.register_commands() |
|
|
261 |
for s in transformation: |
|
|
262 |
s.activate() |
|
|
263 |
s.register_commands() |
|
|
264 |
|
|
|
265 |
self.finish() |