comparison toolfactory/galaxyxml/tool/__init__.py @ 136:94f5560de46d draft

Uploaded
author fubar
date Tue, 13 Apr 2021 00:35:36 +0000
parents
children
comparison
equal deleted inserted replaced
135:7805fdac70ed 136:94f5560de46d
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()