Skip to content

Commit 43c43f6

Browse files
committed
Merge branch 'release_25.0' into release_25.1
2 parents ab55b0d + 4714049 commit 43c43f6

File tree

3 files changed

+91
-21
lines changed

3 files changed

+91
-21
lines changed

lib/galaxy/tool_util/data/__init__.py

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ def _add_entry(
211211
persist: bool = False,
212212
entry_source: EntrySource = None,
213213
tool_data_file_path: Optional[str] = None,
214-
use_first_file_path: bool = False,
214+
bundle_mode: bool = False,
215215
**kwd,
216216
) -> None:
217217
raise NotImplementedError("Abstract method")
@@ -223,7 +223,7 @@ def add_entry(
223223
persist: bool = False,
224224
entry_source: EntrySource = None,
225225
tool_data_file_path: Optional[str] = None,
226-
use_first_file_path: bool = False,
226+
bundle_mode: bool = False,
227227
**kwd,
228228
) -> int:
229229
self._add_entry(
@@ -232,7 +232,7 @@ def add_entry(
232232
persist=persist,
233233
entry_source=entry_source,
234234
tool_data_file_path=tool_data_file_path,
235-
use_first_file_path=use_first_file_path,
235+
bundle_mode=bundle_mode,
236236
**kwd,
237237
)
238238
return self._update_version()
@@ -670,7 +670,7 @@ def _add_entry(
670670
persist: bool = False,
671671
entry_source: EntrySource = None,
672672
tool_data_file_path: Optional[str] = None,
673-
use_first_file_path: bool = False,
673+
bundle_mode: bool = False,
674674
**kwd,
675675
) -> None:
676676
# accepts dict or list of columns
@@ -703,19 +703,9 @@ def _add_entry(
703703
raise MessageException(
704704
f"Attempted to add fields ({fields}) to data table '{self.name}', but there were not enough fields specified ( {len(fields)} < {self.largest_index + 1} )."
705705
)
706-
filename = None
707706

708707
if persist:
709-
if tool_data_file_path is not None:
710-
filename = tool_data_file_path
711-
if os.path.realpath(filename) not in [os.path.realpath(n) for n in self.filenames]:
712-
raise MessageException(f"Path '{tool_data_file_path}' is not a known data table file path.")
713-
elif not use_first_file_path:
714-
filename = self.get_filename_for_source(entry_source)
715-
else:
716-
for name in self.filenames:
717-
filename = name
718-
break
708+
filename = self._locate_filename(tool_data_file_path, entry_source, bundle_mode)
719709
if filename is None:
720710
# If we reach this point, there is no data table with a corresponding .loc file.
721711
raise MessageException(
@@ -742,6 +732,19 @@ def _add_entry(
742732
fields_collapsed = f"{self.separator.join(fields)}\n"
743733
data_table_fh.write(fields_collapsed.encode("utf-8"))
744734

735+
def _locate_filename(self, tool_data_file_path, entry_source, bundle_mode):
736+
if tool_data_file_path is not None:
737+
filename = tool_data_file_path
738+
if os.path.realpath(filename) not in [os.path.realpath(n) for n in self.filenames]:
739+
raise MessageException(f"Path '{tool_data_file_path}' is not a known data table file path.")
740+
elif not bundle_mode:
741+
filename = self.get_filename_for_source(entry_source)
742+
else:
743+
for name in self.filenames:
744+
filename = name
745+
break
746+
return filename
747+
745748
def _remove_entry(self, values):
746749
# update every file
747750
for filename in self.filenames:
@@ -1183,7 +1186,7 @@ def import_bundle(
11831186
bundle = DataTableBundle(**index)
11841187
assert bundle.output_name
11851188
out_data = {bundle.output_name: DirectoryAsExtraFiles(target_directory)}
1186-
return _process_bundle(out_data, bundle, options, self)
1189+
return _process_bundle(out_data, bundle, options, self, bundle_mode=True)
11871190

11881191
def write_bundle(
11891192
self,
@@ -1255,6 +1258,7 @@ def _process_bundle(
12551258
bundle: DataTableBundle,
12561259
options: BundleProcessingOptions,
12571260
tool_data_tables: ToolDataTableManager,
1261+
bundle_mode: bool = False,
12581262
):
12591263
updated_data_tables = []
12601264
data_tables_dict = bundle.data_tables
@@ -1319,7 +1323,7 @@ def _process_bundle(
13191323
persist=True,
13201324
entry_source=bundle.repo_info,
13211325
tool_data_file_path=options.tool_data_file_path,
1322-
use_first_file_path=True,
1326+
bundle_mode=bundle_mode,
13231327
)
13241328
# Removes data table entries
13251329
for data_table_row in data_table_remove_values:
@@ -1344,7 +1348,12 @@ def _process_bundle(
13441348
for name, value in data_table_row.items():
13451349
if name in path_column_names:
13461350
data_table_value[name] = os.path.abspath(os.path.join(options.data_manager_path, value))
1347-
data_table.add_entry(data_table_value, persist=True, entry_source=bundle.repo_info)
1351+
data_table.add_entry(
1352+
data_table_value,
1353+
persist=True,
1354+
entry_source=bundle.repo_info,
1355+
bundle_mode=bundle_mode,
1356+
)
13481357
updated_data_tables.append(data_table_name)
13491358
else:
13501359
for data_table_name, data_table_values in data_tables_dict.items():

lib/galaxy/workflow/modules.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,10 +1507,15 @@ def callback(input, prefixed_name, context, **kwargs):
15071507
subworkflow_input_name = connection.input_name
15081508
for step in module.subworkflow.input_steps:
15091509
if step.input_type == "parameter" and step.label == subworkflow_input_name:
1510+
# static_options are raw tuples, convert to ParameterOption namedtuples
1511+
# to match ToolModule path and support intersection logic
15101512
static_options.append(
1511-
step.module.get_runtime_inputs(step, connections=step.output_connections)[
1512-
"input"
1513-
].static_options
1513+
[
1514+
ParameterOption(*o)
1515+
for o in step.module.get_runtime_inputs(step, connections=step.output_connections)[
1516+
"input"
1517+
].static_options
1518+
]
15141519
)
15151520

15161521
options: Optional[list[OptionDict]] = None

lib/galaxy_test/api/test_workflows.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7799,6 +7799,62 @@ def test_value_restriction_with_select_from_subworkflow_input(self):
77997799
assert len(options) == 5
78007800
assert options[0] == ["Ex1", "--ex1", False]
78017801

7802+
def test_value_restriction_with_select_from_multiple_subworkflow_inputs(self):
7803+
# Regression test for https://github.com/galaxyproject/galaxy/issues/21602
7804+
# When a workflow input with restrictOnConnections connects to multiple subworkflows,
7805+
# the options should be the intersection of all connected subworkflow options.
7806+
workflow_id = self.workflow_populator.upload_yaml_workflow(
7807+
"""
7808+
class: GalaxyWorkflow
7809+
inputs:
7810+
Outer input parameter:
7811+
optional: false
7812+
restrictOnConnections: true
7813+
type: string
7814+
steps:
7815+
- in:
7816+
inner input parameter:
7817+
source: Outer input parameter
7818+
run:
7819+
class: GalaxyWorkflow
7820+
label: First subworkflow
7821+
inputs:
7822+
inner input parameter:
7823+
optional: false
7824+
restrictOnConnections: true
7825+
type: string
7826+
steps:
7827+
- tool_id: multi_select
7828+
in:
7829+
select_ex:
7830+
source: inner input parameter
7831+
- in:
7832+
inner input parameter:
7833+
source: Outer input parameter
7834+
run:
7835+
class: GalaxyWorkflow
7836+
label: Second subworkflow
7837+
inputs:
7838+
inner input parameter:
7839+
optional: false
7840+
restrictOnConnections: true
7841+
type: string
7842+
steps:
7843+
- tool_id: multi_select
7844+
in:
7845+
select_ex:
7846+
source: inner input parameter
7847+
"""
7848+
)
7849+
with self.dataset_populator.test_history() as history_id:
7850+
run_workflow = self._download_workflow(workflow_id, style="run", history_id=history_id)
7851+
options = run_workflow["steps"][0]["inputs"][0]["options"]
7852+
# Both subworkflows use multi_select with same options, so intersection should have all 5 options
7853+
assert len(options) == 5
7854+
# Options are sorted by label when there are multiple connections
7855+
option_values = {opt[1] for opt in options}
7856+
assert option_values == {"--ex1", "ex2", "--ex3", "--ex4", "ex5"}
7857+
78027858
@skip_without_tool("random_lines1")
78037859
def test_run_replace_params_by_tool(self):
78047860
workflow_request, history_id, workflow_id = self._setup_random_x2_workflow("test_for_replace_tool_params")

0 commit comments

Comments
 (0)