136
|
1 import logging
|
|
2 from builtins import (
|
|
3 object,
|
|
4 str
|
|
5 )
|
|
6
|
|
7 from galaxy.tool_util.parser.util import _parse_name
|
|
8
|
|
9 from galaxyxml import Util
|
|
10
|
|
11 from lxml import etree
|
|
12
|
|
13 logging.basicConfig(level=logging.INFO)
|
|
14 logger = logging.getLogger(__name__)
|
|
15
|
|
16
|
|
17 class XMLParam(object):
|
|
18 name = "node"
|
|
19
|
|
20 def __init__(self, *args, **kwargs):
|
|
21 # http://stackoverflow.com/a/12118700
|
|
22 self.children = []
|
|
23 self.parent = None
|
|
24 kwargs = {k: v for k, v in list(kwargs.items()) if v is not None}
|
|
25 kwargs = Util.coerce(kwargs, kill_lists=True)
|
|
26 kwargs = Util.clean_kwargs(kwargs, final=True)
|
|
27 self.node = etree.Element(self.name, **kwargs)
|
|
28
|
|
29 def __getattr__(self, name):
|
|
30 """
|
|
31 Allow to access keys of the node "attributes" (i.e. the dict
|
|
32 self.node.attrib) as attributes.
|
|
33 """
|
|
34 # https://stackoverflow.com/questions/47299243/recursionerror-when-python-copy-deepcopy
|
|
35 if name == "__setstate__":
|
|
36 raise AttributeError(name)
|
|
37 try:
|
|
38 return self.node.attrib[name]
|
|
39 except KeyError:
|
|
40 raise AttributeError(name)
|
|
41
|
|
42 def append(self, sub_node):
|
|
43 if self.acceptable_child(sub_node):
|
|
44 # If one of ours, they aren't etree nodes, they're custom objects
|
|
45 if issubclass(type(sub_node), XMLParam):
|
|
46 self.node.append(sub_node.node)
|
|
47 self.children.append(sub_node)
|
|
48 self.children[-1].parent = self
|
|
49 else:
|
|
50 raise Exception(
|
|
51 "Child was unacceptable to parent (%s is not appropriate for %s)" % (type(self), type(sub_node))
|
|
52 )
|
|
53 else:
|
|
54 raise Exception(
|
|
55 "Child was unacceptable to parent (%s is not appropriate for %s)" % (type(self), type(sub_node))
|
|
56 )
|
|
57
|
|
58 def validate(self):
|
|
59 # Very few need validation, but some nodes we may want to have
|
|
60 # validation routines on. Should only be called when DONE.
|
|
61 for child in self.children:
|
|
62 # If any child fails to validate return false.
|
|
63 if not child.validate():
|
|
64 return False
|
|
65 return True
|
|
66
|
|
67 def cli(self):
|
|
68 lines = []
|
|
69 for child in self.children:
|
|
70 lines.append(child.command_line())
|
|
71 return "\n".join(lines)
|
|
72
|
|
73 def command_line(self, mako_path=None):
|
|
74 """
|
|
75 genetate the command line for the node (and its childres)
|
|
76
|
|
77 mako_path override the path to the node
|
|
78 """
|
|
79 return None
|
|
80
|
|
81
|
|
82 class Stdios(XMLParam):
|
|
83 name = "stdio"
|
|
84
|
|
85 def acceptable_child(self, child):
|
|
86 return isinstance(child, Stdio)
|
|
87
|
|
88
|
|
89 class Stdio(XMLParam):
|
|
90 name = "exit_code"
|
|
91
|
|
92 def __init__(self, range="1:", level="fatal", **kwargs):
|
|
93 params = Util.clean_kwargs(locals().copy())
|
|
94 super(Stdio, self).__init__(**params)
|
|
95
|
|
96
|
|
97 class Macros(XMLParam):
|
|
98 name = "macros"
|
|
99
|
|
100 def acceptable_child(self, child):
|
|
101 return isinstance(child, (Macro, Import))
|
|
102
|
|
103
|
|
104 class Macro(XMLParam):
|
|
105 name = "xml"
|
|
106
|
|
107 def __init__(self, name):
|
|
108 params = Util.clean_kwargs(locals().copy())
|
|
109 passed_kwargs = {}
|
|
110 passed_kwargs['name'] = params['name']
|
|
111 super(Macro, self).__init__(**passed_kwargs)
|
|
112
|
|
113 def acceptable_child(self, child):
|
|
114 return issubclass(type(child), XMLParam) and not isinstance(child, Macro)
|
|
115
|
|
116
|
|
117 class Import(XMLParam):
|
|
118 name = "import"
|
|
119
|
|
120 def __init__(self, value):
|
|
121 super(Import, self).__init__()
|
|
122 self.node.text = value
|
|
123
|
|
124 def acceptable_child(self, child):
|
|
125 return issubclass(type(child), XMLParam) and not isinstance(child, Macro)
|
|
126
|
|
127
|
|
128 class Expand(XMLParam):
|
|
129 """
|
|
130 <expand macro="...">
|
|
131 """
|
|
132 name = "expand"
|
|
133
|
|
134 def __init__(self, macro):
|
|
135 params = Util.clean_kwargs(locals().copy())
|
|
136 passed_kwargs = {}
|
|
137 passed_kwargs['macro'] = params['macro']
|
|
138 super(Expand, self).__init__(**passed_kwargs)
|
|
139
|
|
140 def command_line(self, mako_path=None):
|
|
141 """
|
|
142 need to define empty command line contribution
|
|
143 since Expand can be child of Inputs/Outputs
|
|
144 """
|
|
145 return ""
|
|
146
|
|
147
|
|
148 class ExpandIO(Expand):
|
|
149 """
|
|
150 macro expasion like for Expand
|
|
151 but an additional token with the same name but in upper case is added to
|
|
152 the command section. can only be used in Inputs and Outputs
|
|
153 """
|
|
154 name = "expand"
|
|
155
|
|
156 def __init__(self, macro):
|
|
157 params = Util.clean_kwargs(locals().copy())
|
|
158 passed_kwargs = {}
|
|
159 passed_kwargs['macro'] = params['macro']
|
|
160 super(Expand, self).__init__(**passed_kwargs)
|
|
161
|
|
162 def command_line(self, mako_path=None):
|
|
163 return "@%s@" % self.node.attrib["macro"].upper()
|
|
164
|
|
165
|
|
166 class RequestParamTranslation(XMLParam):
|
|
167 name = "request_param_translation"
|
|
168
|
|
169 def __init__(self, **kwargs):
|
|
170 self.node = etree.Element(self.name)
|
|
171
|
|
172 def acceptable_child(self, child):
|
|
173 return isinstance(child, RequestParamTranslation) \
|
|
174 or isinstance(child, Expand)
|
|
175
|
|
176
|
|
177 class RequestParam(XMLParam):
|
|
178 name = "request_param"
|
|
179
|
|
180 def __init__(self, galaxy_name, remote_name, missing, **kwargs):
|
|
181 # TODO: bulk copy locals into self.attr?
|
|
182 self.galaxy_name = galaxy_name
|
|
183 # http://stackoverflow.com/a/1408860
|
|
184 params = Util.clean_kwargs(locals().copy())
|
|
185 super(RequestParam, self).__init__(**params)
|
|
186
|
|
187 def acceptable_child(self, child):
|
|
188 return isinstance(child, AppendParam) and self.galaxy_name == "URL" \
|
|
189 or isinstance(child, Expand)
|
|
190
|
|
191
|
|
192 class AppendParam(XMLParam):
|
|
193 name = "append_param"
|
|
194
|
|
195 def __init__(self, separator="&", first_separator="?", join="=", **kwargs):
|
|
196 params = Util.clean_kwargs(locals().copy())
|
|
197 super(AppendParam, self).__init__(**params)
|
|
198
|
|
199 def acceptable_child(self, child):
|
|
200 return isinstance(child, AppendParamValue)
|
|
201
|
|
202
|
|
203 class AppendParamValue(XMLParam):
|
|
204 name = "value"
|
|
205
|
|
206 def __init__(self, name="_export", missing="1", **kwargs):
|
|
207 params = Util.clean_kwargs(locals().copy())
|
|
208 super(AppendParamValue, self).__init__(**params)
|
|
209
|
|
210 def acceptable_child(self, child):
|
|
211 return False
|
|
212
|
|
213
|
|
214 class EdamOperations(XMLParam):
|
|
215 name = "edam_operations"
|
|
216
|
|
217 def acceptable_child(self, child):
|
|
218 return issubclass(type(child), EdamOperation) \
|
|
219 or isinstance(child, Expand)
|
|
220
|
|
221 def has_operation(self, edam_operation):
|
|
222 """
|
|
223 Check the presence of a given edam_operation.
|
|
224
|
|
225 :type edam_operation: STRING
|
|
226 """
|
|
227 for operation in self.children:
|
|
228 if operation.node.text == edam_operation:
|
|
229 return True
|
|
230 return False
|
|
231
|
|
232
|
|
233 class EdamOperation(XMLParam):
|
|
234 name = "edam_operation"
|
|
235
|
|
236 def __init__(self, value):
|
|
237 super(EdamOperation, self).__init__()
|
|
238 self.node.text = str(value)
|
|
239
|
|
240
|
|
241 class EdamTopics(XMLParam):
|
|
242 name = "edam_topics"
|
|
243
|
|
244 def acceptable_child(self, child):
|
|
245 return issubclass(type(child), EdamTopic) \
|
|
246 or isinstance(child, Expand)
|
|
247
|
|
248 def has_topic(self, edam_topic):
|
|
249 """
|
|
250 Check the presence of a given edam_topic.
|
|
251
|
|
252 :type edam_topic: STRING
|
|
253 """
|
|
254 for topic in self.children:
|
|
255 if topic.node.text == edam_topic:
|
|
256 return True
|
|
257 return False
|
|
258
|
|
259
|
|
260 class EdamTopic(XMLParam):
|
|
261 name = "edam_topic"
|
|
262
|
|
263 def __init__(self, value):
|
|
264 super(EdamTopic, self).__init__()
|
|
265 self.node.text = str(value)
|
|
266
|
|
267
|
|
268 class Requirements(XMLParam):
|
|
269 name = "requirements"
|
|
270 # This bodes to be an issue -__-
|
|
271
|
|
272 def acceptable_child(self, child):
|
|
273 return issubclass(type(child), Requirement) \
|
|
274 or issubclass(type(child), Container) \
|
|
275 or isinstance(child, Expand)
|
|
276
|
|
277
|
|
278 class Requirement(XMLParam):
|
|
279 name = "requirement"
|
|
280
|
|
281 def __init__(self, type, value, version=None, **kwargs):
|
|
282 params = Util.clean_kwargs(locals().copy())
|
|
283 passed_kwargs = {}
|
|
284 passed_kwargs["version"] = params["version"]
|
|
285 passed_kwargs["type"] = params["type"]
|
|
286 super(Requirement, self).__init__(**passed_kwargs)
|
|
287 self.node.text = str(value)
|
|
288
|
|
289
|
|
290 class Container(XMLParam):
|
|
291 name = "container"
|
|
292
|
|
293 def __init__(self, type, value, **kwargs):
|
|
294 params = Util.clean_kwargs(locals().copy())
|
|
295 passed_kwargs = {}
|
|
296 passed_kwargs["type"] = params["type"]
|
|
297 super(Container, self).__init__(**passed_kwargs)
|
|
298 self.node.text = str(value)
|
|
299
|
|
300
|
|
301 class Configfiles(XMLParam):
|
|
302 name = "configfiles"
|
|
303
|
|
304 def acceptable_child(self, child):
|
|
305 return issubclass(type(child), Configfile) \
|
|
306 or issubclass(type(child), ConfigfileDefaultInputs) \
|
|
307 or isinstance(child, Expand)
|
|
308
|
|
309
|
|
310 class Configfile(XMLParam):
|
|
311 name = "configfile"
|
|
312
|
|
313 def __init__(self, name, text, **kwargs):
|
|
314 params = Util.clean_kwargs(locals().copy())
|
|
315 passed_kwargs = {}
|
|
316 passed_kwargs["name"] = params["name"]
|
|
317 super(Configfile, self).__init__(**passed_kwargs)
|
|
318 self.node.text = etree.CDATA(str(text))
|
|
319
|
|
320
|
|
321 class ConfigfileDefaultInputs(XMLParam):
|
|
322 name = "inputs"
|
|
323
|
|
324 def __init__(self, name, **kwargs):
|
|
325 params = Util.clean_kwargs(locals().copy())
|
|
326 passed_kwargs = {}
|
|
327 passed_kwargs["name"] = params["name"]
|
|
328 super(ConfigfileDefaultInputs, self).__init__(**passed_kwargs)
|
|
329
|
|
330
|
|
331 class Inputs(XMLParam):
|
|
332 name = "inputs"
|
|
333 # This bodes to be an issue -__-
|
|
334
|
|
335 def __init__(self, action=None, check_value=None, method=None, target=None, nginx_upload=None, **kwargs):
|
|
336 params = Util.clean_kwargs(locals().copy())
|
|
337 super(Inputs, self).__init__(**params)
|
|
338
|
|
339 def acceptable_child(self, child):
|
|
340 return issubclass(type(child), InputParameter) \
|
|
341 or issubclass(type(child), Expand) \
|
|
342 or issubclass(type(child), ExpandIO)
|
|
343
|
|
344
|
|
345 class InputParameter(XMLParam):
|
|
346 def __init__(self, name, **kwargs):
|
|
347 # TODO: look at
|
|
348 if "argument" in kwargs and kwargs['argument']:
|
|
349 self.flag_identifier = kwargs['argument'].lstrip()
|
|
350 self.num_dashes = len(kwargs['argument']) - len(self.flag_identifier)
|
|
351 self.mako_identifier = _parse_name(name, kwargs['argument'])
|
|
352 else:
|
|
353 self.flag_identifier = name
|
|
354 self.mako_identifier = name
|
|
355
|
|
356 # We use kwargs instead of the usual locals(), so manually copy the
|
|
357 # name to kwargs
|
|
358 if name is not None:
|
|
359 kwargs = dict([("name", name)] + list(kwargs.items()))
|
|
360
|
|
361 # Handle positional parameters
|
|
362 if "positional" in kwargs and kwargs["positional"]:
|
|
363 self.positional = True
|
|
364 else:
|
|
365 self.positional = False
|
|
366
|
|
367 if "num_dashes" in kwargs:
|
|
368 self.num_dashes = kwargs["num_dashes"]
|
|
369 del kwargs["num_dashes"]
|
|
370 else:
|
|
371 self.num_dashes = 0
|
|
372
|
|
373 self.space_between_arg = " "
|
|
374
|
|
375 # Not sure about this :(
|
|
376 # https://wiki.galaxyproject.org/Tools/BestPractices#Parameter_help
|
|
377 if "label" in kwargs:
|
|
378 # TODO: replace with positional attribute
|
|
379 if len(self.flag()) > 0:
|
|
380 if kwargs["label"] is None:
|
|
381 kwargs["label"] = "Author did not provide help for this parameter... "
|
|
382 # if not self.positional and "argument" not in kwargs:
|
|
383 # kwargs["argument"] = self.flag()
|
|
384
|
|
385 super(InputParameter, self).__init__(**kwargs)
|
|
386
|
|
387 def command_line(self, mako_path=None):
|
|
388 before = self.command_line_before(mako_path)
|
|
389 cli = self.command_line_actual(mako_path)
|
|
390 after = self.command_line_after()
|
|
391
|
|
392 complete = [x for x in (before, cli, after) if x is not None]
|
|
393 return "\n".join(complete)
|
|
394
|
|
395 def command_line_before(self, mako_path):
|
|
396 return None
|
|
397
|
|
398 def command_line_after(self):
|
|
399 return None
|
|
400
|
|
401 def command_line_actual(self, mako_path=None):
|
|
402 try:
|
|
403 return self.command_line_override
|
|
404 except Exception:
|
|
405 if self.positional:
|
|
406 return self.mako_name(mako_path)
|
|
407 else:
|
|
408 return "%s%s%s" % (self.flag(), self.space_between_arg, self.mako_name(mako_path))
|
|
409
|
|
410 def mako_name(self, mako_path=None):
|
|
411 if mako_path:
|
|
412 path = mako_path + "."
|
|
413 else:
|
|
414 parent_identifiers = []
|
|
415 p = self.parent
|
|
416 while p is not None and hasattr(p, "mako_identifier"):
|
|
417 # exclude None identifiers -- e.g. <when> tags
|
|
418 if p.mako_identifier is not None:
|
|
419 parent_identifiers.append(p.mako_identifier)
|
|
420 p = p.parent
|
|
421 if len(parent_identifiers) > 0:
|
|
422 parent_identifiers.append("")
|
|
423 path = ".".join(parent_identifiers)
|
|
424 return "$" + path + self.mako_identifier
|
|
425
|
|
426 def flag(self):
|
|
427 flag = "-" * self.num_dashes
|
|
428 return flag + self.flag_identifier
|
|
429
|
|
430
|
|
431 class Section(InputParameter):
|
|
432 name = "section"
|
|
433
|
|
434 def __init__(self, name, title, expanded=None, help=None, **kwargs):
|
|
435 params = Util.clean_kwargs(locals().copy())
|
|
436 super(Section, self).__init__(**params)
|
|
437
|
|
438 def command_line(self, mako_path=None):
|
|
439 cli = []
|
|
440 for child in self.children:
|
|
441 cli.append(child.command_line(mako_path))
|
|
442 return "\n".join(cli)
|
|
443
|
|
444 def acceptable_child(self, child):
|
|
445 return issubclass(type(child), InputParameter) \
|
|
446 or isinstance(child, Expand)
|
|
447
|
|
448
|
|
449 class Repeat(InputParameter):
|
|
450 name = "repeat"
|
|
451
|
|
452 def __init__(self, name, title, min=None, max=None, default=None, **kwargs):
|
|
453 params = Util.clean_kwargs(locals().copy())
|
|
454 super(Repeat, self).__init__(**params)
|
|
455
|
|
456 def command_line_before(self, mako_path):
|
|
457 return "#for $i_%s in %s" % (self.name, self.mako_name(mako_path))
|
|
458
|
|
459 def command_line_after(self):
|
|
460 return "#end for"
|
|
461
|
|
462 def acceptable_child(self, child):
|
|
463 return issubclass(type(child), InputParameter) \
|
|
464 or isinstance(child, Expand)
|
|
465
|
|
466 def command_line_actual(self, mako_path):
|
|
467 lines = []
|
|
468 for c in self.children:
|
|
469 lines.append(c.command_line(mako_path="i_%s" % self.name))
|
|
470 return "\n".join(lines)
|
|
471
|
|
472
|
|
473 class Conditional(InputParameter):
|
|
474 name = "conditional"
|
|
475
|
|
476 def __init__(self, name, **kwargs):
|
|
477 params = Util.clean_kwargs(locals().copy())
|
|
478 super(Conditional, self).__init__(**params)
|
|
479
|
|
480 def acceptable_child(self, child):
|
|
481 if isinstance(child, Expand):
|
|
482 return True
|
|
483 elif len(self.children) == 0 and issubclass(type(child), SelectParam):
|
|
484 return True
|
|
485 elif len(self.children) > 0 and issubclass(type(child), When):
|
|
486 return True
|
|
487 else:
|
|
488 return False
|
|
489 # return issubclass(type(child), InputParameter) and not isinstance(child, Conditional)
|
|
490
|
|
491 def command_line(self, mako_path=None):
|
|
492 lines = []
|
|
493 for c in self.children[1:]:
|
|
494 if len(c.children) == 0:
|
|
495 continue
|
|
496 lines.append('#if str(%s) == "%s"' % (self.children[0].mako_name(mako_path), c.value))
|
|
497 lines.append(c.cli())
|
|
498 lines.append('#end if')
|
|
499 return "\n".join(lines)
|
|
500
|
|
501 def validate(self):
|
|
502 # Find a way to check if one of the kids is a WHEN
|
|
503 pass
|
|
504
|
|
505
|
|
506 class When(InputParameter):
|
|
507 name = "when"
|
|
508
|
|
509 def __init__(self, value):
|
|
510 params = Util.clean_kwargs(locals().copy())
|
|
511 super(When, self).__init__(None, **params)
|
|
512
|
|
513 def acceptable_child(self, child):
|
|
514 return issubclass(type(child), InputParameter) \
|
|
515 or isinstance(child, Expand)
|
|
516
|
|
517
|
|
518 class Param(InputParameter):
|
|
519 name = "param"
|
|
520
|
|
521 # This...isn't really valid as-is, and shouldn't be used.
|
|
522 def __init__(self, name, argument=None, value=None, optional=None, label=None, help=None, **kwargs):
|
|
523 params = Util.clean_kwargs(locals().copy())
|
|
524 params = dict([("name", params["name"]),
|
|
525 ("argument", params["argument"]),
|
|
526 ("type", self.type)] + list(params.items()))
|
|
527 super(Param, self).__init__(**params)
|
|
528
|
|
529 if type(self) == Param:
|
|
530 raise Exception("Param class is not an actual parameter type, use a subclass of Param")
|
|
531
|
|
532 def acceptable_child(self, child):
|
|
533 return issubclass(type(child), InputParameter) \
|
|
534 or isinstance(child, ValidatorParam) \
|
|
535 or isinstance(child, Expand)
|
|
536
|
|
537
|
|
538 class TextParam(Param):
|
|
539 type = "text"
|
|
540
|
|
541 def __init__(self, name, argument=None, optional=None, value=None, label=None, help=None, **kwargs):
|
|
542 params = Util.clean_kwargs(locals().copy())
|
|
543 super(TextParam, self).__init__(**params)
|
|
544
|
|
545 def command_line_actual(self, mako_path=None):
|
|
546 # TODO same as parent class
|
|
547 try:
|
|
548 return self.command_line_override
|
|
549 except Exception:
|
|
550 if self.positional:
|
|
551 return self.mako_name(mako_path)
|
|
552 else:
|
|
553 return f"{self.flag()}{self.space_between_arg}'{self.mako_name()}'"
|
|
554
|
|
555
|
|
556 class _NumericParam(Param):
|
|
557 def __init__(self, name, value, argument=None, optional=None, min=None, max=None, label=None, help=None, **kwargs):
|
|
558 params = Util.clean_kwargs(locals().copy())
|
|
559 super(_NumericParam, self).__init__(**params)
|
|
560
|
|
561
|
|
562 class IntegerParam(_NumericParam):
|
|
563 type = "integer"
|
|
564
|
|
565
|
|
566 class FloatParam(_NumericParam):
|
|
567 type = "float"
|
|
568
|
|
569
|
|
570 class BooleanParam(Param):
|
|
571 type = "boolean"
|
|
572
|
|
573 def __init__(
|
|
574 self, name, argument=None, optional=None, checked=False, truevalue=None, falsevalue=None, label=None, help=None, **kwargs
|
|
575 ):
|
|
576 params = Util.clean_kwargs(locals().copy())
|
|
577
|
|
578 super(BooleanParam, self).__init__(**params)
|
|
579 if truevalue is None:
|
|
580 # If truevalue and falsevalue are None, then we use "auto", the IUC
|
|
581 # recommended default.
|
|
582 #
|
|
583 # truevalue is set to the parameter's value, and falsevalue is not.
|
|
584 #
|
|
585 # Unfortunately, mako_identifier is set as a result of the super
|
|
586 # call, which we shouldn't call TWICE, so we'll just hack around this :(
|
|
587 # params['truevalue'] = '%s%s' % (self.)
|
|
588 self.node.attrib["truevalue"] = self.flag()
|
|
589
|
|
590 if falsevalue is None:
|
|
591 self.node.attrib["falsevalue"] = ""
|
|
592
|
|
593 def command_line_actual(self, mako_path=None):
|
|
594 if hasattr(self, "command_line_override"):
|
|
595 return self.command_line_override
|
|
596 else:
|
|
597 return "%s" % self.mako_name(mako_path)
|
|
598
|
|
599
|
|
600 class DataParam(Param):
|
|
601 type = "data"
|
|
602
|
|
603 def __init__(self, name, argument=None, optional=None, format=None, multiple=None, label=None, help=None, **kwargs):
|
|
604 params = Util.clean_kwargs(locals().copy())
|
|
605 super(DataParam, self).__init__(**params)
|
|
606
|
|
607
|
|
608 class SelectParam(Param):
|
|
609 type = "select"
|
|
610
|
|
611 def __init__(
|
|
612 self,
|
|
613 name,
|
|
614 argument=None,
|
|
615 optional=None,
|
|
616 data_ref=None,
|
|
617 display=None,
|
|
618 multiple=None,
|
|
619 options=None,
|
|
620 default=None,
|
|
621 label=None,
|
|
622 help=None,
|
|
623 **kwargs,
|
|
624 ):
|
|
625 params = Util.clean_kwargs(locals().copy())
|
|
626 del params["options"]
|
|
627 del params["default"]
|
|
628
|
|
629 super(SelectParam, self).__init__(**params)
|
|
630
|
|
631 if options is not None and default is not None:
|
|
632 if default not in options:
|
|
633 raise Exception("Specified a default that isn't in options")
|
|
634
|
|
635 if options:
|
|
636 for k, v in list(sorted(options.items())):
|
|
637 selected = k == default
|
|
638 self.append(SelectOption(k, v, selected=selected))
|
|
639
|
|
640 def acceptable_child(self, child):
|
|
641 return issubclass(type(child), SelectOption) \
|
|
642 or issubclass(type(child), Options) \
|
|
643 or isinstance(child, Expand)
|
|
644
|
|
645
|
|
646 class SelectOption(InputParameter):
|
|
647 name = "option"
|
|
648
|
|
649 def __init__(self, value, text, selected=False, **kwargs):
|
|
650 params = Util.clean_kwargs(locals().copy())
|
|
651
|
|
652 passed_kwargs = {}
|
|
653 if selected:
|
|
654 passed_kwargs["selected"] = "true"
|
|
655 passed_kwargs["value"] = params["value"]
|
|
656
|
|
657 super(SelectOption, self).__init__(None, **passed_kwargs)
|
|
658 self.node.text = str(text)
|
|
659
|
|
660
|
|
661 class Options(InputParameter):
|
|
662 name = "options"
|
|
663
|
|
664 def __init__(self, from_dataset=None, from_file=None, from_data_table=None, from_parameter=None, **kwargs):
|
|
665 params = Util.clean_kwargs(locals().copy())
|
|
666 super(Options, self).__init__(None, **params)
|
|
667
|
|
668 def acceptable_child(self, child):
|
|
669 return issubclass(type(child), Column) \
|
|
670 or issubclass(type(child), Filter) \
|
|
671 or isinstance(child, Expand)
|
|
672
|
|
673
|
|
674 class Column(InputParameter):
|
|
675 name = "column"
|
|
676
|
|
677 def __init__(self, name, index, **kwargs):
|
|
678 params = Util.clean_kwargs(locals().copy())
|
|
679 super(Column, self).__init__(**params)
|
|
680
|
|
681
|
|
682 class Filter(InputParameter):
|
|
683 name = "filter"
|
|
684
|
|
685 def __init__(
|
|
686 self,
|
|
687 type,
|
|
688 column=None,
|
|
689 name=None,
|
|
690 ref=None,
|
|
691 key=None,
|
|
692 multiple=None,
|
|
693 separator=None,
|
|
694 keep=None,
|
|
695 value=None,
|
|
696 ref_attribute=None,
|
|
697 index=None,
|
|
698 **kwargs,
|
|
699 ):
|
|
700 params = Util.clean_kwargs(locals().copy())
|
|
701 super(Filter, self).__init__(**params)
|
|
702
|
|
703
|
|
704 class ValidatorParam(InputParameter):
|
|
705 name = "validator"
|
|
706
|
|
707 def __init__(
|
|
708 self,
|
|
709 type,
|
|
710 message=None,
|
|
711 filename=None,
|
|
712 metadata_name=None,
|
|
713 metadata_column=None,
|
|
714 line_startswith=None,
|
|
715 min=None,
|
|
716 max=None,
|
|
717 **kwargs,
|
|
718 ):
|
|
719 params = Util.clean_kwargs(locals().copy())
|
|
720 super(ValidatorParam, self).__init__(**params)
|
|
721
|
|
722
|
|
723 class Outputs(XMLParam):
|
|
724 name = "outputs"
|
|
725
|
|
726 def acceptable_child(self, child):
|
|
727 return isinstance(child, OutputData) \
|
|
728 or isinstance(child, OutputCollection) \
|
|
729 or isinstance(child, Expand) \
|
|
730 or isinstance(child, ExpandIO)
|
|
731
|
|
732
|
|
733 class OutputData(XMLParam):
|
|
734 """Copypasta of InputParameter, needs work
|
|
735 """
|
|
736
|
|
737 name = "data"
|
|
738
|
|
739 def __init__(
|
|
740 self,
|
|
741 name,
|
|
742 format,
|
|
743 format_source=None,
|
|
744 metadata_source=None,
|
|
745 label=None,
|
|
746 from_work_dir=None,
|
|
747 hidden=False,
|
|
748 **kwargs,
|
|
749 ):
|
|
750 # TODO: validate format_source&metadata_source against something in the
|
|
751 # XMLParam children tree.
|
|
752 self.mako_identifier = name
|
|
753 if "num_dashes" in kwargs:
|
|
754 self.num_dashes = kwargs["num_dashes"]
|
|
755 del kwargs["num_dashes"]
|
|
756 else:
|
|
757 self.num_dashes = 0
|
|
758 self.space_between_arg = " "
|
|
759 params = Util.clean_kwargs(locals().copy())
|
|
760
|
|
761 super(OutputData, self).__init__(**params)
|
|
762
|
|
763 def command_line(self, mako_path=None):
|
|
764 if hasattr(self, "command_line_override"):
|
|
765 return self.command_line_override
|
|
766 else:
|
|
767 return "%s%s%s" % (self.flag(), self.space_between_arg, self.mako_name(mako_path))
|
|
768
|
|
769 def mako_name(self):
|
|
770 return "'$" + self.mako_identifier + "'"
|
|
771
|
|
772 def flag(self):
|
|
773 flag = "-" * self.num_dashes
|
|
774 return flag + self.mako_identifier
|
|
775
|
|
776 def acceptable_child(self, child):
|
|
777 return isinstance(child, OutputFilter) \
|
|
778 or isinstance(child, ChangeFormat) \
|
|
779 or isinstance(child, DiscoverDatasets) \
|
|
780 or isinstance(child, Expand)
|
|
781
|
|
782
|
|
783 class OutputFilter(XMLParam):
|
|
784 name = "filter"
|
|
785
|
|
786 def __init__(self, text, **kwargs):
|
|
787 params = Util.clean_kwargs(locals().copy())
|
|
788 del params["text"]
|
|
789 super(OutputFilter, self).__init__(**params)
|
|
790 self.node.text = text
|
|
791
|
|
792 def acceptable_child(self, child):
|
|
793 return False
|
|
794
|
|
795
|
|
796 class ChangeFormat(XMLParam):
|
|
797 name = "change_format"
|
|
798
|
|
799 def __init__(self, **kwargs):
|
|
800 params = Util.clean_kwargs(locals().copy())
|
|
801 super(ChangeFormat, self).__init__(**params)
|
|
802
|
|
803 def acceptable_child(self, child):
|
|
804 return isinstance(child, ChangeFormatWhen) \
|
|
805 or isinstance(child, Expand)
|
|
806
|
|
807
|
|
808 class ChangeFormatWhen(XMLParam):
|
|
809 name = "when"
|
|
810
|
|
811 def __init__(self, input, format, value, **kwargs):
|
|
812 params = Util.clean_kwargs(locals().copy())
|
|
813 super(ChangeFormatWhen, self).__init__(**params)
|
|
814
|
|
815 def acceptable_child(self, child):
|
|
816 return False
|
|
817
|
|
818
|
|
819 class OutputCollection(XMLParam):
|
|
820 name = "collection"
|
|
821
|
|
822 def __init__(
|
|
823 self,
|
|
824 name,
|
|
825 type=None,
|
|
826 label=None,
|
|
827 format_source=None,
|
|
828 type_source=None,
|
|
829 structured_like=None,
|
|
830 inherit_format=None,
|
|
831 **kwargs,
|
|
832 ):
|
|
833 params = Util.clean_kwargs(locals().copy())
|
|
834 super(OutputCollection, self).__init__(**params)
|
|
835
|
|
836 def acceptable_child(self, child):
|
|
837 return isinstance(child, OutputData) or isinstance(child, OutputFilter) or isinstance(child, DiscoverDatasets)
|
|
838
|
|
839 def command_line_before(self, mako_path):
|
|
840 return "<output_collection name = '%s'>" % self.name
|
|
841
|
|
842 def command_line_after(self):
|
|
843 return "</output_collection>"
|
|
844
|
|
845 def command_line_actual(self, mako_path):
|
|
846 lines = []
|
|
847 for child in self.children:
|
|
848 lines.append(child.command_line())
|
|
849 return "\n".join(lines)
|
|
850
|
|
851
|
|
852 class DiscoverDatasets(XMLParam):
|
|
853 name = "discover_datasets"
|
|
854
|
|
855 def __init__(self, pattern, directory=None, format=None, ext=None, visible=None, **kwargs):
|
|
856 params = Util.clean_kwargs(locals().copy())
|
|
857 super(DiscoverDatasets, self).__init__(**params)
|
|
858
|
|
859
|
|
860 class Tests(XMLParam):
|
|
861 name = "tests"
|
|
862
|
|
863 def acceptable_child(self, child):
|
|
864 return issubclass(type(child), Test) \
|
|
865 or isinstance(child, Expand)
|
|
866
|
|
867
|
|
868 class Test(XMLParam):
|
|
869 name = "test"
|
|
870
|
|
871 def acceptable_child(self, child):
|
|
872 return isinstance(child, TestParam) \
|
|
873 or isinstance(child, TestOutput) \
|
|
874 or isinstance(child, TestOutputCollection) \
|
|
875 or isinstance(child, TestRepeat) \
|
|
876 or isinstance(child, Expand)
|
|
877
|
|
878
|
|
879 class TestParam(XMLParam):
|
|
880 name = "param"
|
|
881
|
|
882 def __init__(self, name, value=None, ftype=None, dbkey=None, **kwargs):
|
|
883 params = Util.clean_kwargs(locals().copy())
|
|
884 super(TestParam, self).__init__(**params)
|
|
885
|
|
886
|
|
887 class TestOutput(XMLParam):
|
|
888 name = "output"
|
|
889
|
|
890 def __init__(
|
|
891 self,
|
|
892 name=None,
|
|
893 file=None,
|
|
894 ftype=None,
|
|
895 sort=None,
|
|
896 value=None,
|
|
897 md5=None,
|
|
898 checksum=None,
|
|
899 compare=None,
|
|
900 lines_diff=None,
|
|
901 delta=None,
|
|
902 **kwargs,
|
|
903 ):
|
|
904 params = Util.clean_kwargs(locals().copy())
|
|
905 super(TestOutput, self).__init__(**params)
|
|
906
|
|
907
|
|
908 class TestOCElement(XMLParam):
|
|
909 name = "element"
|
|
910
|
|
911 def __init__(self, name=None, file=None, ftype=None, **kwargs):
|
|
912 params = Util.clean_kwargs(locals().copy())
|
|
913 super(TestOCElement, self).__init__(**params)
|
|
914
|
|
915
|
|
916 class TestOutputCollection(XMLParam):
|
|
917 name = "output_collection"
|
|
918
|
|
919 def __init__(
|
|
920 self,
|
|
921 name=None,
|
|
922 ftype=None,
|
|
923 sort=None,
|
|
924 value=None,
|
|
925 compare=None,
|
|
926 lines_diff=None,
|
|
927 delta=None,
|
|
928 **kwargs,
|
|
929 ):
|
|
930 params = Util.clean_kwargs(locals().copy())
|
|
931 super(TestOutputCollection, self).__init__(**params)
|
|
932
|
|
933 def acceptable_child(self, child):
|
|
934 return isinstance(child, TestOCElement)
|
|
935
|
|
936 def command_line_before(self, mako_path):
|
|
937 return "<output_collection name = '%s'>" % self.name
|
|
938
|
|
939 def command_line_after(self):
|
|
940 return "</output_collection>"
|
|
941
|
|
942 def command_line_actual(self, mako_path):
|
|
943 lines = []
|
|
944 for child in self.children:
|
|
945 lines.append(child.command_line())
|
|
946 return "\n".join(lines)
|
|
947
|
|
948
|
|
949 class TestRepeat(XMLParam):
|
|
950 name = "repeat"
|
|
951
|
|
952 def __init__(
|
|
953 self,
|
|
954 name=None,
|
|
955 ftype=None,
|
|
956 sort=None,
|
|
957 value=None,
|
|
958 compare=None,
|
|
959 lines_diff=None,
|
|
960 delta=None,
|
|
961 **kwargs,
|
|
962 ):
|
|
963 params = Util.clean_kwargs(locals().copy())
|
|
964 super(TestRepeat, self).__init__(**params)
|
|
965
|
|
966 def acceptable_child(self, child):
|
|
967 return issubclass(type(child), TestParam) \
|
|
968 or issubclass(type(child), TestOutput) \
|
|
969 or issubclass(type(child), TestOutputCollection)
|
|
970
|
|
971 def command_line_before(self, mako_path):
|
|
972 return "<repeat name = '%s'>" % self.name
|
|
973
|
|
974 def command_line_after(self):
|
|
975 return "</repeat>"
|
|
976
|
|
977 def command_line_actual(self, mako_path):
|
|
978 lines = []
|
|
979 for child in self.children:
|
|
980 lines.append(child.command_line())
|
|
981 return "\n".join(lines)
|
|
982
|
|
983
|
|
984 class Citations(XMLParam):
|
|
985 name = "citations"
|
|
986
|
|
987 def acceptable_child(self, child):
|
|
988 return issubclass(type(child), Citation) \
|
|
989 or isinstance(child, Expand)
|
|
990
|
|
991 def has_citation(self, type, value):
|
|
992 """
|
|
993 Check the presence of a given citation.
|
|
994
|
|
995 :type type: STRING
|
|
996 :type value: STRING
|
|
997 """
|
|
998 for citation in self.children:
|
|
999 if citation.node.attrib['type'] == type \
|
|
1000 and citation.node.text == value:
|
|
1001 return True
|
|
1002 return False
|
|
1003
|
|
1004
|
|
1005 class Citation(XMLParam):
|
|
1006 name = "citation"
|
|
1007
|
|
1008 def __init__(self, type, value):
|
|
1009 passed_kwargs = {}
|
|
1010 passed_kwargs["type"] = type
|
|
1011 super(Citation, self).__init__(**passed_kwargs)
|
|
1012 self.node.text = str(value)
|