Merge branch 'release_26.0' into dev

This commit is contained in:
mvdbeek
2026-03-09 17:27:59 +01:00
34 changed files with 157 additions and 41 deletions
+2
View File
@@ -3478,7 +3478,9 @@ class ExpressionTool(Tool):
output.extension if output.extension not in ("data", "expression.json") else copy_object.extension
)
require_metadata_regeneration = copy_object.extension != new_ext
visible = output.visible
output.copy_from(copy_object, include_metadata=not require_metadata_regeneration)
output.visible = visible
output.extension = new_ext
if require_metadata_regeneration:
if app.config.enable_celery_tasks:
+13 -13
View File
@@ -38,7 +38,7 @@ from .grouping import (
)
from .workflow_utils import (
is_runtime_value,
NO_REPLACEMENT,
NoReplacement,
runtime_to_json,
)
from .wrapped import flat_to_nested_state
@@ -184,33 +184,33 @@ def visit_input_values(
new_value = callback(**args)
# is this good enough ? feels very ugh
if new_value == [no_replacement_value]:
if isinstance(new_value, list) and len(new_value) == 1 and isinstance(new_value[0], NoReplacement):
# Single unspecified value in multiple="true" input with a single null input, pretend it's a singular value
new_value = no_replacement_value
if isinstance(new_value, list):
# Maybe mixed input, I guess tool defaults don't really make sense here ?
# Would e.g. be default dataset in multiple="true" input, you wouldn't expect the default to be inserted
# if other inputs are connected and provided.
new_value = [item if not item == no_replacement_value else None for item in new_value]
new_value = [item if not isinstance(item, NoReplacement) else None for item in new_value]
if no_replacement_value is REPLACE_ON_TRUTHY:
replace = bool(new_value)
else:
replace = new_value != no_replacement_value
replace = not isinstance(new_value, NoReplacement) and new_value != no_replacement_value
if replace:
input_values[input.name] = new_value
elif replace_optional_connections:
# Only used in workflow context
has_default = hasattr(input, "value")
if new_value is value is NO_REPLACEMENT or is_runtime_value(value):
# NO_REPLACEMENT means value was connected but left unspecified
if has_default:
# Use default if we have one
# Only used in workflow context.
# If we reach here the callback returned no_replacement_value,
# meaning the connected step did not produce a value (e.g. an
# omitted optional parameter_input). Only replace sentinel
# values (ConnectedValue, RuntimeValue, NO_REPLACEMENT) with
# the tool parameter's own default — preserve valid tool-state
# values for unconnected inputs.
if isinstance(value, NoReplacement) or is_runtime_value(value):
if hasattr(input, "value"):
input_values[input.name] = input.value
else:
# Should fail if input is not optional and does not have default value
# Effectively however depends on parameter implementation.
# We might want to raise an exception here, instead of depending on a tool parameter value error.
input_values[input.name] = None
def get_current_case(input, input_values):
@@ -732,13 +732,19 @@ class DatasetsService(ServiceBase, UsesVisualizationMixin):
"""
hda = self.hda_manager.get_accessible(history_content_id, trans.user)
self.hda_manager.ensure_dataset_on_disk(trans, hda)
file_ext = hda.metadata.spec.get(metadata_file).get("file_ext", metadata_file)
metadata_spec = hda.metadata.spec.get(metadata_file)
if metadata_spec is None:
raise galaxy_exceptions.RequestParameterInvalidException(f"Unknown metadata file: {metadata_file}")
file_ext = metadata_spec.get("file_ext", metadata_file)
fname = "".join(c in util.FILENAME_VALID_CHARS and c or "_" for c in hda.name)[0:150]
headers = {}
headers["Content-Type"] = "application/octet-stream"
headers["Content-Disposition"] = f'attachment; filename="Galaxy{hda.hid}-[{fname}].{file_ext}"'
mf = hda.metadata.get(metadata_file)
assert mf
if mf is None:
raise galaxy_exceptions.RequestParameterInvalidException(
f"Metadata file {metadata_file} is not set for this dataset"
)
file_path = mf.get_file_name()
if open_file:
return open(file_path, "rb"), headers
+50
View File
@@ -9577,6 +9577,56 @@ steps:
len(copied_collections_with_tags) > 0
), f"Should find copied collection with tags {collection_tags} in new history"
def test_pick_value_output_visible_with_hidden_inputs(self):
"""Test that pick_value output doesn't inherit hidden state from inputs."""
with self.dataset_populator.test_history() as history_id:
summary = self._run_workflow(
"""class: GalaxyWorkflow
inputs:
input_dataset:
type: data
outputs:
pick_out:
outputSource: pick_value/data_param
steps:
cat_skipped:
tool_id: cat1
in:
input1: input_dataset
when: $(false)
pick_value:
tool_id: pick_value
tool_state:
style_cond:
pick_style: first
type_cond:
param_type: data
pick_from:
- __index__: 0
value:
__class__: RuntimeValue
- __index__: 1
value:
__class__: RuntimeValue
in:
style_cond|type_cond|pick_from_0|value:
source: cat_skipped/out_file1
style_cond|type_cond|pick_from_1|value:
source: input_dataset
""",
test_data="""input_dataset:
value: 1.bed
type: File
""",
history_id=history_id,
)
invocation_details = self.workflow_populator.get_invocation(summary.invocation_id, step_details=True)
pick_value_hda = invocation_details["outputs"]["pick_out"]
dataset_details = self.dataset_populator.get_history_dataset_details(
history_id=history_id, content_id=pick_value_hda["id"]
)
assert dataset_details["visible"], "pick_value output should be visible even when inputs are hidden"
class TestAdminWorkflowsApi(BaseWorkflowsApiTestCase):
require_admin_user = True
@@ -0,0 +1,27 @@
- doc: |
Test that omitting an optional text parameter connected to an expression
tool that converts text to boolean produces false, correctly skipping
the conditional downstream step.
job:
required_input:
type: File
value: 1.fasta
outputs:
out:
asserts:
has_text:
text: "null"
- doc: |
Test that providing an optional text parameter connected to an expression
tool that converts text to boolean produces true, so the conditional
downstream step runs.
job:
required_input:
type: File
value: 1.fasta
optional_text: some_value
outputs:
out:
asserts:
has_size:
min: 1
@@ -0,0 +1,29 @@
class: GalaxyWorkflow
doc: |
Test that an omitted optional text parameter connected to an expression
tool (text→boolean conversion, like map_param_value) produces false,
allowing conditional (when) steps to be correctly skipped.
Regression test for https://github.com/galaxyproject/iwc/pull/1128
inputs:
required_input:
type: data
optional_text:
type: text
optional: true
outputs:
out:
outputSource: cat/out_file1
steps:
text_to_bool:
tool_id: expression_text_to_bool
in:
text_input:
source: optional_text
cat:
tool_id: cat
in:
input1:
source: required_input
when:
source: text_to_bool/bool_out
when: $(inputs.when)
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -6,7 +6,6 @@ classifiers =
Environment :: Console
Intended Audience :: Developers
Intended Audience :: Science/Research
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
-1
View File
@@ -5,7 +5,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: POSIX
Programming Language :: Python :: 3
@@ -0,0 +1,27 @@
<tool name="expression_text_to_bool" id="expression_text_to_bool" version="0.1.0" tool_type="expression">
<expression type="ecma5.1">
{
var value = $job.text_input;
if (value == "false" || value == "False") {
return {'bool_out': false};
}
return {'bool_out': !!value};
}
</expression>
<inputs>
<param type="text" label="Text input." name="text_input" />
</inputs>
<outputs>
<output type="boolean" name="bool_out" from="bool_out" />
</outputs>
<tests>
<test>
<param name="text_input" value="hello" />
<output name="bool_out" value_json="true" />
</test>
<test>
<param name="text_input" value="" />
<output name="bool_out" value_json="false" />
</test>
</tests>
</tool>
@@ -230,6 +230,7 @@
<tool file="expression_null_handling_integer.xml" />
<tool file="expression_null_handling_float.xml" />
<tool file="expression_null_handling_text.xml" />
<tool file="expression_text_to_bool.xml" />
<tool file="cheetah_casting.xml" />
<tool file="cheetah_problem_unbound_var.xml" />
<tool file="cheetah_problem_unbound_var_input.xml" />