Source code for planemo.training.tool_input
"""Module contains code for the ToolInput class, dealing with the description of tool in workflow and XML."""
from planemo import templates
from planemo.io import info
INPUT_PARAM = """
>{{space}}- *"{{param_label}}"*: `{{param_value}}`
"""
INPUT_FILE_TEMPLATE = """
>{{space}}- {{ '{%' }} icon {{icon}} {{ '%}' }} *"{{input_name}}"*: {{input_value}}
"""
INPUT_SECTION = """
>{{space}}- In *"{{section_label}}"*:
"""
INPUT_ADD_REPEAT = """
>{{space}}- {{ '{%' }} icon param-repeat {{ '%}' }} *"Insert {{repeat_label}}"*
"""
SPACE = " "
[docs]
class ToolInput:
"""Class to describe a tool input / parameter and its value from a workflow."""
def __init__(self, tool_inp_desc, wf_param_values, wf_steps, level, should_be_there=False, force_default=False):
"""Init an instance of ToolInput."""
self.name = tool_inp_desc["name"]
if "type" not in tool_inp_desc:
raise ValueError(f"No type for the parameter {tool_inp_desc['name']}")
self.type = tool_inp_desc["type"]
self.tool_inp_desc = tool_inp_desc
self.level = level
self.wf_param_values = wf_param_values
self.wf_steps = wf_steps
self.formatted_desc = ""
self.force_default = force_default
if self.name not in self.wf_param_values:
if not should_be_there:
info(f"{self.name} not in workflow")
else:
raise ValueError(f"{self.name} not in workflow")
else:
self.wf_param_values = self.wf_param_values[self.name]
[docs]
def get_formatted_inputs(self):
"""Format the inputs of a step."""
inputlist = ""
inps = []
if isinstance(self.wf_param_values, list):
# multiple input (not collection)
icon = "param-files"
for i in self.wf_param_values:
inps.append(f"`{i['output_name']}` {get_input_tool_name(i['id'], self.wf_steps)}")
else:
inp = self.wf_param_values
if "id" in inp:
# sinle input or collection
inp_type = self.wf_steps[str(inp["id"])]["type"]
if "collection" in inp_type:
icon = "param-collection"
else:
icon = "param-file"
inps = [f"`{inp['output_name']}` {get_input_tool_name(inp['id'], self.wf_steps)}"]
if len(inps) > 0:
inputlist += templates.render(
INPUT_FILE_TEMPLATE,
**{
"icon": icon,
"input_name": self.tool_inp_desc["label"],
"input_value": ", ".join(inps),
"space": SPACE * self.level,
},
)
return inputlist
[docs]
def get_lower_param_desc(self):
"""Get the formatted description of the paramaters in the 'inputs' of the tool description."""
sub_param_desc = ""
for inp in self.tool_inp_desc["inputs"]:
tool_inp = ToolInput(inp, self.wf_param_values, self.wf_steps, self.level + 1)
sub_param_desc += tool_inp.get_formatted_desc()
return sub_param_desc
[docs]
def get_formatted_section_desc(self):
"""Format the description (label and value) for parameters in a section."""
section_paramlist = ""
sub_param_desc = self.get_lower_param_desc()
if sub_param_desc != "":
section_paramlist += templates.render(
INPUT_SECTION, **{"space": SPACE * self.level, "section_label": self.tool_inp_desc["title"]}
)
section_paramlist += sub_param_desc
return section_paramlist
[docs]
def get_formatted_conditional_desc(self):
"""Format the description (label and value) for parameters in a conditional."""
conditional_paramlist = ""
# Get conditional parameter
inp = ToolInput(
self.tool_inp_desc["test_param"],
self.wf_param_values,
self.wf_steps,
self.level,
should_be_there=True,
force_default=True,
)
conditional_paramlist = inp.get_formatted_desc()
cond_param = inp.wf_param_values
# Get parameters in the when and their values
tmp_tool_inp_desc = self.tool_inp_desc
for case in tmp_tool_inp_desc["cases"]:
if case["value"] == cond_param and len(case["inputs"]) > 0:
self.tool_inp_desc = case
conditional_paramlist += self.get_lower_param_desc()
self.tool_inp_desc = tmp_tool_inp_desc
return conditional_paramlist
[docs]
def get_formatted_repeat_desc(self):
"""Format the description (label and value) for parameters in a repeat."""
repeat_paramlist = ""
if self.wf_param_values != "[]":
tool_inp = {}
for inp in self.tool_inp_desc["inputs"]:
tool_inp.setdefault(inp["name"], inp)
tmp_wf_param_values = self.wf_param_values
cur_level = self.level
for param in tmp_wf_param_values:
self.wf_param_values = param
self.level = cur_level + 1
paramlist_in_repeat = self.get_lower_param_desc()
if paramlist_in_repeat != "":
# add first click
repeat_paramlist += templates.render(
INPUT_ADD_REPEAT, **{"space": SPACE * (self.level), "repeat_label": self.tool_inp_desc["title"]}
)
repeat_paramlist += paramlist_in_repeat
self.level = cur_level
self.wf_param_values = tmp_wf_param_values
repeat_desc = ""
if repeat_paramlist != "":
repeat_desc += (
templates.render(
INPUT_SECTION, **{"space": SPACE * self.level, "section_label": self.tool_inp_desc["title"]}
)
+ repeat_paramlist
)
return repeat_desc
[docs]
def get_formatted_other_param_desc(self):
"""Get value of a 'simple' parameter if different from the default value, None otherwise."""
param_value = None
if self.tool_inp_desc["value"] == self.wf_param_values and not self.force_default:
param_value = None
elif self.type == "boolean":
if bool(self.tool_inp_desc["value"]) == self.wf_param_values:
param_value = None
else:
param_value = "Yes" if self.wf_param_values else "No"
elif self.type == "select":
param_values = []
for opt in self.tool_inp_desc["options"]:
if opt[1] == self.wf_param_values:
param_values.append(opt[0])
param_value = ", ".join(param_values)
elif self.type == "data_column":
param_value = f"c{self.wf_param_values}"
else:
param_value = self.wf_param_values
param_desc = ""
if param_value is not None:
param_desc = templates.render(
INPUT_PARAM,
**{"space": SPACE * self.level, "param_label": self.tool_inp_desc["label"], "param_value": param_value},
)
return param_desc
[docs]
def get_formatted_desc(self):
"""Get the formatted description (ready for hands-on tutorial) of the parameter."""
if self.wf_param_values:
if self.type == "data" or self.type == "data_collection":
self.formatted_desc += self.get_formatted_inputs()
elif self.type == "section":
self.formatted_desc += self.get_formatted_section_desc()
elif self.type == "conditional":
self.formatted_desc += self.get_formatted_conditional_desc()
elif self.type == "repeat":
self.formatted_desc += self.get_formatted_repeat_desc()
else:
self.formatted_desc += self.get_formatted_other_param_desc()
return self.formatted_desc
[docs]
def get_input_tool_name(step_id, steps):
"""Get the string with the name of the tool that generated an input."""
inp_provenance = ""
inp_prov_id = str(step_id)
if inp_prov_id in steps:
name = steps[inp_prov_id]["name"]
if "Input dataset" in name:
inp_provenance = f"({name})"
else:
inp_provenance = f"(output of **{name}** {{% icon tool %}})"
return inp_provenance
[docs]
def get_empty_input():
"""Get the string for an empty input."""
return templates.render(
INPUT_FILE_TEMPLATE,
**{"space": 1 * SPACE, "icon": "param-file", "input_name": "Input file", "input_value": "File"},
)
[docs]
def get_empty_param():
"""Get the string for an empty param."""
return templates.render(INPUT_PARAM, **{"space": 1 * SPACE, "param_label": "Parameter", "param_value": "a value"})