Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/galaxy/tool_util/parser/interface.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author | guerler |
---|---|
date | Fri, 31 Jul 2020 00:32:28 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:d30785e31577 | 1:56ad4e20f292 |
---|---|
1 import os | |
2 from abc import ( | |
3 ABCMeta, | |
4 abstractmethod | |
5 ) | |
6 | |
7 import six | |
8 | |
9 from .util import _parse_name | |
10 | |
11 NOT_IMPLEMENTED_MESSAGE = "Galaxy tool format does not yet support this tool feature." | |
12 | |
13 | |
14 @six.python_2_unicode_compatible | |
15 @six.add_metaclass(ABCMeta) | |
16 class ToolSource(object): | |
17 """ This interface represents an abstract source to parse tool | |
18 information from. | |
19 """ | |
20 default_is_multi_byte = False | |
21 | |
22 @abstractmethod | |
23 def parse_id(self): | |
24 """ Parse an ID describing the abstract tool. This is not the | |
25 GUID tracked by the tool shed but the simple id (there may be | |
26 multiple tools loaded in Galaxy with this same simple id). | |
27 """ | |
28 | |
29 @abstractmethod | |
30 def parse_version(self): | |
31 """ Parse a version describing the abstract tool. | |
32 """ | |
33 | |
34 def parse_tool_module(self): | |
35 """ Load Tool class from a custom module. (Optional). | |
36 | |
37 If not None, return pair containing module and class (as strings). | |
38 """ | |
39 return None | |
40 | |
41 def parse_action_module(self): | |
42 """ Load Tool class from a custom module. (Optional). | |
43 | |
44 If not None, return pair containing module and class (as strings). | |
45 """ | |
46 return None | |
47 | |
48 def parse_tool_type(self): | |
49 """ Load simple tool type string (e.g. 'data_source', 'default'). | |
50 """ | |
51 return None | |
52 | |
53 @abstractmethod | |
54 def parse_name(self): | |
55 """ Parse a short name for tool (required). """ | |
56 | |
57 @abstractmethod | |
58 def parse_description(self): | |
59 """ Parse a description for tool. Longer than name, shorted than help. """ | |
60 | |
61 def parse_is_multi_byte(self): | |
62 """ Parse is_multi_byte from tool - TODO: figure out what this is and | |
63 document. | |
64 """ | |
65 return self.default_is_multi_byte | |
66 | |
67 def parse_display_interface(self, default): | |
68 """ Parse display_interface - fallback to default for the tool type | |
69 (supplied as default parameter) if not specified. | |
70 """ | |
71 return default | |
72 | |
73 def parse_require_login(self, default): | |
74 """ Parse whether the tool requires login (as a bool). | |
75 """ | |
76 return default | |
77 | |
78 def parse_request_param_translation_elem(self): | |
79 """ Return an XML element describing require parameter translation. | |
80 | |
81 If we wish to support this feature for non-XML based tools this should | |
82 be converted to return some sort of object interface instead of a RAW | |
83 XML element. | |
84 """ | |
85 return None | |
86 | |
87 @abstractmethod | |
88 def parse_command(self): | |
89 """ Return string contianing command to run. | |
90 """ | |
91 | |
92 def parse_expression(self): | |
93 """ Return string contianing command to run. | |
94 """ | |
95 return None | |
96 | |
97 @abstractmethod | |
98 def parse_environment_variables(self): | |
99 """ Return environment variable templates to expose. | |
100 """ | |
101 | |
102 def parse_home_target(self): | |
103 """Should be "job_home", "shared_home", "job_tmp", "pwd", or None. | |
104 """ | |
105 return "pwd" | |
106 | |
107 def parse_tmp_target(self): | |
108 """Should be "pwd", "shared_home", "job_tmp", "job_tmp_if_explicit", or None. | |
109 """ | |
110 return "job_tmp" | |
111 | |
112 def parse_tmp_directory_vars(self): | |
113 """Directories to override if a tmp_target is not None.""" | |
114 return ["TMPDIR", "TMP", "TEMP"] | |
115 | |
116 def parse_docker_env_pass_through(self): | |
117 return ["GALAXY_SLOTS", "HOME", "_GALAXY_JOB_HOME_DIR", "_GALAXY_JOB_TMP_DIR"] + self.parse_tmp_directory_vars() | |
118 | |
119 @abstractmethod | |
120 def parse_interpreter(self): | |
121 """ Return string containing the interpreter to prepend to the command | |
122 (for instance this might be 'python' to run a Python wrapper located | |
123 adjacent to the tool). | |
124 """ | |
125 | |
126 @abstractmethod | |
127 def parse_interactivetool(self): | |
128 """ Return InteractiveTool entry point templates to expose. | |
129 """ | |
130 | |
131 def parse_redirect_url_params_elem(self): | |
132 """ Return an XML element describing redirect_url_params. | |
133 | |
134 If we wish to support this feature for non-XML based tools this should | |
135 be converted to return some sort of object interface instead of a RAW | |
136 XML element. | |
137 """ | |
138 return None | |
139 | |
140 def parse_version_command(self): | |
141 """ Parse command used to determine version of primary application | |
142 driving the tool. Return None to not generate or record such a command. | |
143 """ | |
144 return None | |
145 | |
146 def parse_version_command_interpreter(self): | |
147 """ Parse command used to determine version of primary application | |
148 driving the tool. Return None to not generate or record such a command. | |
149 """ | |
150 return None | |
151 | |
152 def parse_parallelism(self): | |
153 """ Return a galaxy.jobs.ParallismInfo object describing task splitting | |
154 or None. | |
155 """ | |
156 return None | |
157 | |
158 def parse_hidden(self): | |
159 """ Return boolean indicating whether tool should be hidden in the tool menu. | |
160 """ | |
161 return False | |
162 | |
163 def parse_sanitize(self): | |
164 """ Return boolean indicating whether tool should be sanitized or not. | |
165 """ | |
166 return True | |
167 | |
168 def parse_refresh(self): | |
169 """ Return boolean indicating ... I have no clue... | |
170 """ | |
171 return False | |
172 | |
173 @abstractmethod | |
174 def parse_requirements_and_containers(self): | |
175 """ Return pair of ToolRequirement and ContainerDescription lists. """ | |
176 | |
177 @abstractmethod | |
178 def parse_input_pages(self): | |
179 """ Return a PagesSource representing inputs by page for tool. """ | |
180 | |
181 def parse_provided_metadata_style(self): | |
182 """Return style of tool provided metadata file (e.g. galaxy.json). | |
183 | |
184 A value of of "default" indicates the newer galaxy.json style | |
185 (the default for XML-based tools with profile >= 17.09) and a value | |
186 of "legacy" indicates the older galaxy.json style. | |
187 | |
188 A short description of these two styles can be found at | |
189 https://github.com/galaxyproject/galaxy/pull/4437. | |
190 """ | |
191 return "default" | |
192 | |
193 def parse_provided_metadata_file(self): | |
194 """Return location of provided metadata file (e.g. galaxy.json).""" | |
195 return "galaxy.json" | |
196 | |
197 @abstractmethod | |
198 def parse_outputs(self, tool): | |
199 """ Return a pair of output and output collections ordered | |
200 dictionaries for use by Tool. | |
201 """ | |
202 | |
203 @abstractmethod | |
204 def parse_strict_shell(self): | |
205 """ Return True if tool commands should be executed with | |
206 set -e. | |
207 """ | |
208 | |
209 @abstractmethod | |
210 def parse_stdio(self): | |
211 """ Builds lists of ToolStdioExitCode and ToolStdioRegex objects | |
212 to describe tool execution error conditions. | |
213 """ | |
214 return [], [] | |
215 | |
216 @abstractmethod | |
217 def parse_help(self): | |
218 """ Return RST definition of help text for tool or None if the tool | |
219 doesn't define help text. | |
220 """ | |
221 | |
222 @abstractmethod | |
223 def parse_profile(self): | |
224 """ Return tool profile version as Galaxy major e.g. 16.01 or 16.04. | |
225 """ | |
226 | |
227 @abstractmethod | |
228 def parse_python_template_version(self): | |
229 """ | |
230 Return minimum python version that the tool template has been developed against. | |
231 """ | |
232 | |
233 @property | |
234 def macro_paths(self): | |
235 return [] | |
236 | |
237 @property | |
238 def source_path(self): | |
239 return None | |
240 | |
241 def paths_and_modtimes(self): | |
242 paths_and_modtimes = {p: os.path.getmtime(p) for p in self.macro_paths} | |
243 if self.source_path: | |
244 paths_and_modtimes[self.source_path] = os.path.getmtime(self.source_path) | |
245 return paths_and_modtimes | |
246 | |
247 def parse_tests_to_dict(self): | |
248 return {'tests': []} | |
249 | |
250 def __str__(self): | |
251 source_path = self.source_path | |
252 if source_path: | |
253 as_str = u'%s[%s]' % (self.__class__.__name__, source_path) | |
254 else: | |
255 as_str = u'%s[In-memory]' % (self.__class__.__name__) | |
256 return as_str | |
257 | |
258 | |
259 class PagesSource(object): | |
260 """ Contains a list of Pages - each a list of InputSources - | |
261 each item in the outer list representing a page of inputs. | |
262 Pages are deprecated so ideally this outer list will always | |
263 be exactly a singleton. | |
264 """ | |
265 | |
266 def __init__(self, page_sources): | |
267 self.page_sources = page_sources | |
268 | |
269 @property | |
270 def inputs_defined(self): | |
271 return True | |
272 | |
273 | |
274 @six.add_metaclass(ABCMeta) | |
275 class PageSource(object): | |
276 | |
277 def parse_display(self): | |
278 return None | |
279 | |
280 @abstractmethod | |
281 def parse_input_sources(self): | |
282 """ Return a list of InputSource objects. """ | |
283 | |
284 | |
285 @six.add_metaclass(ABCMeta) | |
286 class InputSource(object): | |
287 default_optional = False | |
288 | |
289 def elem(self): | |
290 # For things in transition that still depend on XML - provide a way | |
291 # to grab it and just throw an error if feature is attempted to be | |
292 # used with other tool sources. | |
293 raise NotImplementedError(NOT_IMPLEMENTED_MESSAGE) | |
294 | |
295 @abstractmethod | |
296 def get(self, key, value=None): | |
297 """ Return simple named properties as string for this input source. | |
298 keys to be supported depend on the parameter type. | |
299 """ | |
300 | |
301 @abstractmethod | |
302 def get_bool(self, key, default): | |
303 """ Return simple named properties as boolean for this input source. | |
304 keys to be supported depend on the parameter type. | |
305 """ | |
306 | |
307 def parse_label(self): | |
308 return self.get("label") | |
309 | |
310 def parse_name(self): | |
311 """Return name of an input source | |
312 returns the name or if absent the argument property | |
313 In the latter case, leading dashes are stripped and | |
314 all remaining dashes are replaced by underscores. | |
315 """ | |
316 return _parse_name(self.get('name'), self.get('argument')) | |
317 | |
318 def parse_help(self): | |
319 return self.get("help") | |
320 | |
321 def parse_sanitizer_elem(self): | |
322 """ Return an XML description of sanitizers. This is a stop gap | |
323 until we can rework galaxy.tools.parameters.sanitize to not | |
324 explicitly depend on XML. | |
325 """ | |
326 return None | |
327 | |
328 def parse_validator_elems(self): | |
329 """ Return an XML description of sanitizers. This is a stop gap | |
330 until we can rework galaxy.tools.parameters.validation to not | |
331 explicitly depend on XML. | |
332 """ | |
333 return [] | |
334 | |
335 def parse_optional(self, default=None): | |
336 """ Return boolean indicating wheter parameter is optional. """ | |
337 if default is None: | |
338 default = self.default_optional | |
339 return self.get_bool("optional", default) | |
340 | |
341 def parse_dynamic_options_elem(self): | |
342 """ Return an XML elemnt describing dynamic options. | |
343 """ | |
344 return None | |
345 | |
346 def parse_static_options(self): | |
347 """ Return list of static options if this is a select type without | |
348 defining a dynamic options. | |
349 """ | |
350 return [] | |
351 | |
352 def parse_conversion_tuples(self): | |
353 """ Return list of (name, extension) to describe explicit conversions. | |
354 """ | |
355 return [] | |
356 | |
357 def parse_nested_inputs_source(self): | |
358 # For repeats | |
359 raise NotImplementedError(NOT_IMPLEMENTED_MESSAGE) | |
360 | |
361 def parse_test_input_source(self): | |
362 # For conditionals | |
363 raise NotImplementedError(NOT_IMPLEMENTED_MESSAGE) | |
364 | |
365 def parse_when_input_sources(self): | |
366 raise NotImplementedError(NOT_IMPLEMENTED_MESSAGE) | |
367 | |
368 | |
369 class TestCollectionDef(object): | |
370 | |
371 def __init__(self, attrib, name, collection_type, elements): | |
372 self.attrib = attrib | |
373 self.collection_type = collection_type | |
374 self.elements = elements | |
375 self.name = name | |
376 | |
377 @staticmethod | |
378 def from_xml(elem, parse_param_elem): | |
379 elements = [] | |
380 attrib = dict(elem.attrib) | |
381 collection_type = attrib["type"] | |
382 name = attrib.get("name", "Unnamed Collection") | |
383 for element in elem.findall("element"): | |
384 element_attrib = dict(element.attrib) | |
385 element_identifier = element_attrib["name"] | |
386 nested_collection_elem = element.find("collection") | |
387 if nested_collection_elem is not None: | |
388 element_definition = TestCollectionDef.from_xml(nested_collection_elem, parse_param_elem) | |
389 else: | |
390 element_definition = parse_param_elem(element) | |
391 elements.append({"element_identifier": element_identifier, "element_definition": element_definition}) | |
392 | |
393 return TestCollectionDef( | |
394 attrib=attrib, | |
395 collection_type=collection_type, | |
396 elements=elements, | |
397 name=name, | |
398 ) | |
399 | |
400 def to_dict(self): | |
401 def element_to_dict(element_dict): | |
402 element_identifier, element_def = element_dict["element_identifier"], element_dict["element_definition"] | |
403 if isinstance(element_def, TestCollectionDef): | |
404 element_def = element_def.to_dict() | |
405 return { | |
406 "element_identifier": element_identifier, | |
407 "element_definition": element_def, | |
408 } | |
409 | |
410 return { | |
411 "model_class": "TestCollectionDef", | |
412 "attributes": self.attrib, | |
413 "collection_type": self.collection_type, | |
414 "elements": list(map(element_to_dict, self.elements or [])), | |
415 "name": self.name, | |
416 } | |
417 | |
418 @staticmethod | |
419 def from_dict(as_dict): | |
420 assert as_dict["model_class"] == "TestCollectionDef" | |
421 | |
422 def element_from_dict(element_dict): | |
423 if "element_definition" not in element_dict: | |
424 raise Exception("Invalid element_dict %s" % element_dict) | |
425 element_def = element_dict["element_definition"] | |
426 if element_def.get("model_class", None) == "TestCollectionDef": | |
427 element_def = TestCollectionDef.from_dict(element_def) | |
428 return {"element_identifier": element_dict["element_identifier"], "element_definition": element_def} | |
429 | |
430 return TestCollectionDef( | |
431 attrib=as_dict["attributes"], | |
432 name=as_dict["name"], | |
433 elements=list(map(element_from_dict, as_dict["elements"] or [])), | |
434 collection_type=as_dict["collection_type"], | |
435 ) | |
436 | |
437 def collect_inputs(self): | |
438 inputs = [] | |
439 for element in self.elements: | |
440 value = element["element_definition"] | |
441 if isinstance(value, TestCollectionDef): | |
442 inputs.extend(value.collect_inputs()) | |
443 else: | |
444 inputs.append(value) | |
445 return inputs | |
446 | |
447 | |
448 class TestCollectionOutputDef(object): | |
449 | |
450 def __init__(self, name, attrib, element_tests): | |
451 self.name = name | |
452 self.collection_type = attrib.get("type", None) | |
453 count = attrib.get("count", None) | |
454 self.count = int(count) if count is not None else None | |
455 self.attrib = attrib | |
456 self.element_tests = element_tests | |
457 | |
458 @staticmethod | |
459 def from_dict(as_dict): | |
460 return TestCollectionOutputDef( | |
461 name=as_dict["name"], | |
462 attrib=as_dict["attributes"], | |
463 element_tests=as_dict["element_tests"], | |
464 ) | |
465 | |
466 def to_dict(self): | |
467 return dict( | |
468 name=self.name, | |
469 attributes=self.attrib, | |
470 element_tests=self.element_tests | |
471 ) |