Skip to content

Commit aa84e87

Browse files
committed
expression refactor: fix workflow output pickValue
also log error and keep going and add another test
1 parent 11dd5ec commit aa84e87

File tree

5 files changed

+97
-35
lines changed

5 files changed

+97
-35
lines changed

cwl_utils/cwl_expression_refactor.py

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
from ruamel import yaml
2323

24+
from cwl_utils.errors import WorkflowException
2425
from cwl_utils.loghandler import _logger as _cwlutilslogger
2526

2627
if TYPE_CHECKING:
@@ -103,6 +104,7 @@ def main(args: Optional[List[str]] = None) -> int:
103104

104105
def run(args: argparse.Namespace) -> int:
105106
"""Primary processing loop."""
107+
return_code = 0
106108
for document in args.inputs:
107109
_logger.info("Processing %s.", document)
108110
with open(document) as doc_handle:
@@ -128,39 +130,44 @@ def run(args: argparse.Namespace) -> int:
128130
"Sorry, %s is not a supported CWL version by this tool.", version
129131
)
130132
return -1
131-
result, modified = traverse(
132-
top, not args.etools, False, args.skip_some1, args.skip_some2
133-
)
134-
output = Path(args.dir) / Path(document).name
135-
if not modified:
136-
if len(args.inputs) > 1:
137-
shutil.copyfile(document, output)
138-
continue
139-
else:
140-
return 7
141-
if not isinstance(result, MutableSequence):
142-
result_json = save(
143-
result,
144-
base_url=result.loadingOptions.fileuri
145-
if result.loadingOptions.fileuri
146-
else "",
133+
try:
134+
result, modified = traverse(
135+
top, not args.etools, False, args.skip_some1, args.skip_some2
147136
)
148-
# ^^ Setting the base_url and keeping the default value
149-
# for relative_uris=True means that the IDs in the generated
150-
# JSON/YAML are kept clean of the path to the input document
151-
else:
152-
result_json = [
153-
save(result_item, base_url=result_item.loadingOptions.fileuri)
154-
for result_item in result
155-
]
156-
yaml.scalarstring.walk_tree(result_json)
157-
# ^ converts multiline strings to nice multiline YAML
158-
with open(output, "w", encoding="utf-8") as output_filehandle:
159-
output_filehandle.write(
160-
"#!/usr/bin/env cwl-runner\n"
161-
) # TODO: teach the codegen to do this?
162-
yaml.main.round_trip_dump(result_json, output_filehandle)
163-
return 0
137+
output = Path(args.dir) / Path(document).name
138+
if not modified:
139+
if len(args.inputs) > 1:
140+
shutil.copyfile(document, output)
141+
continue
142+
else:
143+
return 7
144+
if not isinstance(result, MutableSequence):
145+
result_json = save(
146+
result,
147+
base_url=result.loadingOptions.fileuri
148+
if result.loadingOptions.fileuri
149+
else "",
150+
)
151+
# ^^ Setting the base_url and keeping the default value
152+
# for relative_uris=True means that the IDs in the generated
153+
# JSON/YAML are kept clean of the path to the input document
154+
else:
155+
result_json = [
156+
save(result_item, base_url=result_item.loadingOptions.fileuri)
157+
for result_item in result
158+
]
159+
yaml.scalarstring.walk_tree(result_json)
160+
# ^ converts multiline strings to nice multiline YAML
161+
with open(output, "w", encoding="utf-8") as output_filehandle:
162+
output_filehandle.write(
163+
"#!/usr/bin/env cwl-runner\n"
164+
) # TODO: teach the codegen to do this?
165+
yaml.main.round_trip_dump(result_json, output_filehandle)
166+
except WorkflowException as exc:
167+
return_code = 1
168+
_logger.exception("Skipping %s due to error.", document, exc_info=exc)
169+
170+
return return_code
164171

165172

166173
if __name__ == "__main__":

cwl_utils/cwl_v1_2_expression_refactor.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -602,11 +602,11 @@ def example_input(some_type: Any) -> Any:
602602
)
603603

604604
PICKVALUE_FIRST_NON_NULL_EXPR = """${
605-
self.forEach(function(item) {
606-
if (item !== null){
605+
for (let i = 0; i < self.length; i++) {
606+
if (self[i] !== null){
607607
return self[i];
608608
}
609-
})
609+
}
610610
throw 'pickValue=first_non_null, but no non-null value found: ' + self;
611611
}
612612
"""

testdata/cond-wf-003.1.cwl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
class: Workflow
2+
cwlVersion: v1.2
3+
inputs:
4+
val: int
5+
6+
steps:
7+
8+
step1:
9+
in:
10+
in1: val
11+
a_new_var: val
12+
run: foo.cwl
13+
when: $(inputs.in1 < 1)
14+
out: [out1]
15+
16+
step2:
17+
in:
18+
in1: val
19+
a_new_var: val
20+
run: foo.cwl
21+
when: $(inputs.a_new_var > 2)
22+
out: [out1]
23+
24+
outputs:
25+
out1:
26+
type: string
27+
outputSource:
28+
- step1/out1
29+
- step2/out1
30+
pickValue: first_non_null
31+
32+
requirements:
33+
InlineJavascriptRequirement: {}
34+
MultipleInputFeatureRequirement: {}

testdata/foo.cwl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class: CommandLineTool
2+
cwlVersion: v1.2
3+
inputs:
4+
in1: int
5+
baseCommand: [echo]
6+
outputs:
7+
out1:
8+
type: string
9+
outputBinding:
10+
outputEval: foo $(inputs.in1)

tests/test_etools_to_clt.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,17 @@ def test_v1_2_step_valuefrom_expr_sibling_inputs() -> None:
212212
)
213213

214214

215+
def test_v1_2_workflow_output_pickvalue_expr() -> None:
216+
"""Convert a workflow output pickValue expression."""
217+
result, modified = traverse2(
218+
parser2.load_document(str(HERE / "../testdata/cond-wf-003.1.cwl")),
219+
False,
220+
False,
221+
False,
222+
False,
223+
)
224+
225+
215226
@pytest.fixture(scope="session")
216227
def cwl_v1_0_dir(
217228
tmp_path_factory: TempPathFactory,

0 commit comments

Comments
 (0)