comparison env/lib/python3.9/site-packages/galaxy/tool_util/linters/inputs.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 """This module contains a linting functions for tool inputs."""
2 from galaxy.util import string_as_bool
3 from ._util import is_datasource, is_valid_cheetah_placeholder
4 from ..parser.util import _parse_name
5
6
7 def lint_inputs(tool_xml, lint_ctx):
8 """Lint parameters in a tool's inputs block."""
9 datasource = is_datasource(tool_xml)
10 inputs = tool_xml.findall("./inputs//param")
11 num_inputs = 0
12 for param in inputs:
13 num_inputs += 1
14 param_attrib = param.attrib
15 has_errors = False
16 if "type" not in param_attrib:
17 lint_ctx.error("Found param input with no type specified.")
18 has_errors = True
19 if "name" not in param_attrib and "argument" not in param_attrib:
20 lint_ctx.error("Found param input with no name specified.")
21 has_errors = True
22
23 if has_errors:
24 continue
25
26 param_type = param_attrib["type"]
27 param_name = _parse_name(param_attrib.get("name"), param_attrib.get("argument"))
28
29 if not is_valid_cheetah_placeholder(param_name):
30 lint_ctx.warn("Param input [%s] is not a valid Cheetah placeholder.", param_name)
31
32 if param_type == "data":
33 if "format" not in param_attrib:
34 lint_ctx.warn("Param input [%s] with no format specified - 'data' format will be assumed.", param_name)
35 elif param_type == "select":
36 dynamic_options = param.get("dynamic_options", None)
37 if dynamic_options is None:
38 dynamic_options = param.find("options")
39
40 select_options = param.findall('./option')
41 if any(['value' not in option.attrib for option in select_options]):
42 lint_ctx.error("Select [%s] has option without value", param_name)
43
44 if dynamic_options is None and len(select_options) == 0:
45 message = "No options defined for select [%s]" % param_name
46 lint_ctx.warn(message)
47 # TODO: Validate type, much more...
48
49 conditional_selects = tool_xml.findall("./inputs//conditional")
50 for conditional in conditional_selects:
51 conditional_name = conditional.get('name')
52 if not conditional_name:
53 lint_ctx.error("Conditional without a name")
54 if conditional.get("value_from"):
55 # Probably only the upload tool use this, no children elements
56 continue
57 first_param = conditional.find("param")
58 if first_param is None:
59 lint_ctx.error("Conditional '%s' has no child <param>" % conditional_name)
60 continue
61 first_param_type = first_param.get('type')
62 if first_param_type not in ['select', 'boolean']:
63 lint_ctx.warn("Conditional '%s' first param should have type=\"select\" /> or type=\"boolean\"" % conditional_name)
64 continue
65
66 if first_param_type == 'select':
67 select_options = _find_with_attribute(first_param, 'option', 'value')
68 option_ids = [option.get('value') for option in select_options]
69 else: # boolean
70 option_ids = [
71 first_param.get('truevalue', 'true'),
72 first_param.get('falsevalue', 'false')
73 ]
74
75 if string_as_bool(first_param.get('optional', False)):
76 lint_ctx.warn("Conditional test parameter cannot be optional")
77
78 whens = conditional.findall('./when')
79 if any('value' not in when.attrib for when in whens):
80 lint_ctx.error("When without value")
81
82 when_ids = [w.get('value') for w in whens]
83
84 for option_id in option_ids:
85 if option_id not in when_ids:
86 lint_ctx.warn(f"No <when /> block found for {first_param_type} option '{option_id}' inside conditional '{conditional_name}'")
87
88 for when_id in when_ids:
89 if when_id not in option_ids:
90 if first_param_type == 'select':
91 lint_ctx.warn(f"No <option /> found for when block '{when_id}' inside conditional '{conditional_name}'")
92 else:
93 lint_ctx.warn(f"No truevalue/falsevalue found for when block '{when_id}' inside conditional '{conditional_name}'")
94
95 if datasource:
96 for datasource_tag in ('display', 'uihints'):
97 if not any([param.tag == datasource_tag for param in inputs]):
98 lint_ctx.info("%s tag usually present in data sources" % datasource_tag)
99
100 if num_inputs:
101 lint_ctx.info("Found %d input parameters.", num_inputs)
102 else:
103 if datasource:
104 lint_ctx.info("No input parameters, OK for data sources")
105 else:
106 lint_ctx.warn("Found no input parameters.")
107
108
109 def lint_repeats(tool_xml, lint_ctx):
110 """Lint repeat blocks in tool inputs."""
111 repeats = tool_xml.findall("./inputs//repeat")
112 for repeat in repeats:
113 if "name" not in repeat.attrib:
114 lint_ctx.error("Repeat does not specify name attribute.")
115 if "title" not in repeat.attrib:
116 lint_ctx.error("Repeat does not specify title attribute.")
117
118
119 def _find_with_attribute(element, tag, attribute, test_value=None):
120 rval = []
121 for el in (element.findall('./%s' % tag) or []):
122 if attribute not in el.attrib:
123 continue
124 value = el.attrib[attribute]
125 if test_value is not None:
126 if value == test_value:
127 rval.append(el)
128 else:
129 rval.append(el)
130 return rval