Skip to content

Commit 876e5bd

Browse files
authored
Fix algorithm for generating output names when output names clash (#1342)
1 parent 76c81f6 commit 876e5bd

File tree

3 files changed

+79
-3
lines changed

3 files changed

+79
-3
lines changed

cwltool/process.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,13 @@ def stage_files(
276276
targets[entry.target] = entry
277277
elif targets[entry.target].resolved != entry.resolved:
278278
if fix_conflicts:
279-
tgt = entry.target
279+
# find first key that does not clash with an existing entry in targets
280+
# start with entry.target + '_' + 2 and then keep incrementing the number till there is no clash
280281
i = 2
281-
tgt = "%s_%s" % (tgt, i)
282+
tgt = "%s_%s" % (entry.target, i)
282283
while tgt in targets:
283284
i += 1
284-
tgt = "%s_%s" % (tgt, i)
285+
tgt = "%s_%s" % (entry.target, i)
285286
targets[tgt] = pathmapper.update(
286287
key, entry.resolved, tgt, entry.type, entry.staged
287288
)

tests/scatter_numbers.cwl

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/usr/bin/env cwl-runner
2+
cwlVersion: v1.1
3+
class: Workflow
4+
5+
inputs:
6+
range:
7+
type: int
8+
outputs:
9+
output:
10+
type: File[]
11+
outputSource:
12+
generate_files/output
13+
14+
steps:
15+
generate_list:
16+
requirements:
17+
- class: InlineJavascriptRequirement
18+
run:
19+
class: ExpressionTool
20+
inputs:
21+
max:
22+
type: int
23+
default: 100
24+
outputs:
25+
numbers:
26+
type: int[]
27+
expression: |
28+
${
29+
var numberList = Array.apply(null, Array(inputs.max)).map(function(_, i) { return i});
30+
return { "numbers": numberList }
31+
}
32+
in:
33+
max: range
34+
out:
35+
- numbers
36+
generate_files:
37+
requirements:
38+
- class: ScatterFeatureRequirement
39+
scatter: number
40+
run:
41+
class: CommandLineTool
42+
inputs:
43+
number:
44+
type: int
45+
inputBinding:
46+
position: 10
47+
baseCommand: [ echo ]
48+
stdout: output.txt
49+
outputs:
50+
output:
51+
type: stdout
52+
in:
53+
number: generate_list/numbers
54+
out:
55+
- output

tests/test_examples.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,3 +1261,23 @@ def test_v1_0_arg_empty_prefix_separate_false() -> None:
12611261
)
12621262
assert "completed success" in stderr
12631263
assert error_code == 0
1264+
1265+
1266+
def test_scatter_output_filenames(tmpdir: py.path.local) -> None:
1267+
"""If a scatter step produces identically named output then confirm that the final output is renamed correctly."""
1268+
cwd = tmpdir.chdir()
1269+
rtc = RuntimeContext()
1270+
rtc.outdir = str(cwd)
1271+
factory = cwltool.factory.Factory(runtime_context=rtc)
1272+
output_names = ['output.txt', 'output.txt_2', 'output.txt_3']
1273+
scatter_workflow = factory.make(get_data("tests/scatter_numbers.cwl"))
1274+
result = scatter_workflow(range=3)
1275+
assert 'output' in result
1276+
1277+
locations = sorted([element['location'] for element in result['output']])
1278+
1279+
assert(
1280+
locations[0].endswith('output.txt') and
1281+
locations[1].endswith('output.txt_2') and
1282+
locations[2].endswith('output.txt_3')
1283+
), "Locations {} do not end with {}".format(locations, output_names)

0 commit comments

Comments
 (0)