Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying multi-select workflow parameters #18715

Merged
merged 6 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/src/components/Workflow/Editor/NodeOutput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ const outputDetails = computed(() => {
const outputType =
collectionType && collectionType.isCollection && collectionType.collectionType
? `output is ${collectionTypeToDescription(collectionType)}`
: `output is dataset`;
: `output is ${terminal.value.type || "dataset"}`;
if (isMultiple.value) {
if (!collectionType) {
collectionType = NULL_COLLECTION_TYPE_DESCRIPTION;
Expand Down
9 changes: 9 additions & 0 deletions client/src/components/Workflow/Editor/modules/terminals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,12 @@ export class InputParameterTerminal extends BaseInputTerminal {
const otherType = ("type" in other && other.type) || "data";
const effectiveOtherType = this.effectiveType(otherType);
const canAccept = effectiveThisType === effectiveOtherType;
if (!this.multiple && other.multiple) {
return new ConnectionAcceptable(
false,
`This output parameter represents multiple values but input only accepts a single value`
);
}
return new ConnectionAcceptable(
canAccept,
canAccept ? null : `Cannot attach a ${effectiveOtherType} parameter to a ${effectiveThisType} input`
Expand Down Expand Up @@ -812,12 +818,14 @@ export class OutputCollectionTerminal extends BaseOutputTerminal {

interface OutputParameterTerminalArgs extends Omit<BaseOutputTerminalArgs, "datatypes"> {
type: ParameterOutput["type"];
multiple: ParameterOutput["multiple"];
}

export class OutputParameterTerminal extends BaseOutputTerminal {
constructor(attr: OutputParameterTerminalArgs) {
super({ ...attr, datatypes: [] });
this.type = attr.type;
this.multiple = attr.multiple;
}
}

Expand Down Expand Up @@ -988,6 +996,7 @@ export function terminalFactory<T extends TerminalSourceAndInvalid>(
if (isOutputParameterArg(terminalSource)) {
return new OutputParameterTerminal({
...outputArgs,
multiple: terminalSource.multiple,
type: terminalSource.type,
}) as TerminalOf<T>;
} else if (isOutputCollectionArg(terminalSource)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@
"content_id": null,
"name": "Input parameter",
"tool_state": {
"parameter_definition": "{\"__current_case__\": 1, \"optional\": {\"__current_case__\": 1, \"optional\": \"false\"}, \"parameter_type\": \"integer\"}",
"parameter_definition": "{\"__current_case__\": 1, \"optional\": {\"__current_case__\": 1, \"optional\": \"false\"}, \"parameter_type\": \"integer\", \"multiple\": \"false\",}",
"__page__": null,
"__rerun_remap_job_id__": null
},
Expand All @@ -211,7 +211,8 @@
"label": "integer parameter input",
"type": "integer",
"optional": false,
"parameter": true
"parameter": true,
"multiple": false
}
],
"annotation": "",
Expand Down Expand Up @@ -427,7 +428,7 @@
"content_id": null,
"name": "Input parameter",
"tool_state": {
"parameter_definition": "{\"__current_case__\": 0, \"optional\": {\"__current_case__\": 1, \"optional\": \"false\"}, \"parameter_type\": \"text\", \"restrictions\": {\"__current_case__\": 0, \"how\": \"none\"}}",
"parameter_definition": "{\"__current_case__\": 0, \"optional\": {\"__current_case__\": 1, \"optional\": \"false\"}, \"parameter_type\": \"text\", \"multiple\": \"false\", \"restrictions\": {\"__current_case__\": 0, \"how\": \"none\"}}",
"__page__": null,
"__rerun_remap_job_id__": null
},
Expand All @@ -439,7 +440,8 @@
"label": "text parameter input",
"type": "text",
"optional": false,
"parameter": true
"parameter": true,
"multiple": false
}
],
"annotation": "",
Expand Down Expand Up @@ -746,15 +748,17 @@
"txt"
],
"type": "data",
"optional": false
"optional": false,
"multiple": false
},
{
"name": "out2",
"extensions": [
"txt"
],
"type": "data",
"optional": false
"optional": false,
"multiple": false
}
],
"annotation": "",
Expand Down
1 change: 1 addition & 0 deletions client/src/stores/workflowStepStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export declare const ParameterTypes: "text" | "integer" | "float" | "boolean" |
export interface ParameterOutput extends Omit<DataOutput, "type" | "extensions"> {
type: typeof ParameterTypes;
parameter: true;
multiple: boolean;
}

interface BaseStepInput {
Expand Down
2 changes: 1 addition & 1 deletion lib/galaxy/dependencies/pinned-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ graphql-relay==3.2.0 ; python_version >= "3.8" and python_version < "3.13"
gravity==1.0.6 ; python_version >= "3.8" and python_version < "3.13"
greenlet==3.0.3 ; python_version < "3.13" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") and python_version >= "3.8"
gunicorn==22.0.0 ; python_version >= "3.8" and python_version < "3.13"
gxformat2==0.19.0 ; python_version >= "3.8" and python_version < "3.13"
gxformat2==0.20.0 ; python_version >= "3.8" and python_version < "3.13"
h11==0.14.0 ; python_version >= "3.8" and python_version < "3.13"
h5grove==2.2.0 ; python_version >= "3.8" and python_version < "3.13"
h5py==3.11.0 ; python_version >= "3.8" and python_version < "3.13"
Expand Down
23 changes: 20 additions & 3 deletions lib/galaxy/workflow/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,18 @@ def get_inputs(self):
optional_cond.cases = optional_cases

if param_type == "text":

specify_multiple_source = dict(
name="multiple",
label="Allow multiple selection",
help="Only applies when connected to multi-select parameter(s)",
type="boolean",
checked=parameter_def.get("multiple", False),
)
specify_multiple = BooleanToolParameter(None, specify_multiple_source)
# Insert multiple option as first option, which is determined by dictionary insert order
when_this_type.inputs = {"multiple": specify_multiple, **when_this_type.inputs}

restrict_how_source: Dict[str, Union[str, List[Dict[str, Union[str, bool]]]]] = dict(
name="how", label="Restrict Text Values?", type="select"
)
Expand Down Expand Up @@ -1449,6 +1461,8 @@ def get_runtime_inputs(self, step, connections: Optional[Iterable[WorkflowStepCo

# Optional parameters for tool input source definition.
parameter_kwds: Dict[str, Union[str, List[Dict[str, Any]]]] = {}
if "multiple" in parameter_def:
parameter_kwds["multiple"] = parameter_def["multiple"]

is_text = parameter_type == "text"
restricted_inputs = False
Expand Down Expand Up @@ -1499,9 +1513,6 @@ def _parameter_def_list_to_options(parameter_value):
if parameter_type == "boolean":
parameter_kwds["checked"] = default_value

if "value" not in parameter_kwds and parameter_type in ["integer", "float"]:
parameter_kwds["value"] = str(0)

if is_text and parameter_def.get("suggestions") is not None:
suggestion_values = parameter_def.get("suggestions")
parameter_kwds["options"] = _parameter_def_list_to_options(suggestion_values)
Expand All @@ -1528,6 +1539,7 @@ def get_all_outputs(self, data_only=False):
label=self.label,
type=parameter_def.get("parameter_type"),
optional=parameter_def["optional"],
multiple=parameter_def.get("multiple", False),
parameter=True,
)
]
Expand Down Expand Up @@ -1556,6 +1568,7 @@ def step_state_to_tool_state(self, state):
default_set = True
default_value = state["default"]
state["optional"] = True
multiple = state.get("multiple")
restrictions = state.get("restrictions")
restrictOnConnections = state.get("restrictOnConnections")
suggestions = state.get("suggestions")
Expand All @@ -1573,6 +1586,8 @@ def step_state_to_tool_state(self, state):
"optional": {"optional": str(state.get("optional", False))},
}
}
if multiple is not None:
state["parameter_definition"]["multiple"] = multiple
state["parameter_definition"]["restrictions"] = {}
state["parameter_definition"]["restrictions"]["how"] = restrictions_how

Expand Down Expand Up @@ -1614,6 +1629,8 @@ def _parse_state_into_dict(self):
rval["default"] = optional_state["specify_default"]["default"]
else:
optional = False
if "multiple" in parameters_def:
rval["multiple"] = parameters_def["multiple"]
restrictions_cond_values = parameters_def.get("restrictions")
if restrictions_cond_values:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
- doc: |
Test to verify text parameter can be connected to data column param
job:
input:
type: File
value: 2.tabular
file_type: tabular
column:
value: [1, 2]
type: raw
outputs:
output:
asserts:
- that: has_text
text: "col 1,2"
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class: GalaxyWorkflow
inputs:
input:
type: data
column:
type: [integer]
outputs:
output:
outputSource: column_param_list/output2
steps:
column_param_list:
tool_id: column_param_list
in:
input1: input
col: column
col_names: column
14 changes: 14 additions & 0 deletions lib/galaxy_test/workflow/multiple_text.gxwf-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- doc: |
Test that workflows can run with multiple text parameter fed into a multi select parameter.
job:
input:
value:
- --ex1
- ex2
- --ex3
type: raw
outputs:
output:
asserts:
- that: has_line
line: '--ex1,ex2,--ex3'
15 changes: 15 additions & 0 deletions lib/galaxy_test/workflow/multiple_text.gxwf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class: GalaxyWorkflow
inputs:
input:
type: [string]
outputs:
output:
outputSource: multi_select/output
steps:
multi_select:
tool_id: multi_select
tool_version: "0.1"
in:
select_ex: input
tool_state:
select_optional: null
Loading