From 67aa64a089cfc50e9999ccdf550dfdae631a946e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 07:29:14 +0000 Subject: [PATCH 01/11] Update pytest requirement from <8.3,>=6.2 to >=6.2,<8.4 Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/6.2.0...8.3.1) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- setup.py | 2 +- test-requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index cd74658e8..748e97aae 100644 --- a/setup.py +++ b/setup.py @@ -151,7 +151,7 @@ test_suite="tests", tests_require=[ "bagit >= 1.6.4, < 1.9", - "pytest >= 6.2, < 8.3", + "pytest >= 6.2, < 8.4", "mock >= 2.0.0", "pytest-mock >= 1.10.0", "pytest-httpserver", diff --git a/test-requirements.txt b/test-requirements.txt index ce709ef96..e545ee65a 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,5 +1,5 @@ bagit>=1.6.4,<1.9 -pytest>= 6.2,< 8.3 +pytest>= 6.2,< 8.4 pytest-xdist>=3.2.0 # for the worksteal scheduler psutil # enhances pytest-xdist to allow "-n logical" pytest-httpserver From 8185991c49704f78bfd5fa57cdc5657d21f903bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 07:12:26 +0000 Subject: [PATCH 02/11] Bump mypy from 1.10.1 to 1.11.1 Bumps [mypy](https://github.com/python/mypy) from 1.10.1 to 1.11.1. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.10.1...v1.11.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 31c4c0211..628a75488 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.10.1 # also update pyproject.toml +mypy==1.11.1 # also update pyproject.toml ruamel.yaml>=0.16.0,<0.19 cwl-utils>=0.32 types-requests From f06f061bdcab4f076e03105a43f3eb43230f31a7 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" Date: Wed, 31 Jul 2024 22:31:11 +0200 Subject: [PATCH 03/11] mypy 1.11.x type fixes, the callback is not optional --- cwltool/command_line_tool.py | 2 +- cwltool/process.py | 2 +- cwltool/procgenerator.py | 6 +++--- cwltool/workflow.py | 4 ++-- cwltool/workflow_job.py | 8 ++++---- tests/test_context.py | 4 ++-- tests/test_load_tool.py | 4 ++-- tests/test_streaming.py | 4 ++-- tests/test_tmpdir.py | 4 ++-- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/cwltool/command_line_tool.py b/cwltool/command_line_tool.py index b11bb4bc3..7a4e8ff71 100644 --- a/cwltool/command_line_tool.py +++ b/cwltool/command_line_tool.py @@ -806,7 +806,7 @@ def remove_dirname(d: CWLObjectType) -> None: def job( self, job_order: CWLObjectType, - output_callbacks: Optional[OutputCallbackType], + output_callbacks: OutputCallbackType, runtimeContext: RuntimeContext, ) -> Generator[Union[JobBase, CallbackJob], None, None]: workReuse, _ = self.get_requirement("WorkReuse") diff --git a/cwltool/process.py b/cwltool/process.py index afbed8147..bde035118 100644 --- a/cwltool/process.py +++ b/cwltool/process.py @@ -1075,7 +1075,7 @@ def visit(self, op: Callable[[CommentedMap], None]) -> None: def job( self, job_order: CWLObjectType, - output_callbacks: Optional[OutputCallbackType], + output_callbacks: OutputCallbackType, runtimeContext: RuntimeContext, ) -> JobsGeneratorType: pass diff --git a/cwltool/procgenerator.py b/cwltool/procgenerator.py index 0f1801b2d..34c1e650f 100644 --- a/cwltool/procgenerator.py +++ b/cwltool/procgenerator.py @@ -30,7 +30,7 @@ def receive_output(self, jobout: Optional[CWLObjectType], processStatus: str) -> def job( self, job_order: CWLObjectType, - output_callbacks: Optional[OutputCallbackType], + output_callbacks: OutputCallbackType, runtimeContext: RuntimeContext, ) -> JobsGeneratorType: try: @@ -41,7 +41,7 @@ def job( while self.processStatus is None: yield None - if self.processStatus != "success" and output_callbacks: + if self.processStatus != "success": output_callbacks(self.jobout, self.processStatus) return @@ -89,7 +89,7 @@ def __init__( def job( self, job_order: CWLObjectType, - output_callbacks: Optional[OutputCallbackType], + output_callbacks: OutputCallbackType, runtimeContext: RuntimeContext, ) -> JobsGeneratorType: return ProcessGeneratorJob(self).job(job_order, output_callbacks, runtimeContext) diff --git a/cwltool/workflow.py b/cwltool/workflow.py index 727331dd4..982ec7e70 100644 --- a/cwltool/workflow.py +++ b/cwltool/workflow.py @@ -153,7 +153,7 @@ def make_workflow_step( def job( self, job_order: CWLObjectType, - output_callbacks: Optional[OutputCallbackType], + output_callbacks: OutputCallbackType, runtimeContext: RuntimeContext, ) -> JobsGeneratorType: builder = self._init_job(job_order, runtimeContext) @@ -420,7 +420,7 @@ def receive_output( def job( self, job_order: CWLObjectType, - output_callbacks: Optional[OutputCallbackType], + output_callbacks: OutputCallbackType, runtimeContext: RuntimeContext, ) -> JobsGeneratorType: """Initialize sub-workflow as a step in the parent profile.""" diff --git a/cwltool/workflow_job.py b/cwltool/workflow_job.py index e6c1f8d8a..8402b2b4b 100644 --- a/cwltool/workflow_job.py +++ b/cwltool/workflow_job.py @@ -65,7 +65,7 @@ def __init__(self, step: "WorkflowStep") -> None: def job( self, joborder: CWLObjectType, - output_callback: Optional[OutputCallbackType], + output_callback: OutputCallbackType, runtimeContext: RuntimeContext, ) -> JobsGeneratorType: runtimeContext = runtimeContext.copy() @@ -584,7 +584,7 @@ def receive_output( def try_make_job( self, step: WorkflowJobStep, - final_output_callback: Optional[OutputCallbackType], + final_output_callback: OutputCallbackType, runtimeContext: RuntimeContext, ) -> JobsGeneratorType: container_engine = "docker" @@ -773,7 +773,7 @@ def run( def job( self, joborder: CWLObjectType, - output_callback: Optional[OutputCallbackType], + output_callback: OutputCallbackType, runtimeContext: RuntimeContext, ) -> JobsGeneratorType: self.state = {} @@ -848,7 +848,7 @@ def job( else: yield None - if not self.did_callback and output_callback: + if not self.did_callback: # could have called earlier on line 336; self.do_output_callback(output_callback) # depends which one comes first. All steps are completed diff --git a/tests/test_context.py b/tests/test_context.py index 754216048..acb7dfbca 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -14,8 +14,8 @@ def test_replace_default_stdout_stderr() -> None: original_stdout = sys.stdout original_stderr = sys.stderr - sys.stdout = "" # type: ignore - sys.stderr = "" # type: ignore + sys.stdout = "" + sys.stderr = "" runtime_context = RuntimeContext() runtime_context.default_stdout = subprocess.DEVNULL # type: ignore diff --git a/tests/test_load_tool.py b/tests/test_load_tool.py index 2c504eafd..2b9e9b6ed 100644 --- a/tests/test_load_tool.py +++ b/tests/test_load_tool.py @@ -30,13 +30,13 @@ def test_check_version() -> None: joborder: CWLObjectType = {"inp": "abc"} loadingContext = LoadingContext({"do_update": True}) tool = load_tool(get_data("tests/echo.cwl"), loadingContext) - for _ in tool.job(joborder, None, RuntimeContext()): + for _ in tool.job(joborder, lambda output, process_status: None, RuntimeContext()): pass loadingContext = LoadingContext({"do_update": False}) tool = load_tool(get_data("tests/echo.cwl"), loadingContext) with pytest.raises(WorkflowException): - for _ in tool.job(joborder, None, RuntimeContext()): + for _ in tool.job(joborder, lambda output, process_status: None, RuntimeContext()): pass diff --git a/tests/test_streaming.py b/tests/test_streaming.py index 83ad81e0d..aef4a7efe 100644 --- a/tests/test_streaming.py +++ b/tests/test_streaming.py @@ -61,7 +61,7 @@ def test_regular_file() -> None: } } - job = next(clt.job(joborder, None, runtime_context)) + job = next(clt.job(joborder, lambda output, process_status: None, runtime_context)) assert isinstance(job, JobBase) job._setup(runtime_context) @@ -99,7 +99,7 @@ def test_input_can_be_named_pipe( } } - job = next(clt.job(joborder, None, runtime_context)) + job = next(clt.job(joborder, lambda output, process_status: None, runtime_context)) assert isinstance(job, JobBase) if raise_exception: diff --git a/tests/test_tmpdir.py b/tests/test_tmpdir.py index 2470a2515..73fe240d0 100644 --- a/tests/test_tmpdir.py +++ b/tests/test_tmpdir.py @@ -66,7 +66,7 @@ def test_docker_commandLineTool_job_tmpdir_prefix(tmp_path: Path) -> None: "tmp_outdir_prefix": tmp_outdir_prefix, } ) - job = next(clt.job({}, None, runtime_context)) + job = next(clt.job({}, lambda output, process_status: None, runtime_context)) assert isinstance(job, JobBase) assert job.stagedir and job.stagedir.startswith(tmpdir_prefix) assert job.tmpdir and job.tmpdir.startswith(tmpdir_prefix) @@ -106,7 +106,7 @@ def test_commandLineTool_job_tmpdir_prefix(tmp_path: Path) -> None: "tmp_outdir_prefix": tmp_outdir_prefix, } ) - job = next(clt.job({}, None, runtime_context)) + job = next(clt.job({}, lambda output, process_status: None, runtime_context)) assert isinstance(job, JobBase) assert job.stagedir and job.stagedir.startswith(tmpdir_prefix) assert job.tmpdir and job.tmpdir.startswith(tmpdir_prefix) From 67df61c8b3ea11f00d5f24c016e540b5c146d759 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 07:17:00 +0000 Subject: [PATCH 04/11] Update black requirement from ~=24.4 to ~=24.8 Updates the requirements on [black](https://github.com/psf/black) to permit the latest version. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/24.4.0...24.8.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index cad3da694..b728d78b2 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,3 +1,3 @@ flake8-bugbear<24.3 -black~=24.4 +black~=24.8 codespell From 73b742f54b24651dbe8e8a044c8d9a2860e35181 Mon Sep 17 00:00:00 2001 From: "Daniel S. Katz" Date: Sun, 18 Aug 2024 02:35:48 -0500 Subject: [PATCH 05/11] removing duplicate "reference" (#2030) Unless this was intentional? --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 2888f08bb..db40d0420 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ ############################################################################################# -``cwltool``: The reference reference implementation of the Common Workflow Language standards +``cwltool``: The reference implementation of the Common Workflow Language standards ############################################################################################# |Linux Status| |Coverage Status| |Docs Status| From 6d8c2a41e2c524e8d746020cc91711ecc3418a23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 07:09:16 +0000 Subject: [PATCH 06/11] Update flake8-bugbear requirement from <24.3 to <24.9 Updates the requirements on [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear) to permit the latest version. - [Release notes](https://github.com/PyCQA/flake8-bugbear/releases) - [Commits](https://github.com/PyCQA/flake8-bugbear/compare/16.4.1...24.8.19) --- updated-dependencies: - dependency-name: flake8-bugbear dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- lint-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lint-requirements.txt b/lint-requirements.txt index b728d78b2..b0d7944eb 100644 --- a/lint-requirements.txt +++ b/lint-requirements.txt @@ -1,3 +1,3 @@ -flake8-bugbear<24.3 +flake8-bugbear<24.9 black~=24.8 codespell From 26213120bcfe5818cbcf796c7b40c7186c0c5e39 Mon Sep 17 00:00:00 2001 From: Tomoya Tanjo Date: Mon, 9 Sep 2024 22:49:50 +0900 Subject: [PATCH 07/11] Support array of integers and floats as command argument parameters (#2037) --- cwltool/argparser.py | 5 +++ tests/test_toolargparse.py | 81 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/cwltool/argparser.py b/cwltool/argparser.py index f9d98e32d..efced5386 100644 --- a/cwltool/argparser.py +++ b/cwltool/argparser.py @@ -903,6 +903,11 @@ def add_argument( action = DirectoryAppendAction else: action = AppendAction + items = inptype["items"] + if items == "int" or items == "long": + atype = int + elif items == "double" or items == "float": + atype = float elif isinstance(inptype, MutableMapping) and inptype["type"] == "enum": atype = str elif isinstance(inptype, MutableMapping) and inptype["type"] == "record": diff --git a/tests/test_toolargparse.py b/tests/test_toolargparse.py index 756c373e8..11ce5e3db 100644 --- a/tests/test_toolargparse.py +++ b/tests/test_toolargparse.py @@ -101,6 +101,62 @@ outputs: [] """ +script_int = """ +#!/usr/bin/env cwl-runner + +cwlVersion: v1.0 +class: ExpressionTool + +inputs: + foo: int[] + +expression: '{"bar": $(inputs.foo)}' + +outputs: [] +""" + +script_long = """ +#!/usr/bin/env cwl-runner + +cwlVersion: v1.0 +class: ExpressionTool + +inputs: + foo: long[] + +expression: '{"bar": $(inputs.foo)}' + +outputs: [] +""" + +script_float = """ +#!/usr/bin/env cwl-runner + +cwlVersion: v1.0 +class: ExpressionTool + +inputs: + foo: float[] + +expression: '{"bar": $(inputs.foo)}' + +outputs: [] +""" + +script_double = """ +#!/usr/bin/env cwl-runner + +cwlVersion: v1.0 +class: ExpressionTool + +inputs: + foo: double[] + +expression: '{"bar": $(inputs.foo)}' + +outputs: [] +""" + scripts_argparse_params = [ ("help", script_a, lambda x: ["--debug", x, "--input", get_data("tests/echo.cwl")]), ("boolean", script_b, lambda x: [x, "--help"]), @@ -120,6 +176,31 @@ script_e, lambda x: [x, "--foo", "http://example.com"], ), + ( + "foo with int", + script_int, + lambda x: [x, "--foo", "1", "--foo", "2"], + ), + ( + "foo with long for large value", + script_long, + lambda x: [x, "--foo", str(2**31 + 10)], + ), + ( + "foo with long for small value", + script_long, + lambda x: [x, "--foo", str(-1 * (2**31) - 10)], + ), + ( + "foo with float", + script_float, + lambda x: [x, "--foo", "1.2", "--foo", "3.4"], + ), + ( + "foo with double", + script_double, + lambda x: [x, "--foo", "1.2", "--foo", "3.4"], + ), ] From eb0bba5effd03948400877c6649705977f9936c2 Mon Sep 17 00:00:00 2001 From: "Michael R. Crusoe" <1330696+mr-c@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:15:21 +0200 Subject: [PATCH 08/11] Explicitly support Python 3.13; add to CI matrix (#2040) --- .github/workflows/ci-tests.yml | 2 +- setup.py | 3 ++- tox.ini | 44 ++++++++++++++++++---------------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 29f281516..1530ab92b 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -32,7 +32,7 @@ jobs: strategy: matrix: py-ver-major: [3] - py-ver-minor: [8, 9, 10, 11, 12] + py-ver-minor: [8, 9, 10, 11, 12, 13] step: [lint, unit, bandit, mypy] env: diff --git a/setup.py b/setup.py index 748e97aae..9980276e5 100644 --- a/setup.py +++ b/setup.py @@ -145,7 +145,7 @@ "galaxy-util <24.2", ], }, - python_requires=">=3.8, <4", + python_requires=">=3.8, <3.14", use_scm_version=True, setup_requires=PYTEST_RUNNER + ["setuptools_scm>=8.0.4,<9"], test_suite="tests", @@ -176,6 +176,7 @@ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Bio-Informatics", "Topic :: Scientific/Engineering :: Astronomy", diff --git a/tox.ini b/tox.ini index 71562af10..c75d0cc47 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,9 @@ [tox] envlist = - py3{8,9,10,11,12}-lint - py3{8,9,10,11,12}-unit - py3{8,9,10,11,12}-bandit - py3{8,9,10,11,12}-mypy + py3{8,9,10,11,12,13}-lint + py3{8,9,10,11,12,13}-unit + py3{8,9,10,11,12,13}-bandit + py3{8,9,10,11,12,13}-mypy py312-lintreadme py312-shellcheck py312-pydocstyle @@ -21,16 +21,17 @@ python = 3.10: py310 3.11: py311 3.12: py312 + 3.13: py313 [testenv] skipsdist = - py3{8,9,10,11,12}-!{unit,mypy,lintreadme} = True + py3{8,9,10,11,12,13}-!{unit,mypy,lintreadme} = True description = - py3{8,9,10,11,12}-unit: Run the unit tests - py3{8,9,10,11,12}-lint: Lint the Python code - py3{8,9,10,11,12}-bandit: Search for common security issues - py3{8,9,10,11,12}-mypy: Check for type safety + py3{8,9,10,11,12,13}-unit: Run the unit tests + py3{8,9,10,11,12,13}-lint: Lint the Python code + py3{8,9,10,11,12,13}-bandit: Search for common security issues + py3{8,9,10,11,12,13}-mypy: Check for type safety py312-pydocstyle: docstring style checker py312-shellcheck: syntax check for shell scripts py312-lintreadme: Lint the README.rst→.md conversion @@ -43,14 +44,14 @@ passenv = SINGULARITY_FAKEROOT extras = - py3{8,9,10,11,12}-unit: deps + py3{8,9,10,11,12,13}-unit: deps deps = - py3{8,9,10,11,12}-{unit,lint,bandit,mypy}: -rrequirements.txt - py3{8,9,10,11,12}-{unit,mypy}: -rtest-requirements.txt - py3{8,9,10,11,12}-lint: -rlint-requirements.txt - py3{8,9,10,11,12}-bandit: bandit - py3{8,9,10,11,12}-mypy: -rmypy-requirements.txt + py3{8,9,10,11,12,13}-{unit,lint,bandit,mypy}: -rrequirements.txt + py3{8,9,10,11,12,13}-{unit,mypy}: -rtest-requirements.txt + py3{8,9,10,11,12,13}-lint: -rlint-requirements.txt + py3{8,9,10,11,12,13}-bandit: bandit + py3{8,9,10,11,12,13}-mypy: -rmypy-requirements.txt py312-pydocstyle: pydocstyle py312-pydocstyle: diff-cover py312-lintreadme: twine @@ -62,19 +63,20 @@ setenv = HOME = {envtmpdir} commands_pre = - py3{8,9,10,11,12}-unit: python -m pip install -U pip setuptools wheel + py3{8,9,10,11,12,13}-unit: python -m pip install -U pip setuptools wheel py312-lintreadme: python -m build --outdir {distdir} commands = - py3{8,9,10,11,12}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs} - py3{8,9,10,11,12}-bandit: bandit -r cwltool - py3{8,9,10,11,12}-lint: make flake8 format-check codespell-check - py3{8,9,10,11,12}-mypy: make mypy mypyc PYTEST_EXTRA={posargs} + py3{8,9,10,11,12,13}-unit: make coverage-report coverage.xml PYTEST_EXTRA={posargs} + py3{8,9,10,11,12,13}-bandit: bandit -r cwltool + py3{8,9,10,11,12,13}-lint: make flake8 format-check codespell-check + py3{8,9,10,11,12,13}-mypy: make mypy PYTEST_EXTRA={posargs} + py3{8,9,10,11,12}-mypy: make mypyc PYTEST_EXTRA={posargs} py312-shellcheck: make shellcheck py312-pydocstyle: make diff_pydocstyle_report py312-lintreadme: twine check {distdir}/* skip_install = - py3{8,9,10,11,12}-{bandit,lint,mypy,shellcheck,pydocstyle,lintreadme}: true + py3{8,9,10,11,12,13}-{bandit,lint,mypy,shellcheck,pydocstyle,lintreadme}: true allowlist_externals = make From 4046c49ff8be97b29e76f1fc4440602338270d41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 07:50:53 +0000 Subject: [PATCH 09/11] Bump mypy from 1.11.1 to 1.11.2 Bumps [mypy](https://github.com/python/mypy) from 1.11.1 to 1.11.2. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.11.1...v1.11.2) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- mypy-requirements.txt | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy-requirements.txt b/mypy-requirements.txt index 628a75488..a7d0dacb8 100644 --- a/mypy-requirements.txt +++ b/mypy-requirements.txt @@ -1,4 +1,4 @@ -mypy==1.11.1 # also update pyproject.toml +mypy==1.11.2 # also update pyproject.toml ruamel.yaml>=0.16.0,<0.19 cwl-utils>=0.32 types-requests diff --git a/pyproject.toml b/pyproject.toml index 1753a6175..05a2b82f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ requires = [ "setuptools>=45", "setuptools_scm[toml]>=8.0.4,<9", - "mypy==1.10.1", # also update mypy-requirements.txt + "mypy==1.11.2", # also update mypy-requirements.txt "types-requests", "types-psutil", "importlib_resources>=1.4;python_version<'3.9'", From 4bb5329997cb84562a40733b5c2f55600b1a741a Mon Sep 17 00:00:00 2001 From: Francis Charette-Migneault Date: Mon, 9 Sep 2024 12:49:51 -0400 Subject: [PATCH 10/11] fix `loadContents` for `File[]` (#2036) --- .gitignore | 3 ++- cwltool/builder.py | 4 ++-- tests/load_contents-1.txt | 1 + tests/load_contents-2.txt | 1 + tests/load_contents-array.cwl | 24 ++++++++++++++++++++++++ tests/load_contents-array.yml | 5 +++++ tests/test_load_contents.py | 22 ++++++++++++++++++++++ 7 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 tests/load_contents-1.txt create mode 100644 tests/load_contents-2.txt create mode 100644 tests/load_contents-array.cwl create mode 100644 tests/load_contents-array.yml create mode 100644 tests/test_load_contents.py diff --git a/.gitignore b/.gitignore index 5941627f8..fbe4b24fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # Generated during tests pytestdebug.log tmp/ +*.sif +involucro # Python temps __pycache__/ @@ -59,4 +61,3 @@ cwltool/_version.py cwltool_deps docs/_build/ docs/autoapi/ - diff --git a/cwltool/builder.py b/cwltool/builder.py index ff1c099e5..2ba1e6543 100644 --- a/cwltool/builder.py +++ b/cwltool/builder.py @@ -282,7 +282,7 @@ def bind_input( and "itemSeparator" not in binding ): st["inputBinding"] = {} - for k in ("secondaryFiles", "format", "streamable"): + for k in ("secondaryFiles", "format", "streamable", "loadContents"): if k in schema: st[k] = schema[k] if value_from_expression: @@ -349,7 +349,7 @@ def bind_input( "type": schema["items"], "inputBinding": b2, } - for k in ("secondaryFiles", "format", "streamable"): + for k in ("secondaryFiles", "format", "streamable", "loadContents"): if k in schema: itemschema[k] = schema[k] bindings.extend( diff --git a/tests/load_contents-1.txt b/tests/load_contents-1.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/tests/load_contents-1.txt @@ -0,0 +1 @@ +1 diff --git a/tests/load_contents-2.txt b/tests/load_contents-2.txt new file mode 100644 index 000000000..0cfbf0888 --- /dev/null +++ b/tests/load_contents-2.txt @@ -0,0 +1 @@ +2 diff --git a/tests/load_contents-array.cwl b/tests/load_contents-array.cwl new file mode 100644 index 000000000..f6b786ec6 --- /dev/null +++ b/tests/load_contents-array.cwl @@ -0,0 +1,24 @@ +cwlVersion: "v1.2" +class: CommandLineTool +baseCommand: echo +requirements: + InlineJavascriptRequirement: {} +inputs: + files: + type: + type: array + items: File + loadContents: true + inputBinding: + valueFrom: | + ${ + return JSON.stringify({ + "data": inputs.files.map(item => parseInt(item.contents)) + }); + } +outputs: + out: + type: File + outputBinding: + glob: "data.json" +stdout: "data.json" diff --git a/tests/load_contents-array.yml b/tests/load_contents-array.yml new file mode 100644 index 000000000..b7a919340 --- /dev/null +++ b/tests/load_contents-array.yml @@ -0,0 +1,5 @@ +files: + - class: File + path: load_contents-1.txt + - class: File + path: load_contents-2.txt diff --git a/tests/test_load_contents.py b/tests/test_load_contents.py new file mode 100644 index 000000000..36e9da2ab --- /dev/null +++ b/tests/test_load_contents.py @@ -0,0 +1,22 @@ +"""Test the loadContents feature.""" + +import json +from pathlib import Path + +from cwltool.main import main + +from .util import get_data + + +def test_load_contents_file_array(tmp_path: Path) -> None: + """Ensures that a File[] input with loadContents loads each file.""" + params = [ + "--outdir", + str(tmp_path), + get_data("tests/load_contents-array.cwl"), + str(Path(__file__) / "../load_contents-array.yml"), + ] + assert main(params) == 0 + with open(tmp_path / "data.json") as out_fd: + data = json.load(out_fd) + assert data == {"data": [1, 2]} From 55ccde7c2fe3e7899136ce8606a341e292d7050a Mon Sep 17 00:00:00 2001 From: Iacopo Colonnelli Date: Wed, 18 Sep 2024 12:22:02 +0200 Subject: [PATCH 11/11] Updated `outputMethod` values --- cwltool/checker.py | 7 ++++-- cwltool/errors.py | 4 +-- cwltool/schemas/v1.3.0-dev1/Workflow.yml | 25 ++++++++++--------- cwltool/update.py | 14 ++++++++--- cwltool/workflow_job.py | 10 ++++---- tests/loop/all-output-loop-no-iteration.cwl | 2 +- tests/loop/all-output-loop.cwl | 2 +- tests/loop/default-value-loop.cwl | 2 +- tests/loop/invalid-loop-scatter.cwl | 2 +- tests/loop/invalid-loop-when-exception.cwl | 2 +- tests/loop/invalid-loop-when-exception2.cwl | 2 +- ...valid-multi-source-loop-no-requirement.cwl | 2 +- tests/loop/invalid-no-loopWhen.cwl | 2 +- tests/loop/invalid-non-boolean-loopWhen.cwl | 2 +- tests/loop/invalid-non-boolean-loopWhen2.cwl | 2 +- ...invalid-value-from-loop-no-requirement.cwl | 2 +- tests/loop/loop-inside-loop-all.cwl | 4 +-- tests/loop/loop-inside-loop.cwl | 4 +-- tests/loop/loop-inside-scatter.cwl | 2 +- tests/loop/multi-source-loop.cwl | 2 +- tests/loop/opt-var-loop.cwl | 2 +- tests/loop/scatter-inside-loop.cwl | 2 +- tests/loop/single-var-loop-no-iteration.cwl | 2 +- tests/loop/single-var-loop.cwl | 2 +- tests/loop/two-vars-loop-2.cwl | 2 +- tests/loop/two-vars-loop.cwl | 2 +- tests/loop/value-from-loop.cwl | 2 +- tests/test_loop.py | 6 ++--- tests/test_path_checks.py | 6 ++--- 29 files changed, 65 insertions(+), 55 deletions(-) diff --git a/cwltool/checker.py b/cwltool/checker.py index 541d59440..676245698 100644 --- a/cwltool/checker.py +++ b/cwltool/checker.py @@ -517,10 +517,13 @@ def is_conditional_step(param_to_step: Dict[str, CWLObjectType], parm_id: str) - def is_all_output_method_loop_step(param_to_step: Dict[str, CWLObjectType], parm_id: str) -> bool: - """Check if a step contains a `loop` directive with `all` outputMethod.""" + """Check if a step contains a `loop` directive with `all_iterations` outputMethod.""" source_step: Optional[MutableMapping[str, Any]] = param_to_step.get(parm_id) if source_step is not None: - if source_step.get("loop") is not None and source_step.get("outputMethod") == "all": + if ( + source_step.get("loop") is not None + and source_step.get("outputMethod") == "all_iterations" + ): return True return False diff --git a/cwltool/errors.py b/cwltool/errors.py index 978078ec6..045b9b383 100644 --- a/cwltool/errors.py +++ b/cwltool/errors.py @@ -8,10 +8,8 @@ # flake8: noqa: F401 -from cwl_utils.errors import WorkflowException as WorkflowException - - from cwl_utils.errors import GraphTargetMissingException as GraphTargetMissingException +from cwl_utils.errors import WorkflowException as WorkflowException class UnsupportedRequirement(WorkflowException): diff --git a/cwltool/schemas/v1.3.0-dev1/Workflow.yml b/cwltool/schemas/v1.3.0-dev1/Workflow.yml index f83575b2a..3e4045a43 100644 --- a/cwltool/schemas/v1.3.0-dev1/Workflow.yml +++ b/cwltool/schemas/v1.3.0-dev1/Workflow.yml @@ -497,8 +497,8 @@ $graph: docParent: "#LoopWorkflowStep" doc: The loop output method, as described in [workflow step loop](#LoopWorkflowStep). symbols: - - last - - all + - last_iteration + - all_iterations - name: AbstractWorkflowStep @@ -705,14 +705,14 @@ $graph: The `outputMethod` field describes how to deal with loop outputs after termination: - * **last** specifies that only the last computed element for each output - parameter should be propagated to the subsequent steps. This is the - default value. + * **last_iteration** specifies that only the last computed element for + each output parameter should be propagated to the subsequent steps. + This is the default value. - * **all** specifies that an array with all output values computed at the - end of each loop iteration should be propagated to the subsequent steps. - Elements in the array must be ordered according to the loop iterations - that produced them. + * **all_iterations** specifies that an array with all output values + computed at the end of each loop iteration should be propagated to + the subsequent steps. Elements in the array must be ordered according + to the loop iterations that produced them. Iterative execution in CWL is an optional feature and is not required to be implemented by all consumers of CWL documents. An implementation that @@ -734,9 +734,9 @@ $graph: mapPredicate: outputSource - name: outputMethod doc: | - If not specified, the default method is "last". + If not specified, the default method is "last_iteration". type: LoopOutputMethod? - default: last + default: last_iteration jsonldPredicate: "_id": "cwl:outputMethod" "_type": "@vocab" @@ -748,7 +748,8 @@ $graph: Only run the next iteration when the expression evaluates to `true`. If the first iteration evaluates to `false` the step is skipped. A skipped step produces a `null` on each output if the `outputMethod` - is set to `last`, and an empty array if the `outputMethod` is set to `all`. + is set to `last_iteration`, and an empty array if the `outputMethod` + is set to `all_iterations`. - name: Workflow diff --git a/cwltool/update.py b/cwltool/update.py index 7b801f5dc..4fd66b37a 100644 --- a/cwltool/update.py +++ b/cwltool/update.py @@ -11,12 +11,11 @@ cast, ) +from ruamel.yaml.comments import CommentedMap, CommentedSeq from schema_salad.exceptions import ValidationException from schema_salad.ref_resolver import Loader from schema_salad.sourceline import SourceLine -from ruamel.yaml.comments import CommentedMap, CommentedSeq - from .loghandler import _logger from .utils import CWLObjectType, CWLOutputType, aslist, visit_class, visit_field @@ -51,7 +50,16 @@ def rewrite_loop_requirements(t: CWLObjectType) -> None: el["outputSource"] = source s["loop"] = r["loop"] if "outputMethod" in r: - s["outputMethod"] = r["outputMethod"] + if r["outputMethod"] == "all": + s["outputMethod"] = "all_iterations" + elif r["outputMethod"] == "last": + s["outputMethod"] = "last_iteration" + else: + raise SourceLine( + r, raise_type=ValidationException + ).makeError( # pragma: no cover + f"Invalid value {r['outputMethod']} for `outputMethod`." + ) cast( MutableSequence[CWLObjectType], s["requirements"], diff --git a/cwltool/workflow_job.py b/cwltool/workflow_job.py index 8402b2b4b..2e69ca70c 100644 --- a/cwltool/workflow_job.py +++ b/cwltool/workflow_job.py @@ -744,7 +744,7 @@ def valueFromFunc(k: str, v: Optional[CWLOutputType]) -> Optional[CWLOutputType] _logger.info("[%s] will be skipped", step.name) if ( step.tool.get("loop") is not None - and step.tool.get("outputMethod", "last") == "all" + and step.tool.get("outputMethod", "last_iteration") == "all_iterations" ): callback({k["id"]: [] for k in outputparms}, "skipped") else: @@ -874,7 +874,7 @@ def _set_empty_output(self, outputMethod: str) -> None: for i in self.step.tool["outputs"]: if "id" in i: iid = cast(str, i["id"]) - if outputMethod == "all": + if outputMethod == "all_iterations": self.output_buffer[iid] = cast(MutableSequence[Optional[CWLOutputType]], []) else: self.output_buffer[iid] = None @@ -887,7 +887,7 @@ def job( ) -> JobsGeneratorType: """Generate a WorkflowJobStep job until the `when` condition evaluates to False.""" self.joborder = joborder - outputMethod = self.step.tool.get("outputMethod", "last") + outputMethod = self.step.tool.get("outputMethod", "last_iteration") callback = functools.partial( self.loop_callback, @@ -953,14 +953,14 @@ def loop_callback( self.iteration += 1 try: loop = cast(MutableSequence[CWLObjectType], self.step.tool.get("loop", [])) - outputMethod = self.step.tool.get("outputMethod", "last") + outputMethod = self.step.tool.get("outputMethod", "last_iteration") state: Dict[str, Optional[WorkflowStateItem]] = {} for i in self.step.tool["outputs"]: if "id" in i: iid = cast(str, i["id"]) if iid in jobout: state[iid] = WorkflowStateItem(i, jobout[iid], processStatus) - if outputMethod == "all": + if outputMethod == "all_iterations": if iid not in self.output_buffer: self.output_buffer[iid] = cast( MutableSequence[Optional[CWLOutputType]], [] diff --git a/tests/loop/all-output-loop-no-iteration.cwl b/tests/loop/all-output-loop-no-iteration.cwl index 04ec87a18..49189faff 100644 --- a/tests/loop/all-output-loop-no-iteration.cwl +++ b/tests/loop/all-output-loop-no-iteration.cwl @@ -25,4 +25,4 @@ steps: when: $(inputs.i1 < 1) loop: i1: o1 - outputMethod: all + outputMethod: all_iterations diff --git a/tests/loop/all-output-loop.cwl b/tests/loop/all-output-loop.cwl index 157432e8f..001f50a7e 100644 --- a/tests/loop/all-output-loop.cwl +++ b/tests/loop/all-output-loop.cwl @@ -25,4 +25,4 @@ steps: when: $(inputs.i1 < 10) loop: i1: o1 - outputMethod: all + outputMethod: all_iterations diff --git a/tests/loop/default-value-loop.cwl b/tests/loop/default-value-loop.cwl index 04c64f0dd..08b032caf 100644 --- a/tests/loop/default-value-loop.cwl +++ b/tests/loop/default-value-loop.cwl @@ -44,4 +44,4 @@ steps: i1: outputSource: o1 default: 5 - outputMethod: all + outputMethod: all_iterations diff --git a/tests/loop/invalid-loop-scatter.cwl b/tests/loop/invalid-loop-scatter.cwl index 02451351d..31c563414 100644 --- a/tests/loop/invalid-loop-scatter.cwl +++ b/tests/loop/invalid-loop-scatter.cwl @@ -26,7 +26,7 @@ steps: when: $(inputs.i1 < 10) loop: i1: o1 - outputMethod: last + outputMethod: last_iteration in: i1: i1 i2: i2 diff --git a/tests/loop/invalid-loop-when-exception.cwl b/tests/loop/invalid-loop-when-exception.cwl index 33f7795c4..0bedd197d 100644 --- a/tests/loop/invalid-loop-when-exception.cwl +++ b/tests/loop/invalid-loop-when-exception.cwl @@ -29,7 +29,7 @@ steps: } loop: i1: o1 - outputMethod: last + outputMethod: last_iteration in: i1: i1 i2: i2 diff --git a/tests/loop/invalid-loop-when-exception2.cwl b/tests/loop/invalid-loop-when-exception2.cwl index 8e80250c4..5d2d3a426 100644 --- a/tests/loop/invalid-loop-when-exception2.cwl +++ b/tests/loop/invalid-loop-when-exception2.cwl @@ -33,7 +33,7 @@ steps: } loop: i1: o1 - outputMethod: last + outputMethod: last_iteration in: i1: i1 i2: i2 diff --git a/tests/loop/invalid-multi-source-loop-no-requirement.cwl b/tests/loop/invalid-multi-source-loop-no-requirement.cwl index 811ba6c6e..2c1cf35ec 100644 --- a/tests/loop/invalid-multi-source-loop-no-requirement.cwl +++ b/tests/loop/invalid-multi-source-loop-no-requirement.cwl @@ -61,4 +61,4 @@ steps: i1: loopSource: [osmall, obig] pickValue: the_only_non_null - outputMethod: all + outputMethod: all_iterations diff --git a/tests/loop/invalid-no-loopWhen.cwl b/tests/loop/invalid-no-loopWhen.cwl index 0a869be8e..8d4eb7589 100644 --- a/tests/loop/invalid-no-loopWhen.cwl +++ b/tests/loop/invalid-no-loopWhen.cwl @@ -25,7 +25,7 @@ steps: ${return {'o1': inputs.i1 + inputs.i2};} loop: i1: o1 - outputMethod: last + outputMethod: last_iteration in: i1: i1 i2: i2 diff --git a/tests/loop/invalid-non-boolean-loopWhen.cwl b/tests/loop/invalid-non-boolean-loopWhen.cwl index ea807ba3a..f7c16cd97 100644 --- a/tests/loop/invalid-non-boolean-loopWhen.cwl +++ b/tests/loop/invalid-non-boolean-loopWhen.cwl @@ -26,7 +26,7 @@ steps: when: $(inputs.i1) loop: i1: o1 - outputMethod: last + outputMethod: last_iteration in: i1: i1 i2: i2 diff --git a/tests/loop/invalid-non-boolean-loopWhen2.cwl b/tests/loop/invalid-non-boolean-loopWhen2.cwl index ba13e38ca..021752b18 100644 --- a/tests/loop/invalid-non-boolean-loopWhen2.cwl +++ b/tests/loop/invalid-non-boolean-loopWhen2.cwl @@ -26,7 +26,7 @@ steps: when: '$(inputs.i1 == 1 ? true : "I am a string")' loop: i1: o1 - outputMethod: last + outputMethod: last_iteration in: i1: i1 i2: i2 diff --git a/tests/loop/invalid-value-from-loop-no-requirement.cwl b/tests/loop/invalid-value-from-loop-no-requirement.cwl index c232194bc..dd1b8e384 100644 --- a/tests/loop/invalid-value-from-loop-no-requirement.cwl +++ b/tests/loop/invalid-value-from-loop-no-requirement.cwl @@ -29,4 +29,4 @@ steps: loop: i1: valueFrom: $(inputs.i1 + 1) - outputMethod: last + outputMethod: last_iteration diff --git a/tests/loop/loop-inside-loop-all.cwl b/tests/loop/loop-inside-loop-all.cwl index bc805c2f5..ef0a9798b 100644 --- a/tests/loop/loop-inside-loop-all.cwl +++ b/tests/loop/loop-inside-loop-all.cwl @@ -46,7 +46,7 @@ steps: when: $(inputs.i1 <= inputs.i2) loop: i1: o1 - outputMethod: all + outputMethod: all_iterations in: i1: i1 i2: i2 @@ -55,4 +55,4 @@ steps: loop: i2: valueFrom: $(inputs.i2 + 1) - outputMethod: all + outputMethod: all_iterations diff --git a/tests/loop/loop-inside-loop.cwl b/tests/loop/loop-inside-loop.cwl index 9b9fd7367..df01d114c 100644 --- a/tests/loop/loop-inside-loop.cwl +++ b/tests/loop/loop-inside-loop.cwl @@ -42,7 +42,7 @@ steps: when: $(inputs.i1 <= inputs.i2) loop: i1: o1 - outputMethod: last + outputMethod: last_iteration in: i1: i1 i2: i2 @@ -51,4 +51,4 @@ steps: loop: i2: valueFrom: $(inputs.i2 + 1) - outputMethod: all + outputMethod: all_iterations diff --git a/tests/loop/loop-inside-scatter.cwl b/tests/loop/loop-inside-scatter.cwl index 3fc7fe257..fbb60c9cf 100644 --- a/tests/loop/loop-inside-scatter.cwl +++ b/tests/loop/loop-inside-scatter.cwl @@ -41,7 +41,7 @@ steps: when: $(inputs.i1 < 10) loop: i1: o1 - outputMethod: last + outputMethod: last_iteration in: i1: i1 i2: i2 diff --git a/tests/loop/multi-source-loop.cwl b/tests/loop/multi-source-loop.cwl index 8c2a271cf..504e1d4c2 100644 --- a/tests/loop/multi-source-loop.cwl +++ b/tests/loop/multi-source-loop.cwl @@ -62,4 +62,4 @@ steps: i1: outputSource: [osmall, obig] pickValue: the_only_non_null - outputMethod: all + outputMethod: all_iterations diff --git a/tests/loop/opt-var-loop.cwl b/tests/loop/opt-var-loop.cwl index d74f7c225..626c86788 100644 --- a/tests/loop/opt-var-loop.cwl +++ b/tests/loop/opt-var-loop.cwl @@ -27,4 +27,4 @@ steps: when: $(inputs.i1 < 10) loop: i1: o1 - outputMethod: last + outputMethod: last_iteration diff --git a/tests/loop/scatter-inside-loop.cwl b/tests/loop/scatter-inside-loop.cwl index ab857b0d0..f3d2370cc 100644 --- a/tests/loop/scatter-inside-loop.cwl +++ b/tests/loop/scatter-inside-loop.cwl @@ -46,4 +46,4 @@ steps: when: $(inputs.i1[0] < 10) loop: i1: o1 - outputMethod: last + outputMethod: last_iteration diff --git a/tests/loop/single-var-loop-no-iteration.cwl b/tests/loop/single-var-loop-no-iteration.cwl index a5678e735..a39fcf583 100644 --- a/tests/loop/single-var-loop-no-iteration.cwl +++ b/tests/loop/single-var-loop-no-iteration.cwl @@ -26,4 +26,4 @@ steps: when: $(inputs.i1 < 1) loop: i1: o1 - outputMethod: last + outputMethod: last_iteration diff --git a/tests/loop/single-var-loop.cwl b/tests/loop/single-var-loop.cwl index ef3819ee1..3af765744 100644 --- a/tests/loop/single-var-loop.cwl +++ b/tests/loop/single-var-loop.cwl @@ -26,4 +26,4 @@ steps: when: $(inputs.i1 < 10) loop: i1: o1 - outputMethod: last + outputMethod: last_iteration diff --git a/tests/loop/two-vars-loop-2.cwl b/tests/loop/two-vars-loop-2.cwl index 7e50afe02..3542534b0 100644 --- a/tests/loop/two-vars-loop-2.cwl +++ b/tests/loop/two-vars-loop-2.cwl @@ -28,4 +28,4 @@ steps: when: $(inputs.i1 < 10) loop: i1: o1 - outputMethod: last + outputMethod: last_iteration diff --git a/tests/loop/two-vars-loop.cwl b/tests/loop/two-vars-loop.cwl index 15b659e4a..945bea8f1 100644 --- a/tests/loop/two-vars-loop.cwl +++ b/tests/loop/two-vars-loop.cwl @@ -30,4 +30,4 @@ steps: loop: i1: o1 i2: o2 - outputMethod: last + outputMethod: last_iteration diff --git a/tests/loop/value-from-loop.cwl b/tests/loop/value-from-loop.cwl index 545029bd1..457682cc3 100644 --- a/tests/loop/value-from-loop.cwl +++ b/tests/loop/value-from-loop.cwl @@ -30,4 +30,4 @@ steps: loop: i1: valueFrom: $(inputs.i1 + 1) - outputMethod: last + outputMethod: last_iteration diff --git a/tests/test_loop.py b/tests/test_loop.py index 269251627..bf908196d 100644 --- a/tests/test_loop.py +++ b/tests/test_loop.py @@ -143,7 +143,7 @@ def test_loop_two_variables_single_backpropagation() -> None: def test_loop_with_all_output_method() -> None: - """Test a loop case with outputMethod set to all.""" + """Test a loop case with outputMethod set to all_iterations.""" stream = StringIO() params = [ "--enable-dev", @@ -156,7 +156,7 @@ def test_loop_with_all_output_method() -> None: def test_loop_with_all_output_method_no_iteration() -> None: - """Test a loop case with outputMethod set to all and a false 'when' condition.""" + """Test a loop case with outputMethod set to all_iterations and a false 'when' condition.""" stream = StringIO() params = [ "--enable-dev", @@ -244,7 +244,7 @@ def test_nested_loops() -> None: def test_nested_loops_all() -> None: - """Test a workflow with two nested loops, both with outputMethod set to all.""" + """Test a workflow with two nested loops, both with outputMethod set to all_iterations.""" stream = StringIO() params = [ "--enable-dev", diff --git a/tests/test_path_checks.py b/tests/test_path_checks.py index 0532f3cde..01ab7fe17 100644 --- a/tests/test_path_checks.py +++ b/tests/test_path_checks.py @@ -7,14 +7,14 @@ from ruamel.yaml.comments import CommentedMap from schema_salad.sourceline import cmap +from cwltool.builder import content_limit_respected_read from cwltool.command_line_tool import CommandLineTool from cwltool.context import LoadingContext, RuntimeContext +from cwltool.errors import WorkflowException from cwltool.main import main from cwltool.stdfsaccess import StdFsAccess from cwltool.update import INTERNAL_VERSION -from cwltool.utils import CWLObjectType, CONTENT_LIMIT, bytes2str_in_dicts -from cwltool.builder import content_limit_respected_read -from cwltool.errors import WorkflowException +from cwltool.utils import CONTENT_LIMIT, CWLObjectType, bytes2str_in_dicts from .util import needs_docker