Switch to unified view

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()