136
|
1 import copy
|
|
2 import logging
|
|
3
|
|
4 from galaxyxml import GalaxyXML, Util
|
|
5 from galaxyxml.tool.parameters import (
|
|
6 Expand,
|
|
7 Import,
|
|
8 Inputs,
|
|
9 Macro,
|
|
10 Macros,
|
|
11 Outputs,
|
|
12 XMLParam
|
|
13 )
|
|
14
|
|
15 from lxml import etree
|
|
16
|
|
17 VALID_TOOL_TYPES = ("data_source", "data_source_async")
|
|
18 VALID_URL_METHODS = ("get", "post")
|
|
19
|
|
20 logging.basicConfig(level=logging.INFO)
|
|
21 logger = logging.getLogger(__name__)
|
|
22
|
|
23
|
|
24 class Tool(GalaxyXML):
|
|
25 def __init__(
|
|
26 self,
|
|
27 name,
|
|
28 id,
|
|
29 version,
|
|
30 description,
|
|
31 executable,
|
|
32 hidden=False,
|
|
33 tool_type=None,
|
|
34 URL_method=None,
|
|
35 workflow_compatible=True,
|
|
36 interpreter=None,
|
|
37 version_command="interpreter filename.exe --version",
|
|
38 command_override=None,
|
|
39 macros=[],
|
|
40 ):
|
|
41
|
|
42 self.id = id
|
|
43 self.executable = executable
|
|
44 self.interpreter = interpreter
|
|
45 self.command_override = command_override
|
|
46 kwargs = {
|
|
47 "name": name,
|
|
48 "id": id,
|
|
49 "version": version,
|
|
50 "hidden": hidden,
|
|
51 "workflow_compatible": workflow_compatible,
|
|
52 }
|
|
53 self.version_command = version_command
|
|
54
|
|
55 # Remove some of the default values to make tools look a bit nicer
|
|
56 if not hidden:
|
|
57 del kwargs["hidden"]
|
|
58 if workflow_compatible:
|
|
59 del kwargs["workflow_compatible"]
|
|
60
|
|
61 kwargs = Util.coerce(kwargs)
|
|
62 self.root = etree.Element("tool", **kwargs)
|
|
63
|
|
64 if tool_type is not None:
|
|
65 if tool_type not in VALID_TOOL_TYPES:
|
|
66 raise Exception("Tool type must be one of %s" % ",".join(VALID_TOOL_TYPES))
|
|
67 else:
|
|
68 kwargs["tool_type"] = tool_type
|
|
69
|
|
70 if URL_method is not None:
|
|
71 if URL_method in VALID_URL_METHODS:
|
|
72 kwargs["URL_method"] = URL_method
|
|
73 else:
|
|
74 raise Exception("URL_method must be one of %s" % ",".join(VALID_URL_METHODS))
|
|
75
|
|
76 description_node = etree.SubElement(self.root, "description")
|
|
77 description_node.text = description
|
|
78 if len(macros) > 0:
|
|
79 self.macros = Macros()
|
|
80 for m in macros:
|
|
81 self.macros.append(Import(m))
|
|
82 self.inputs = Inputs()
|
|
83 self.outputs = Outputs()
|
|
84
|
|
85 def add_comment(self, comment_txt):
|
|
86 comment = etree.Comment(comment_txt)
|
|
87 self.root.insert(0, comment)
|
|
88
|
|
89 def append_version_command(self):
|
|
90 version_command = etree.SubElement(self.root, "version_command")
|
|
91 try:
|
|
92 version_command.text = etree.CDATA(self.version_command)
|
|
93 except Exception:
|
|
94 pass
|
|
95
|
|
96 def append(self, sub_node):
|
|
97 if issubclass(type(sub_node), XMLParam):
|
|
98 self.root.append(sub_node.node)
|
|
99 else:
|
|
100 self.root.append(sub_node)
|
|
101
|
|
102 def clean_command_string(self, command_line):
|
|
103 clean = []
|
|
104 for x in command_line:
|
|
105 if x is not [] and x is not [""]:
|
|
106 clean.append(x)
|
|
107 return "\n".join(clean)
|
|
108
|
|
109 def export(self, keep_old_command=False):
|
|
110 # see lib/galaxy/tool_util/linters/xml_order.py
|
|
111 export_xml = copy.deepcopy(self)
|
|
112 try:
|
|
113 export_xml.append(export_xml.macros)
|
|
114 except Exception:
|
|
115 pass
|
|
116
|
|
117 try:
|
|
118 export_xml.append(export_xml.edam_operations)
|
|
119 except Exception:
|
|
120 pass
|
|
121
|
|
122 try:
|
|
123 export_xml.append(export_xml.edam_topics)
|
|
124 except Exception:
|
|
125 pass
|
|
126
|
|
127 try:
|
|
128 export_xml.append(export_xml.requirements)
|
|
129 except Exception:
|
|
130 export_xml.append(Expand(macro="requirements"))
|
|
131
|
|
132 # Add stdio section - now an XMLParameter
|
|
133 try:
|
|
134 stdio_element = export_xml.stdios
|
|
135 except Exception:
|
|
136 stdio_element = None
|
|
137 if not stdio_element:
|
|
138 stdio_element = etree.SubElement(export_xml.root, "stdio")
|
|
139 etree.SubElement(stdio_element, "exit_code", range="1:", level="fatal")
|
|
140 try:
|
|
141 export_xml.append(stdio_element)
|
|
142 except Exception:
|
|
143 export_xml.append(Expand(macro="stdio"))
|
|
144
|
|
145 # Append version command
|
|
146 export_xml.append_version_command()
|
|
147
|
|
148 if self.command_override:
|
|
149 command_line = self.command_override
|
|
150 else:
|
|
151 command_line = []
|
|
152 try:
|
|
153 command_line.append(export_xml.inputs.cli())
|
|
154 except Exception as e:
|
|
155 logger.warning(str(e))
|
|
156 raise
|
|
157 try:
|
|
158 command_line.append(export_xml.outputs.cli())
|
|
159 except Exception:
|
|
160 pass
|
|
161 # Steal interpreter from kwargs
|
|
162 command_kwargs = {}
|
|
163 if export_xml.interpreter is not None:
|
|
164 command_kwargs["interpreter"] = export_xml.interpreter
|
|
165 # Add command section
|
|
166 command_node = etree.SubElement(export_xml.root, "command", **command_kwargs)
|
|
167 if keep_old_command:
|
|
168 if getattr(self, "command", None):
|
|
169 command_node.text = etree.CDATA(export_xml.command)
|
|
170 else:
|
|
171 logger.warning("The tool does not have any old command stored. Only the command line is written.")
|
|
172 command_node.text = export_xml.executable
|
|
173 else:
|
|
174 if self.command_override:
|
|
175 actual_cli = export_xml.clean_command_string(command_line)
|
|
176 else:
|
|
177 actual_cli = "%s %s" % (export_xml.executable, export_xml.clean_command_string(command_line),)
|
|
178 command_node.text = etree.CDATA(actual_cli.strip())
|
|
179 export_xml.append(command_node)
|
|
180
|
|
181 try:
|
|
182 export_xml.append(export_xml.configfiles)
|
|
183 except Exception:
|
|
184 pass
|
|
185
|
|
186 try:
|
|
187 export_xml.append(export_xml.inputs)
|
|
188 except Exception:
|
|
189 pass
|
|
190 try:
|
|
191 export_xml.append(export_xml.outputs)
|
|
192 except Exception:
|
|
193 pass
|
|
194
|
|
195 try:
|
|
196 export_xml.append(export_xml.tests)
|
|
197 except Exception:
|
|
198 export_xml.append(Expand(macro="%s_tests" % self.id))
|
|
199
|
|
200 help_element = etree.SubElement(export_xml.root, "help")
|
|
201 help_element.text = etree.CDATA(export_xml.help)
|
|
202 export_xml.append(help_element)
|
|
203
|
|
204 try:
|
|
205 export_xml.append(export_xml.citations)
|
|
206 except Exception:
|
|
207 export_xml.append(Expand(macro="citations"))
|
|
208
|
|
209 return super(Tool, export_xml).export()
|
|
210
|
|
211
|
|
212 class MacrosTool(Tool):
|
|
213 """
|
|
214 creates a <macros> tag containing macros and tokens
|
|
215 for the inputs and outputs:
|
|
216
|
|
217 for the inputs
|
|
218
|
|
219 - a macro `<xml name="ID_inmacro">` containing all the inputs
|
|
220 - a token `<token name="ID_INMACRO">` containing the CLI for the inputs
|
|
221
|
|
222 where ID is the id used in initialization.
|
|
223
|
|
224 analogously for the outputs `ID_outmacro` and `ID_OUTMACRO`
|
|
225 are created.
|
|
226
|
|
227 TODO all other elements, like requirements are currently ignored
|
|
228 """
|
|
229 def __init__(self, *args, **kwargs):
|
|
230 super(MacrosTool, self).__init__(*args, **kwargs)
|
|
231 self.root = etree.Element('macros')
|
|
232 self.inputs = Macro("%s_inmacro" % self.id)
|
|
233 self.outputs = Macro("%s_outmacro" % self.id)
|
|
234
|
|
235
|
|
236 def export(self, keep_old_command=False): # noqa
|
|
237
|
|
238 export_xml = copy.deepcopy(self)
|
|
239
|
|
240 try:
|
|
241 for child in export_xml.macros:
|
|
242 export_xml.append(child)
|
|
243 except Exception:
|
|
244 pass
|
|
245
|
|
246 command_line = []
|
|
247 try:
|
|
248 command_line.append(export_xml.inputs.cli())
|
|
249 except Exception as e:
|
|
250 logger.warning(str(e))
|
|
251 raise
|
|
252
|
|
253 # Add command section
|
|
254 command_node = etree.SubElement(export_xml.root, 'token', {"name": "%s_INMACRO" % self.id.upper()})
|
|
255 actual_cli = "%s" % (export_xml.clean_command_string(command_line))
|
|
256 command_node.text = etree.CDATA(actual_cli.strip())
|
|
257
|
|
258 command_line = []
|
|
259 try:
|
|
260 command_line.append(export_xml.outputs.cli())
|
|
261 except Exception:
|
|
262 pass
|
|
263 command_node = etree.SubElement(export_xml.root, 'token', {"name": "%s_OUTMACRO" % self.id.upper()})
|
|
264 actual_cli = "%s" % (export_xml.clean_command_string(command_line))
|
|
265 command_node.text = etree.CDATA(actual_cli.strip())
|
|
266
|
|
267 try:
|
|
268 export_xml.append(export_xml.inputs)
|
|
269 except Exception:
|
|
270 pass
|
|
271
|
|
272 try:
|
|
273 export_xml.append(export_xml.outputs)
|
|
274 except Exception:
|
|
275 pass
|
|
276
|
|
277 return super(Tool, export_xml).export()
|