diff --git a/cwltool/command_line_tool.py b/cwltool/command_line_tool.py index b11bb4bc3..d249c0200 100644 --- a/cwltool/command_line_tool.py +++ b/cwltool/command_line_tool.py @@ -1495,8 +1495,21 @@ def collect_output( ) primary["format"] = format_eval else: - for primary in aslist(result): - primary["format"] = format_field + + def recursively_insert(j_dict: Any, key: Any, val: Any) -> Any: + """Recursively insert a value into any dictionary.""" + if isinstance(j_dict, MutableSequence): + return [recursively_insert(x, key, val) for x in j_dict] + if isinstance(j_dict, MutableMapping): + if j_dict.get("class") == "File": + j_dict[key] = val + else: + return { + x: recursively_insert(y, key, val) for x, y in j_dict.items() + } + return j_dict + + result = recursively_insert(result, "format", format_field) # Ensure files point to local references outside of the run environment adjustFileObjs(result, revmap) diff --git a/tests/output_2D_file_format.cwl b/tests/output_2D_file_format.cwl new file mode 100644 index 000000000..621111061 --- /dev/null +++ b/tests/output_2D_file_format.cwl @@ -0,0 +1,29 @@ +#!/usr/bin/env cwl-runner +cwlVersion: v1.0 + +class: CommandLineTool + +baseCommand: 'true' + +requirements: + InlineJavascriptRequirement: {} + +inputs: {} + +outputs: + output_array: + type: {"type": "array", "items": {"type": "array", "items": "File"}} + outputBinding: + outputEval: | + ${ + var out2d = []; + for (var i = 0; i < 2; i++) { + var out1d = []; + for (var j = 0; j < 2; j++) { + out1d.push({"class": "File", "location": "../../filename.txt"}); + } + out2d.push(out1d); + } + return out2d; + } + format: some_format diff --git a/tests/test_2D.py b/tests/test_2D.py new file mode 100644 index 000000000..87d16ccf0 --- /dev/null +++ b/tests/test_2D.py @@ -0,0 +1,21 @@ +from pathlib import Path + +from .util import get_data, get_main_output + + +def test_output_2d_file_format(tmp_path: Path) -> None: + """A simple test for format tag fix for 2D output arrays.""" + + # still need to create 'filename.txt' as it is needed in output_2D_file_format.cwl + (tmp_path / "filename.txt").touch() + commands = [ + "--cachedir", + str(tmp_path / "foo"), # just so that the relative path of file works out + "--outdir", + str(tmp_path / "out"), + get_data("tests/output_2D_file_format.cwl"), + ] + + error_code, _, stderr = get_main_output(commands) + + assert error_code == 0, stderr