Skip to content

Commit

Permalink
test optional inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
mlin committed May 24, 2019
1 parent a70299b commit 8999de0
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 14 deletions.
33 changes: 19 additions & 14 deletions WDL/runtime/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
import WDL


# InputError


class CommandError(WDL.Error.RuntimeError):
pass

Expand Down Expand Up @@ -446,29 +443,37 @@ def map_files(v: WDL.Value.Base) -> WDL.Value.Base:
posix_inputs, lambda namespace, binding: map_files(copy.deepcopy(binding.rhs))
)

# Collect task declarations requiring evaluation.
decls_to_eval = {}
# initialize value environment with the inputs
container_env = []
for b in container_inputs:
assert isinstance(b, WDL.Env.Binding)
v = b.rhs
assert isinstance(v, WDL.Value.Base)
container_env = WDL.Env.bind(container_env, [], b.name, v)
vj = json.dumps(v.json)
logger.info("input {} -> {}".format(b.name, vj if len(vj) < 4096 else "(large)"))

# collect remaining declarations requiring evaluation.
decls_to_eval = []
for decl in (task.inputs or []) + (task.postinputs or []):
try:
WDL.Env.resolve(container_inputs, [], decl.name)
WDL.Env.resolve(container_env, [], decl.name)
except KeyError:
decls_to_eval[decl.name] = decl
decls_to_eval.append(decl)

# TODO: topsort decls_to_eval according to internal dependencies

container_env = container_inputs
for b in container_env:
assert isinstance(b, WDL.Env.Binding)
logger.info("input {} -> {}".format(b.name, json.dumps(b.rhs.json)))

# evaluate each declaration in order
# note: the write_* functions call container.add_files as a side-effect
stdlib = container.stdlib_input()
for decl in decls_to_eval.values():
for decl in decls_to_eval:
v = WDL.Value.Null()
if decl.expr:
v = decl.expr.eval(container_env, stdlib=stdlib)
logger.info("eval {} -> {}".format(decl.name, json.dumps(v.json)))
else:
assert decl.type.optional
vj = json.dumps(v.json)
logger.info("eval {} -> {}".format(decl.name, vj if len(vj) < 4096 else "(large)"))
container_env = WDL.Env.bind(container_env, [], decl.name, v)

return container_env
Expand Down
46 changes: 46 additions & 0 deletions tests/test_5taskrun.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,49 @@ def test_compound_files(self):
self.assertEqual(infile.read(), "Alyssa,")
with open(friends.value[1].value) as infile:
self.assertEqual(infile.read(), "Ben,")

def test_optional_inputs(self):
code = R"""
version 1.0
task defaults {
input {
String s0
String s1 = "ben"
String? s2
}
command {
echo "~{s0}"
echo "~{s1}"
echo "~{if (defined(s2)) then s2 else 'None'}"
}
output {
String out = read_string(stdout())
}
}
"""
outputs = self._test_task(code, WDL.Env.bind([], [], "s0", WDL.Value.String("alyssa")))
self.assertEqual(WDL.Env.resolve(outputs, [], "out").value, "alyssa\nben\nNone\n")

outputs = self._test_task(code,
WDL.Env.bind(WDL.Env.bind([], [], "s1", WDL.Value.String("cy")),
[], "s0", WDL.Value.String("alyssa")))
self.assertEqual(WDL.Env.resolve(outputs, [], "out").value, "alyssa\ncy\nNone\n")

outputs = self._test_task(code,
WDL.Env.bind(WDL.Env.bind([], [], "s2", WDL.Value.String("mallory")),
[], "s0", WDL.Value.String("alyssa")))
self.assertEqual(WDL.Env.resolve(outputs, [], "out").value, "alyssa\nben\nmallory\n")

# FIXME: need some restrictions on what File inputs can default to
self._test_task(R"""
version 1.0
task hacker {
File host_passwords = "/etc/passwd"
command {
>&2 cat "~{host_passwords}"
}
output {
String owned = read_string(stderr())
}
}
""")

0 comments on commit 8999de0

Please sign in to comment.