Skip to content

Commit

Permalink
extend validation to the inputs of the top level proces
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-c committed Oct 2, 2023
1 parent cf3e49f commit 83b99b4
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 2 deletions.
3 changes: 3 additions & 0 deletions cwltool/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import copy
import os
import shutil
import sys
import tempfile
import threading
from typing import (
Expand Down Expand Up @@ -197,6 +198,8 @@ def __init__(self, kwargs: Optional[Dict[str, Any]] = None) -> None:
self.mpi_config: MpiConfig = MpiConfig()
self.default_stdout: Optional[Union[IO[bytes], TextIO]] = None
self.default_stderr: Optional[Union[IO[bytes], TextIO]] = None
self.validate_only: bool = False
self.validate_stdout: Union[IO[bytes], TextIO, IO[str]] = sys.stdout
super().__init__(kwargs)
if self.tmp_outdir_prefix == "":
self.tmp_outdir_prefix = self.tmpdir_prefix
Expand Down
12 changes: 12 additions & 0 deletions cwltool/executors.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ def check_for_abstract_op(tool: CWLObjectType) -> None:
process.requirements.append(req)

self.run_jobs(process, job_order_object, logger, runtime_context)
if runtime_context.validate_only is True:
return (None, "ValidationSuccess")

if self.final_output and self.final_output[0] is not None and finaloutdir is not None:
self.final_output[0] = relocateOutputs(
Expand Down Expand Up @@ -238,6 +240,16 @@ def run_jobs(
process_run_id = prov_obj.record_process_start(process, job)
runtime_context = runtime_context.copy()
runtime_context.process_run_id = process_run_id
if runtime_context.validate_only is True:
if isinstance(job, WorkflowJob):
name = job.tool.lc.filename
else:
name = getattr(job, "name", str(job))
print(
f"{name} is valid CWL. No errors detected in the inputs.",
file=runtime_context.validate_stdout,
)
return
job.run(runtime_context)
else:
logger.error("Workflow cannot make any more progress.")
Expand Down
6 changes: 5 additions & 1 deletion cwltool/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,7 @@ def main(
make_template(tool, stdout)
return 0

if args.validate:
if len(args.job_order) == 0 and args.validate:
print(f"{args.workflow} is valid CWL.", file=stdout)
return 0

Expand Down Expand Up @@ -1294,10 +1294,14 @@ def main(
use_biocontainers=args.beta_use_biocontainers,
container_image_cache_path=args.beta_dependencies_directory,
)
runtimeContext.validate_only = args.validate
runtimeContext.validate_stdout = stdout

(out, status) = real_executor(
tool, initialized_job_order_object, runtimeContext, logger=_logger
)
if runtimeContext.validate_only is True:
return 0

if out is not None:
if runtimeContext.research_obj is not None:
Expand Down
40 changes: 39 additions & 1 deletion tests/test_validate.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Tests --validation."""

import re

from .util import get_data, get_main_output

Expand All @@ -14,3 +14,41 @@ def test_validate_graph_with_no_default() -> None:
assert "packed_no_main.cwl#cat is valid CWL" in stdout
assert "packed_no_main.cwl#collision is valid CWL" in stdout
assert "tests/wf/packed_no_main.cwl is valid CWL" in stdout


def test_validate_with_valid_input_object() -> None:
"""Ensure that --validate with a valid input object."""
exit_code, stdout, stderr = get_main_output(
[
"--validate",
get_data("tests/wf/1st-workflow.cwl"),
"--inp",
get_data("tests/wf/1st-workflow.cwl"),
"--ex",
"FOO",
]
)
assert exit_code == 0
assert "tests/wf/1st-workflow.cwl is valid CWL. No errors detected in the inputs." in stdout


def test_validate_with_invalid_input_object() -> None:
"""Ensure that --validate with an invalid input object."""
exit_code, stdout, stderr = get_main_output(
[
"--validate",
get_data("tests/wf/1st-workflow.cwl"),
get_data("tests/wf/1st-workflow_bad_inputs.yml"),
]
)
assert exit_code == 1
stderr = re.sub(r"\s\s+", " ", stderr)
assert "Invalid job input record" in stderr
assert (
"tests/wf/1st-workflow_bad_inputs.yml:2:1: * the 'ex' field is not "
"valid because the value is not string" in stderr
)
assert (
"tests/wf/1st-workflow_bad_inputs.yml:1:1: * the 'inp' field is not "
"valid because is not a dict. Expected a File object." in stderr
)
4 changes: 4 additions & 0 deletions tests/wf/1st-workflow_bad_inputs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
inp: 42
ex:
class: File
path: 1st-workflow.cwl

0 comments on commit 83b99b4

Please sign in to comment.