Skip to content

Commit 6dc1477

Browse files
author
Anton Khodak
authored
Merge branch 'master' into fix/no-compute-checksum
2 parents e2ce8d3 + af59ba2 commit 6dc1477

File tree

9 files changed

+104
-11
lines changed

9 files changed

+104
-11
lines changed

cwltool/builder.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ def generate_arg(self, binding): # type: (Dict[Text,Any]) -> List[Text]
217217

218218
prefix = binding.get("prefix")
219219
sep = binding.get("separate", True)
220+
if prefix is None and not sep:
221+
with SourceLine(binding, "separate", WorkflowException, _logger.isEnabledFor(logging.DEBUG)):
222+
raise WorkflowException("'separate' option can not be specified without prefix")
220223

221224
l = [] # type: List[Dict[Text,Text]]
222225
if isinstance(value, list):
@@ -249,8 +252,8 @@ def generate_arg(self, binding): # type: (Dict[Text,Any]) -> List[Text]
249252

250253
return [a for a in args if a is not None]
251254

252-
def do_eval(self, ex, context=None, pull_image=True, recursive=False):
253-
# type: (Union[Dict[Text, Text], Text], Any, bool, bool) -> Any
255+
def do_eval(self, ex, context=None, pull_image=True, recursive=False, strip_whitespace=True):
256+
# type: (Union[Dict[Text, Text], Text], Any, bool, bool, bool) -> Any
254257
if recursive:
255258
if isinstance(ex, dict):
256259
return {k: self.do_eval(v, context, pull_image, recursive) for k, v in iteritems(ex)}
@@ -265,4 +268,5 @@ def do_eval(self, ex, context=None, pull_image=True, recursive=False):
265268
timeout=self.timeout,
266269
debug=self.debug,
267270
js_console=self.js_console,
268-
force_docker_pull=self.force_docker_pull)
271+
force_docker_pull=self.force_docker_pull,
272+
strip_whitespace=strip_whitespace)

cwltool/draft2tool.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ def rm_pending_output_callback(output_callbacks, jobcachepending,
383383
else:
384384
for t in initialWorkdir["listing"]:
385385
if "entry" in t:
386-
et = {u"entry": builder.do_eval(t["entry"])}
386+
et = {u"entry": builder.do_eval(t["entry"], strip_whitespace=False)}
387387
if "entryname" in t:
388388
et["entryname"] = builder.do_eval(t["entryname"])
389389
else:

cwltool/expression.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,10 @@ def evaluator(ex, jslib, obj, fullJS=False, timeout=None, force_docker_pull=Fals
173173

174174
def interpolate(scan, rootvars,
175175
timeout=None, fullJS=None, jslib="", force_docker_pull=False,
176-
debug=False, js_console=False):
177-
# type: (Text, Dict[Text, Any], int, bool, Union[str, Text], bool, bool, bool) -> JSON
178-
scan = scan.strip()
176+
debug=False, js_console=False, strip_whitespace=True):
177+
# type: (Text, Dict[Text, Any], int, bool, Union[str, Text], bool, bool, bool, bool) -> JSON
178+
if strip_whitespace:
179+
scan = scan.strip()
179180
parts = []
180181
w = scanner(scan)
181182
while w:
@@ -202,8 +203,9 @@ def interpolate(scan, rootvars,
202203

203204

204205
def do_eval(ex, jobinput, requirements, outdir, tmpdir, resources,
205-
context=None, pull_image=True, timeout=None, force_docker_pull=False, debug=False, js_console=False):
206-
# type: (Union[dict, AnyStr], Dict[Text, Union[Dict, List, Text]], List[Dict[Text, Any]], Text, Text, Dict[Text, Union[int, Text]], Any, bool, int, bool, bool, bool) -> Any
206+
context=None, pull_image=True, timeout=None, force_docker_pull=False,
207+
debug=False, js_console=False, strip_whitespace=True):
208+
# type: (Union[dict, AnyStr], Dict[Text, Union[Dict, List, Text]], List[Dict[Text, Any]], Text, Text, Dict[Text, Union[int, Text]], Any, bool, int, bool, bool, bool, bool) -> Any
207209

208210
runtime = copy.copy(resources)
209211
runtime["tmpdir"] = docker_windows_path_adjust(tmpdir)
@@ -231,7 +233,8 @@ def do_eval(ex, jobinput, requirements, outdir, tmpdir, resources,
231233
jslib=jslib,
232234
force_docker_pull=force_docker_pull,
233235
debug=debug,
234-
js_console=js_console)
236+
js_console=js_console,
237+
strip_whitespace=strip_whitespace)
235238

236239
except Exception as e:
237240
raise WorkflowException("Expression evaluation error:\n%s" % e)

cwltool/load_tool.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from avro.schema import Names
2121
from ruamel.yaml.comments import CommentedMap, CommentedSeq
2222
from schema_salad.ref_resolver import ContextType, Fetcher, Loader, file_uri
23-
from schema_salad.sourceline import cmap
23+
from schema_salad.sourceline import cmap, SourceLine
2424
from schema_salad.validate import ValidationException
2525

2626
from . import process, update
@@ -124,6 +124,9 @@ def _convert_stdstreams_to_files(workflowobj):
124124
if isinstance(workflowobj, dict):
125125
if workflowobj.get('class') == 'CommandLineTool':
126126
for out in workflowobj.get('outputs', []):
127+
if type(out) is not CommentedMap:
128+
with SourceLine(workflowobj, "outputs", ValidationException, _logger.isEnabledFor(logging.DEBUG)):
129+
raise ValidationException("Output '%s' is not a valid OutputParameter." % out)
127130
for streamtype in ['stdout', 'stderr']:
128131
if out.get('type') == streamtype:
129132
if 'outputBinding' in out:

tests/test_examples.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from io import StringIO
99

10+
from cwltool.errors import WorkflowException
1011
from cwltool.utils import onWindows
1112

1213
try:
@@ -525,6 +526,20 @@ def test_lifting(self):
525526
echo = f.make(get_data("tests/test_bad_outputs_wf.cwl"))
526527
self.assertEqual(echo(inp="foo"), {"out": "foo\n"})
527528

529+
def test_malformed_outputs(self):
530+
# check that tool validation fails if one of the outputs is not a valid CWL type
531+
f = cwltool.factory.Factory()
532+
with self.assertRaises(schema_salad.validate.ValidationException):
533+
echo = f.make(get_data("tests/wf/malformed_outputs.cwl"))
534+
echo()
535+
536+
def test_separate_without_prefix(self):
537+
# check that setting 'separate = false' on an inputBinding without prefix fails the workflow
538+
with self.assertRaises(WorkflowException):
539+
f = cwltool.factory.Factory()
540+
echo = f.make(get_data("tests/wf/separate_without_prefix.cwl"))
541+
echo()
542+
528543

529544
def test_checker(self):
530545
# check that the static checker raises exception when a source type

tests/test_iwdr.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import unittest
2+
3+
import cwltool
4+
import cwltool.factory
5+
from .util import get_data
6+
7+
8+
class TestInitialWorkDir(unittest.TestCase):
9+
10+
def test_newline_in_entry(self):
11+
"""
12+
test that files in InitialWorkingDirectory are created with a newline character
13+
"""
14+
f = cwltool.factory.Factory()
15+
echo = f.make(get_data("tests/wf/iwdr-entry.cwl"))
16+
self.assertEqual(echo(message="hello"), {"out": "CONFIGVAR=hello\n"})

tests/wf/iwdr-entry.cwl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env cwl-runner
2+
3+
class: CommandLineTool
4+
cwlVersion: v1.0
5+
baseCommand: ["cat", "example.conf"]
6+
7+
requirements:
8+
InitialWorkDirRequirement:
9+
listing:
10+
- entryname: example.conf
11+
entry: |
12+
CONFIGVAR=$(inputs.message)
13+
14+
inputs:
15+
message: string
16+
outputs:
17+
out:
18+
type: string
19+
outputBinding:
20+
glob: example.conf
21+
loadContents: true
22+
outputEval: $(self[0].contents)

tests/wf/malformed_outputs.cwl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
cwlVersion: v1.0
2+
class: CommandLineTool
3+
baseCommand: echo
4+
5+
inputs:
6+
[]
7+
outputs:
8+
-

tests/wf/separate_without_prefix.cwl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
cwlVersion: v1.0
2+
class: CommandLineTool
3+
baseCommand: echo
4+
5+
inputs:
6+
src:
7+
type: string
8+
default:
9+
string
10+
inputBinding:
11+
position: 1
12+
separate: false
13+
14+
stdout: output.txt
15+
16+
outputs:
17+
output:
18+
type: string
19+
outputBinding:
20+
glob: output.txt
21+
loadContents: true
22+
outputEval: $(self[0].contents)

0 commit comments

Comments
 (0)