toil 9.1.1__py3-none-any.whl → 9.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- toil/__init__.py +5 -9
- toil/batchSystems/abstractBatchSystem.py +23 -22
- toil/batchSystems/abstractGridEngineBatchSystem.py +17 -12
- toil/batchSystems/awsBatch.py +8 -8
- toil/batchSystems/cleanup_support.py +4 -4
- toil/batchSystems/contained_executor.py +3 -3
- toil/batchSystems/gridengine.py +3 -4
- toil/batchSystems/htcondor.py +5 -5
- toil/batchSystems/kubernetes.py +65 -63
- toil/batchSystems/local_support.py +2 -3
- toil/batchSystems/lsf.py +6 -7
- toil/batchSystems/mesos/batchSystem.py +11 -7
- toil/batchSystems/mesos/test/__init__.py +1 -2
- toil/batchSystems/options.py +9 -10
- toil/batchSystems/registry.py +3 -7
- toil/batchSystems/singleMachine.py +8 -11
- toil/batchSystems/slurm.py +49 -38
- toil/batchSystems/torque.py +3 -4
- toil/bus.py +36 -34
- toil/common.py +129 -89
- toil/cwl/cwltoil.py +857 -729
- toil/cwl/utils.py +44 -35
- toil/fileStores/__init__.py +3 -1
- toil/fileStores/abstractFileStore.py +28 -30
- toil/fileStores/cachingFileStore.py +8 -8
- toil/fileStores/nonCachingFileStore.py +10 -21
- toil/job.py +159 -158
- toil/jobStores/abstractJobStore.py +68 -69
- toil/jobStores/aws/jobStore.py +249 -213
- toil/jobStores/aws/utils.py +13 -24
- toil/jobStores/fileJobStore.py +28 -22
- toil/jobStores/googleJobStore.py +21 -17
- toil/jobStores/utils.py +3 -7
- toil/leader.py +17 -22
- toil/lib/accelerators.py +6 -4
- toil/lib/aws/__init__.py +9 -10
- toil/lib/aws/ami.py +33 -19
- toil/lib/aws/iam.py +6 -6
- toil/lib/aws/s3.py +259 -157
- toil/lib/aws/session.py +76 -76
- toil/lib/aws/utils.py +51 -43
- toil/lib/checksum.py +19 -15
- toil/lib/compatibility.py +3 -2
- toil/lib/conversions.py +45 -18
- toil/lib/directory.py +29 -26
- toil/lib/docker.py +93 -99
- toil/lib/dockstore.py +77 -50
- toil/lib/ec2.py +39 -38
- toil/lib/ec2nodes.py +11 -4
- toil/lib/exceptions.py +8 -5
- toil/lib/ftp_utils.py +9 -14
- toil/lib/generatedEC2Lists.py +161 -20
- toil/lib/history.py +141 -97
- toil/lib/history_submission.py +163 -72
- toil/lib/io.py +27 -17
- toil/lib/memoize.py +2 -1
- toil/lib/misc.py +15 -11
- toil/lib/pipes.py +40 -25
- toil/lib/plugins.py +12 -8
- toil/lib/resources.py +1 -0
- toil/lib/retry.py +32 -38
- toil/lib/threading.py +12 -12
- toil/lib/throttle.py +1 -2
- toil/lib/trs.py +113 -51
- toil/lib/url.py +14 -23
- toil/lib/web.py +7 -2
- toil/options/common.py +18 -15
- toil/options/cwl.py +2 -2
- toil/options/runner.py +9 -5
- toil/options/wdl.py +1 -3
- toil/provisioners/__init__.py +9 -9
- toil/provisioners/abstractProvisioner.py +22 -20
- toil/provisioners/aws/__init__.py +20 -14
- toil/provisioners/aws/awsProvisioner.py +10 -8
- toil/provisioners/clusterScaler.py +19 -18
- toil/provisioners/gceProvisioner.py +2 -3
- toil/provisioners/node.py +11 -13
- toil/realtimeLogger.py +4 -4
- toil/resource.py +5 -5
- toil/server/app.py +2 -2
- toil/server/cli/wes_cwl_runner.py +11 -11
- toil/server/utils.py +18 -21
- toil/server/wes/abstract_backend.py +9 -8
- toil/server/wes/amazon_wes_utils.py +3 -3
- toil/server/wes/tasks.py +3 -5
- toil/server/wes/toil_backend.py +17 -21
- toil/server/wsgi_app.py +3 -3
- toil/serviceManager.py +3 -4
- toil/statsAndLogging.py +12 -13
- toil/test/__init__.py +33 -24
- toil/test/batchSystems/batchSystemTest.py +12 -11
- toil/test/batchSystems/batch_system_plugin_test.py +3 -5
- toil/test/batchSystems/test_slurm.py +38 -24
- toil/test/cwl/conftest.py +5 -6
- toil/test/cwl/cwlTest.py +194 -78
- toil/test/cwl/download_file_uri.json +6 -0
- toil/test/cwl/download_file_uri_no_hostname.json +6 -0
- toil/test/docs/scripts/tutorial_staging.py +1 -0
- toil/test/jobStores/jobStoreTest.py +9 -7
- toil/test/lib/aws/test_iam.py +1 -3
- toil/test/lib/aws/test_s3.py +1 -1
- toil/test/lib/dockerTest.py +9 -9
- toil/test/lib/test_ec2.py +12 -11
- toil/test/lib/test_history.py +4 -4
- toil/test/lib/test_trs.py +16 -14
- toil/test/lib/test_url.py +7 -6
- toil/test/lib/url_plugin_test.py +12 -18
- toil/test/provisioners/aws/awsProvisionerTest.py +10 -8
- toil/test/provisioners/clusterScalerTest.py +2 -5
- toil/test/provisioners/clusterTest.py +1 -3
- toil/test/server/serverTest.py +13 -4
- toil/test/sort/restart_sort.py +2 -6
- toil/test/sort/sort.py +3 -8
- toil/test/src/deferredFunctionTest.py +7 -7
- toil/test/src/environmentTest.py +1 -2
- toil/test/src/fileStoreTest.py +5 -5
- toil/test/src/importExportFileTest.py +5 -6
- toil/test/src/jobServiceTest.py +22 -14
- toil/test/src/jobTest.py +121 -25
- toil/test/src/miscTests.py +5 -7
- toil/test/src/promisedRequirementTest.py +8 -7
- toil/test/src/regularLogTest.py +2 -3
- toil/test/src/resourceTest.py +5 -8
- toil/test/src/restartDAGTest.py +5 -6
- toil/test/src/resumabilityTest.py +2 -2
- toil/test/src/retainTempDirTest.py +3 -3
- toil/test/src/systemTest.py +3 -3
- toil/test/src/threadingTest.py +1 -1
- toil/test/src/workerTest.py +1 -2
- toil/test/utils/toilDebugTest.py +6 -4
- toil/test/utils/toilKillTest.py +1 -1
- toil/test/utils/utilsTest.py +15 -14
- toil/test/wdl/wdltoil_test.py +247 -124
- toil/test/wdl/wdltoil_test_kubernetes.py +2 -2
- toil/toilState.py +2 -3
- toil/utils/toilDebugFile.py +3 -8
- toil/utils/toilDebugJob.py +1 -2
- toil/utils/toilLaunchCluster.py +1 -2
- toil/utils/toilSshCluster.py +2 -0
- toil/utils/toilStats.py +19 -24
- toil/utils/toilStatus.py +11 -14
- toil/version.py +10 -10
- toil/wdl/wdltoil.py +313 -209
- toil/worker.py +18 -12
- {toil-9.1.1.dist-info → toil-9.2.0.dist-info}/METADATA +11 -14
- {toil-9.1.1.dist-info → toil-9.2.0.dist-info}/RECORD +150 -153
- {toil-9.1.1.dist-info → toil-9.2.0.dist-info}/WHEEL +1 -1
- toil/test/cwl/staging_cat.cwl +0 -27
- toil/test/cwl/staging_make_file.cwl +0 -25
- toil/test/cwl/staging_workflow.cwl +0 -43
- toil/test/cwl/zero_default.cwl +0 -61
- toil/test/utils/ABCWorkflowDebug/ABC.txt +0 -1
- {toil-9.1.1.dist-info → toil-9.2.0.dist-info}/entry_points.txt +0 -0
- {toil-9.1.1.dist-info → toil-9.2.0.dist-info}/licenses/LICENSE +0 -0
- {toil-9.1.1.dist-info → toil-9.2.0.dist-info}/top_level.txt +0 -0
toil/test/utils/utilsTest.py
CHANGED
|
@@ -12,33 +12,33 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import builtins
|
|
15
|
-
from collections.abc import Callable, Generator
|
|
16
15
|
import logging
|
|
17
16
|
import os
|
|
18
|
-
from pathlib import Path
|
|
19
17
|
import re
|
|
20
18
|
import subprocess
|
|
21
19
|
import sys
|
|
22
20
|
import time
|
|
23
21
|
import uuid
|
|
24
|
-
from
|
|
22
|
+
from collections.abc import Callable, Generator
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Any, cast
|
|
25
|
+
|
|
25
26
|
import pytest
|
|
26
27
|
|
|
27
28
|
import toil
|
|
28
29
|
from toil import resolveEntryPoint
|
|
29
30
|
from toil.common import Config, Toil
|
|
31
|
+
from toil.fileStores.abstractFileStore import AbstractFileStore
|
|
30
32
|
from toil.job import Job
|
|
31
33
|
from toil.lib.bioio import system
|
|
32
|
-
from toil.
|
|
33
|
-
from toil.test import
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
pslow as slow,
|
|
41
|
-
)
|
|
34
|
+
from toil.test import get_data
|
|
35
|
+
from toil.test import pintegrative as integrative
|
|
36
|
+
from toil.test import pneeds_aws_ec2 as needs_aws_ec2
|
|
37
|
+
from toil.test import pneeds_cwl as needs_cwl
|
|
38
|
+
from toil.test import pneeds_docker as needs_docker
|
|
39
|
+
from toil.test import pneeds_rsync3 as needs_rsync3
|
|
40
|
+
from toil.test import pslow as slow
|
|
41
|
+
import toil.test.sort.sort
|
|
42
42
|
from toil.test.sort.sort import makeFileToSort
|
|
43
43
|
from toil.utils.toilStats import get_stats, process_data
|
|
44
44
|
from toil.utils.toilStatus import ToilStatus
|
|
@@ -353,7 +353,7 @@ class TestUtils:
|
|
|
353
353
|
jobstore: Path,
|
|
354
354
|
status: str,
|
|
355
355
|
status_fn: Callable[[str], str],
|
|
356
|
-
process:
|
|
356
|
+
process: subprocess.Popen[Any] | None = None,
|
|
357
357
|
seconds: int = 20,
|
|
358
358
|
) -> None:
|
|
359
359
|
time_elapsed = 0.0
|
|
@@ -542,6 +542,7 @@ class TestUtils:
|
|
|
542
542
|
|
|
543
543
|
def fake_print(*args: Any, **kwargs: Any) -> None:
|
|
544
544
|
print_args.extend(args)
|
|
545
|
+
|
|
545
546
|
# Run a workflow that will always fail
|
|
546
547
|
with get_data("test/cwl/alwaysfails.cwl") as cwl_file:
|
|
547
548
|
cmd = [
|
toil/test/wdl/wdltoil_test.py
CHANGED
|
@@ -2,75 +2,105 @@ import json
|
|
|
2
2
|
import logging
|
|
3
3
|
import os
|
|
4
4
|
import re
|
|
5
|
-
import shutil
|
|
6
5
|
import string
|
|
7
6
|
import subprocess
|
|
8
7
|
import unittest
|
|
9
8
|
from collections.abc import Generator
|
|
10
9
|
from pathlib import Path
|
|
11
|
-
from typing import Any,
|
|
10
|
+
from typing import Any, cast
|
|
12
11
|
from unittest.mock import patch
|
|
12
|
+
from urllib.parse import quote
|
|
13
13
|
from uuid import uuid4
|
|
14
14
|
|
|
15
15
|
import pytest
|
|
16
|
-
from pytest_httpserver import HTTPServer
|
|
17
|
-
|
|
18
16
|
import WDL.Error
|
|
19
17
|
import WDL.Expr
|
|
18
|
+
from pytest_httpserver import HTTPServer
|
|
20
19
|
|
|
21
20
|
from toil.fileStores import FileID
|
|
22
21
|
from toil.test import (
|
|
23
|
-
ToilTest,
|
|
24
22
|
get_data,
|
|
25
23
|
needs_docker,
|
|
26
24
|
needs_docker_cuda,
|
|
27
25
|
needs_google_storage,
|
|
28
26
|
needs_online,
|
|
29
27
|
needs_singularity_or_docker,
|
|
30
|
-
needs_wdl,
|
|
31
28
|
slow,
|
|
32
29
|
)
|
|
33
30
|
from toil.version import exactPython
|
|
34
|
-
from toil.wdl.wdltoil import
|
|
35
|
-
WDLSectionJob,
|
|
36
|
-
WDLWorkflowGraph,
|
|
37
|
-
parse_disks,
|
|
38
|
-
)
|
|
31
|
+
from toil.wdl.wdltoil import WDLSectionJob, WDLWorkflowGraph, parse_disks
|
|
39
32
|
|
|
40
33
|
logger = logging.getLogger(__name__)
|
|
41
34
|
|
|
42
35
|
|
|
43
36
|
WDL_CONFORMANCE_TEST_REPO = "https://github.com/DataBiosphere/wdl-conformance-tests.git"
|
|
44
|
-
WDL_CONFORMANCE_TEST_COMMIT = "
|
|
37
|
+
WDL_CONFORMANCE_TEST_COMMIT = "12d6d8a54a11803fb529aeca18ee01cba01f1d3e"
|
|
45
38
|
# These tests are known to require things not implemented by
|
|
46
39
|
# Toil and will not be run in CI.
|
|
47
40
|
WDL_CONFORMANCE_TESTS_UNSUPPORTED_BY_TOIL = [
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
"object", # Basic object test (deprecated and removed in 1.1); MiniWDL and toil-wdl-runner do not support Objects, so this will fail if ran by them
|
|
42
|
+
"string_placeholders_conditionals_1_0", # Parser: expression placeholders in strings in conditional expressions in 1.0, Cromwell style; Fails with MiniWDL and toil-wdl-runner
|
|
43
|
+
"as_map", # Legacy test for as_map_as_input; It looks like MiniWDL does not have the function as_map()
|
|
44
|
+
"array_coerce", # Test that array cannot coerce to a string. WDL 1.1 does not allow compound types to coerce into a string. This should return a TypeError.
|
|
45
|
+
"sibling_directories", # TODO: This has started failing in CI despite passing locally on Mac and Linux. Come up with a more consistent test!
|
|
52
46
|
]
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
47
|
+
|
|
48
|
+
# These tests (in the same order as in SPEC.md) are known to fail
|
|
49
|
+
WDL_11_UNIT_TESTS_UNSUPPORTED_BY_TOIL = [
|
|
50
|
+
"test_object", # Objects are not supported
|
|
51
|
+
"map_to_struct", # miniwdl cannot coerce map to struct, https://github.com/chanzuckerberg/miniwdl/issues/712
|
|
52
|
+
"relative_and_absolute_task", # needs root to run
|
|
53
|
+
"test_gpu_task", # needs gpu to run, else warning
|
|
54
|
+
"hisat2_task", # This needs way too many resources (and actually doesn't work?), see https://github.com/DataBiosphere/wdl-conformance-tests/blob/2d617b703a33791f75f30a9db43c3740a499cd89/README_UNIT.md?plain=1#L8
|
|
55
|
+
"gatk_haplotype_caller_task", # same as above
|
|
56
|
+
"input_ref_call", # Inputs refering into workflow body not yet implemented: see https://github.com/DataBiosphere/toil/issues/4993
|
|
57
|
+
"call_imported", # Same as input_ref_call since it imports it
|
|
58
|
+
"call_imported_task", # Same as input_ref_call since it imports it
|
|
59
|
+
"test_sub", # MiniWDL does not handle metacharacters properly when running regex, https://github.com/chanzuckerberg/miniwdl/issues/709
|
|
60
|
+
"read_bool_task", # miniwdl bug, see https://github.com/chanzuckerberg/miniwdl/issues/701
|
|
61
|
+
"write_json_fail", # miniwdl (and toil) bug, unserializable json is serialized, see https://github.com/chanzuckerberg/miniwdl/issues/702
|
|
62
|
+
"read_object_task", # object not supported
|
|
63
|
+
"read_objects_task", # object not supported
|
|
64
|
+
"write_object_task", # object not supported
|
|
65
|
+
"write_objects_task", # object not supported
|
|
66
|
+
"test_transpose", # miniwdl bug, see https://github.com/chanzuckerberg/miniwdl/issues/699
|
|
67
|
+
"test_as_map_fail", # miniwdl bug, evalerror, see https://github.com/chanzuckerberg/miniwdl/issues/700
|
|
68
|
+
"test_collect_by_key", # same as test_as_map_
|
|
69
|
+
"serde_pair", # miniwdl and toil bug
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
WDL_12_UNIT_TESTS_UNSUPPORTED_BY_TOIL = WDL_11_UNIT_TESTS_UNSUPPORTED_BY_TOIL + [
|
|
73
|
+
"relative_paths_context", # Toil can't yet resolve File coercion at task scope relative to task file.
|
|
74
|
+
"file_directory_equality", # String to Directory coercion not yet implemented.
|
|
75
|
+
"single_return_code_task", # MiniWDL 1.13.1 only knows returnCodes and not return_codes.
|
|
76
|
+
"all_return_codes_task", # MiniWDL 1.13.1 only knows returnCodes and not return_codes.
|
|
77
|
+
"test_runtime_info_task", # MiniWDL 1.13.1 can't yet expose the task global.
|
|
78
|
+
"placeholder_none", # 'outputs' section expected 1 results (['placeholder_none.s']), got 0 instead ([]) with exit code 1
|
|
79
|
+
"person_struct_task", # Doesn't work as written in the spec; see https://github.com/openwdl/wdl/issues/739
|
|
80
|
+
"import_structs", # Feature not yet implemented?
|
|
81
|
+
"environment_variable_should_echo", # Ln 14 Col 45: Unexpected token STRING1_FRAGMENT
|
|
82
|
+
"outputs_task", # 'outputs' section expected 2 results (['outputs.threshold', 'outputs.two_csvs']), got 3 instead (['outputs.two_csvs', 'outputs.csvs', 'outputs.threshold']) with exit code 0
|
|
83
|
+
"glob_task", # 'outputs' section expected 1 results (['glob.last_file_contents']), got 2 instead (['glob.last_file_contents', 'glob.outfiles']) with exit code 0
|
|
84
|
+
"test_hints_task", # Test is written as if the file has 3 lines, but it really has 2. See https://github.com/openwdl/wdl/issues/741
|
|
85
|
+
"input_hint_task", # Missing outputs in test definition: https://github.com/openwdl/wdl/issues/740
|
|
86
|
+
"test_allow_nested_inputs", # Ln 27 Col 3: Unexpected token HINTS
|
|
87
|
+
"multi_nested_inputs", # Ln 8 Col 9: Unexpected token STRING1_FRAGMENT
|
|
88
|
+
"allow_nested", # Ln 32 Col 9: Unexpected token STRING1_FRAGMENT
|
|
89
|
+
"test_find_task", # Ln 9 Col 22: No such function: find
|
|
90
|
+
"test_matches_task", # Ln 7 Col 29: No such function: matches
|
|
91
|
+
"change_extension_task", # 'outputs' section expected 2 results (['change_extension.data', 'change_extension.index']), got 3 instead (['change_extension.index', 'change_extension.data', 'change_extension.data_file']) with exit code 0
|
|
92
|
+
"join_paths_task", # Ln 14 Col 15: No such function: join_paths
|
|
93
|
+
"gen_files_task", # 'outputs' section expected 1 results (['gen_files.glob_len']), got 2 instead (['gen_files.glob_len', 'gen_files.files']) with exit code 0
|
|
94
|
+
"file_sizes_task", # WDL.Error.StaticTypeMismatch: Expected File? instead of Map[String,Pair[Int,File?]]
|
|
95
|
+
"read_tsv_task", # Ln 21 Col 5: Unknown type Object
|
|
96
|
+
"write_tsv_task", # Ln 28 Col 16: write_tsv expects 1 argument(s)
|
|
97
|
+
"test_contains", # Ln 25 Col 22: No such function: contains
|
|
98
|
+
"chunk_array", # Ln 8 Col 17: No such function: chunk
|
|
99
|
+
"test_select_first", # Ln 14 Col 17: select_first expects 1 argument(s)
|
|
100
|
+
"test_keys", # Ln 32 Col 36: Expected Map[Any,Any] instead of Name
|
|
101
|
+
"test_contains_key", # Ln 18 Col 20: No such function: contains_key
|
|
102
|
+
"test_values", # Ln 28 Col 20: No such function: values
|
|
103
|
+
"test_length", # length() isn't implemented for maps and strings yet
|
|
74
104
|
]
|
|
75
105
|
|
|
76
106
|
|
|
@@ -152,8 +182,78 @@ class TestWDLConformance:
|
|
|
152
182
|
"-v",
|
|
153
183
|
"1.1",
|
|
154
184
|
"--progress",
|
|
155
|
-
"--exclude-
|
|
156
|
-
",".join(
|
|
185
|
+
"--exclude-ids",
|
|
186
|
+
",".join(WDL_11_UNIT_TESTS_UNSUPPORTED_BY_TOIL),
|
|
187
|
+
]
|
|
188
|
+
p2 = subprocess.run(commands2, capture_output=True)
|
|
189
|
+
self.check(p2)
|
|
190
|
+
|
|
191
|
+
@slow
|
|
192
|
+
def test_unit_tests_v12(self, wdl_conformance_test_repo: Path) -> None:
|
|
193
|
+
# TODO: Using a branch lets Toil commits that formerly passed start to
|
|
194
|
+
# fail CI when the branch moves.
|
|
195
|
+
os.chdir(wdl_conformance_test_repo)
|
|
196
|
+
repo_url = "https://github.com/adamnovak/wdl.git"
|
|
197
|
+
repo_branch = "wdl-1.2-fix-json"
|
|
198
|
+
commands1 = [
|
|
199
|
+
exactPython,
|
|
200
|
+
"setup_unit_tests.py",
|
|
201
|
+
"-v",
|
|
202
|
+
"1.2",
|
|
203
|
+
"--extra-patch-data",
|
|
204
|
+
"unit_tests_patch_data.yaml",
|
|
205
|
+
"--repo",
|
|
206
|
+
repo_url,
|
|
207
|
+
"--branch",
|
|
208
|
+
repo_branch,
|
|
209
|
+
"--force-pull",
|
|
210
|
+
]
|
|
211
|
+
p1 = subprocess.run(commands1, capture_output=True)
|
|
212
|
+
self.check(p1)
|
|
213
|
+
commands2 = [
|
|
214
|
+
exactPython,
|
|
215
|
+
"run_unit.py",
|
|
216
|
+
"-r",
|
|
217
|
+
"toil-wdl-runner",
|
|
218
|
+
"-v",
|
|
219
|
+
"1.2",
|
|
220
|
+
"--progress",
|
|
221
|
+
"--exclude-ids",
|
|
222
|
+
",".join(WDL_12_UNIT_TESTS_UNSUPPORTED_BY_TOIL),
|
|
223
|
+
]
|
|
224
|
+
p2 = subprocess.run(commands2, capture_output=True)
|
|
225
|
+
self.check(p2)
|
|
226
|
+
|
|
227
|
+
@slow
|
|
228
|
+
def test_single_unit_test(self, wdl_conformance_test_repo: Path) -> None:
|
|
229
|
+
os.chdir(wdl_conformance_test_repo)
|
|
230
|
+
repo_url = "https://github.com/openwdl/wdl.git"
|
|
231
|
+
repo_branch = "wdl-1.1"
|
|
232
|
+
commands1 = [
|
|
233
|
+
exactPython,
|
|
234
|
+
"setup_unit_tests.py",
|
|
235
|
+
"-v",
|
|
236
|
+
"1.1",
|
|
237
|
+
"--extra-patch-data",
|
|
238
|
+
"unit_tests_patch_data.yaml",
|
|
239
|
+
"--repo",
|
|
240
|
+
repo_url,
|
|
241
|
+
"--branch",
|
|
242
|
+
repo_branch,
|
|
243
|
+
"--force-pull",
|
|
244
|
+
]
|
|
245
|
+
p1 = subprocess.run(commands1, capture_output=True)
|
|
246
|
+
self.check(p1)
|
|
247
|
+
commands2 = [
|
|
248
|
+
exactPython,
|
|
249
|
+
"run_unit.py",
|
|
250
|
+
"-r",
|
|
251
|
+
"toil-wdl-runner",
|
|
252
|
+
"-v",
|
|
253
|
+
"1.1",
|
|
254
|
+
"--progress",
|
|
255
|
+
"--id",
|
|
256
|
+
",".join("glob_task"),
|
|
157
257
|
]
|
|
158
258
|
p2 = subprocess.run(commands2, capture_output=True)
|
|
159
259
|
self.check(p2)
|
|
@@ -173,10 +273,8 @@ class TestWDLConformance:
|
|
|
173
273
|
"1.0",
|
|
174
274
|
]
|
|
175
275
|
if WDL_CONFORMANCE_TESTS_UNSUPPORTED_BY_TOIL:
|
|
176
|
-
commands.append("--exclude-
|
|
177
|
-
commands.append(
|
|
178
|
-
",".join([str(t) for t in WDL_CONFORMANCE_TESTS_UNSUPPORTED_BY_TOIL])
|
|
179
|
-
)
|
|
276
|
+
commands.append("--exclude-ids")
|
|
277
|
+
commands.append(",".join(WDL_CONFORMANCE_TESTS_UNSUPPORTED_BY_TOIL))
|
|
180
278
|
p = subprocess.run(commands, capture_output=True)
|
|
181
279
|
|
|
182
280
|
self.check(p)
|
|
@@ -196,10 +294,8 @@ class TestWDLConformance:
|
|
|
196
294
|
"1.1",
|
|
197
295
|
]
|
|
198
296
|
if WDL_CONFORMANCE_TESTS_UNSUPPORTED_BY_TOIL:
|
|
199
|
-
commands.append("--exclude-
|
|
200
|
-
commands.append(
|
|
201
|
-
",".join([str(t) for t in WDL_CONFORMANCE_TESTS_UNSUPPORTED_BY_TOIL])
|
|
202
|
-
)
|
|
297
|
+
commands.append("--exclude-ids")
|
|
298
|
+
commands.append(",".join(WDL_CONFORMANCE_TESTS_UNSUPPORTED_BY_TOIL))
|
|
203
299
|
p = subprocess.run(commands, capture_output=True)
|
|
204
300
|
|
|
205
301
|
self.check(p)
|
|
@@ -207,7 +303,9 @@ class TestWDLConformance:
|
|
|
207
303
|
# estimated running time: 10 minutes (once all the appropriate tests get
|
|
208
304
|
# marked as "development")
|
|
209
305
|
@slow
|
|
210
|
-
def test_conformance_tests_development(
|
|
306
|
+
def test_conformance_tests_development(
|
|
307
|
+
self, wdl_conformance_test_repo: Path
|
|
308
|
+
) -> None:
|
|
211
309
|
os.chdir(wdl_conformance_test_repo)
|
|
212
310
|
commands = [
|
|
213
311
|
exactPython,
|
|
@@ -220,10 +318,8 @@ class TestWDLConformance:
|
|
|
220
318
|
"development",
|
|
221
319
|
]
|
|
222
320
|
if WDL_CONFORMANCE_TESTS_UNSUPPORTED_BY_TOIL:
|
|
223
|
-
commands.append("--exclude-
|
|
224
|
-
commands.append(
|
|
225
|
-
",".join([str(t) for t in WDL_CONFORMANCE_TESTS_UNSUPPORTED_BY_TOIL])
|
|
226
|
-
)
|
|
321
|
+
commands.append("--exclude-ids")
|
|
322
|
+
commands.append(",".join(WDL_CONFORMANCE_TESTS_UNSUPPORTED_BY_TOIL))
|
|
227
323
|
p = subprocess.run(commands, capture_output=True)
|
|
228
324
|
|
|
229
325
|
self.check(p)
|
|
@@ -284,6 +380,51 @@ class TestWDL:
|
|
|
284
380
|
assert os.path.exists(result["ga4ghMd5.value"])
|
|
285
381
|
assert os.path.basename(result["ga4ghMd5.value"]) == "md5sum.txt"
|
|
286
382
|
|
|
383
|
+
@needs_singularity_or_docker
|
|
384
|
+
def test_file_uri_no_hostname(self, tmp_path: Path, subtests: pytest.Subtests) -> None:
|
|
385
|
+
"""Test if Toil handles file URIs without even empty hostnames"""
|
|
386
|
+
|
|
387
|
+
# We need to test file:/absolute/path/to/the/file in conjunction with
|
|
388
|
+
# worker imports, which didn't work in
|
|
389
|
+
# https://github.com/DataBiosphere/toil/issues/5392
|
|
390
|
+
with get_data("test/wdl/md5sum/md5sum.1.0.wdl") as wdl:
|
|
391
|
+
with get_data("test/wdl/md5sum/md5sum.input") as input_file:
|
|
392
|
+
# We need to wrap the absolute path to the input file in a JSON as a URI.
|
|
393
|
+
file_uri = f"file:{quote(os.path.abspath(input_file))}"
|
|
394
|
+
|
|
395
|
+
# Then put that in inline input JSON
|
|
396
|
+
input_json = json.dumps({"ga4ghMd5.inputFile": file_uri})
|
|
397
|
+
|
|
398
|
+
for worker_import in (False, True):
|
|
399
|
+
with subtests.test(msg=f"Worker import: {worker_import}"):
|
|
400
|
+
|
|
401
|
+
result_json = subprocess.check_output(
|
|
402
|
+
self.base_command
|
|
403
|
+
+ [
|
|
404
|
+
str(wdl),
|
|
405
|
+
input_json,
|
|
406
|
+
"-o",
|
|
407
|
+
str(tmp_path),
|
|
408
|
+
"--logDebug",
|
|
409
|
+
"--retryCount=0",
|
|
410
|
+
]
|
|
411
|
+
+ (
|
|
412
|
+
[
|
|
413
|
+
"--runImportsOnWorkers",
|
|
414
|
+
]
|
|
415
|
+
if worker_import
|
|
416
|
+
else []
|
|
417
|
+
)
|
|
418
|
+
)
|
|
419
|
+
result = json.loads(result_json)
|
|
420
|
+
|
|
421
|
+
assert "ga4ghMd5.value" in result
|
|
422
|
+
assert isinstance(result["ga4ghMd5.value"], str)
|
|
423
|
+
assert os.path.exists(result["ga4ghMd5.value"])
|
|
424
|
+
assert (
|
|
425
|
+
os.path.basename(result["ga4ghMd5.value"]) == "md5sum.txt"
|
|
426
|
+
)
|
|
427
|
+
|
|
287
428
|
@needs_online
|
|
288
429
|
def test_url_to_file(self, tmp_path: Path) -> None:
|
|
289
430
|
"""
|
|
@@ -314,7 +455,7 @@ class TestWDL:
|
|
|
314
455
|
"-o",
|
|
315
456
|
str(tmp_path),
|
|
316
457
|
"--logInfo",
|
|
317
|
-
"--retryCount=0"
|
|
458
|
+
"--retryCount=0",
|
|
318
459
|
]
|
|
319
460
|
)
|
|
320
461
|
result = json.loads(result_json)
|
|
@@ -329,13 +470,7 @@ class TestWDL:
|
|
|
329
470
|
with get_data("test/wdl/testfiles/gather.wdl") as wdl:
|
|
330
471
|
result_json = subprocess.check_output(
|
|
331
472
|
self.base_command
|
|
332
|
-
+ [
|
|
333
|
-
str(wdl),
|
|
334
|
-
"-o",
|
|
335
|
-
str(tmp_path),
|
|
336
|
-
"--logInfo",
|
|
337
|
-
"--retryCount=0"
|
|
338
|
-
]
|
|
473
|
+
+ [str(wdl), "-o", str(tmp_path), "--logInfo", "--retryCount=0"]
|
|
339
474
|
)
|
|
340
475
|
result = json.loads(result_json)
|
|
341
476
|
|
|
@@ -374,42 +509,35 @@ class TestWDL:
|
|
|
374
509
|
out_dir = tmp_path / "out"
|
|
375
510
|
file_path = tmp_path / "file"
|
|
376
511
|
jobstore_path = tmp_path / "tree"
|
|
377
|
-
command =
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
"--retryCount=0"
|
|
388
|
-
]
|
|
389
|
-
)
|
|
512
|
+
command = self.base_command + [
|
|
513
|
+
str(wdl),
|
|
514
|
+
"-o",
|
|
515
|
+
str(out_dir),
|
|
516
|
+
"-i",
|
|
517
|
+
json.dumps({"read_file.input_string": str(file_path)}),
|
|
518
|
+
"--jobStore",
|
|
519
|
+
str(jobstore_path),
|
|
520
|
+
"--retryCount=0",
|
|
521
|
+
]
|
|
390
522
|
with pytest.raises(subprocess.CalledProcessError):
|
|
391
523
|
# The first time we run it, it should fail because it's trying
|
|
392
524
|
# to work on a nonexistent file from a string path.
|
|
393
|
-
result_json = subprocess.check_output(
|
|
394
|
-
command + ["--logCritical"]
|
|
395
|
-
)
|
|
525
|
+
result_json = subprocess.check_output(command + ["--logCritical"])
|
|
396
526
|
|
|
397
527
|
# Then create the file
|
|
398
528
|
with open(file_path, "w") as f:
|
|
399
529
|
f.write("This is a line\n")
|
|
400
530
|
f.write("This is a different line")
|
|
401
|
-
|
|
531
|
+
|
|
402
532
|
# Now it should work
|
|
403
|
-
result_json = subprocess.check_output(
|
|
404
|
-
command + ["--restart"]
|
|
405
|
-
)
|
|
533
|
+
result_json = subprocess.check_output(command + ["--restart"])
|
|
406
534
|
result = json.loads(result_json)
|
|
407
535
|
|
|
408
536
|
assert "read_file.lines" in result
|
|
409
537
|
assert isinstance(result["read_file.lines"], list)
|
|
410
538
|
assert result["read_file.lines"] == [
|
|
411
539
|
"This is a line",
|
|
412
|
-
"This is a different line"
|
|
540
|
+
"This is a different line",
|
|
413
541
|
]
|
|
414
542
|
|
|
415
543
|
# Since we were catching
|
|
@@ -721,15 +849,14 @@ class TestWDL:
|
|
|
721
849
|
Return the parsed output.
|
|
722
850
|
"""
|
|
723
851
|
logger.info("Test optional file with HTTP code %s", code)
|
|
724
|
-
httpserver.expect_request(
|
|
725
|
-
"
|
|
726
|
-
).respond_with_data(
|
|
727
|
-
"Some data",
|
|
728
|
-
status=code,
|
|
729
|
-
content_type="text/plain"
|
|
852
|
+
httpserver.expect_request("/" + str(code)).respond_with_data(
|
|
853
|
+
"Some data", status=code, content_type="text/plain"
|
|
730
854
|
)
|
|
731
855
|
base_url = httpserver.url_for("/")
|
|
732
|
-
json_value =
|
|
856
|
+
json_value = (
|
|
857
|
+
'{"url_to_optional_file.http_code": %d, "url_to_optional_file.base_url": "%s"}'
|
|
858
|
+
% (code, base_url)
|
|
859
|
+
)
|
|
733
860
|
result_json = subprocess.check_output(
|
|
734
861
|
self.base_command
|
|
735
862
|
+ [
|
|
@@ -761,6 +888,7 @@ class TestWDL:
|
|
|
761
888
|
with pytest.raises(subprocess.CalledProcessError):
|
|
762
889
|
run_for_code(code)
|
|
763
890
|
|
|
891
|
+
@needs_singularity_or_docker
|
|
764
892
|
def test_missing_output_directory(self, tmp_path: Path) -> None:
|
|
765
893
|
"""
|
|
766
894
|
Test if Toil can run a WDL workflow into a new directory.
|
|
@@ -781,7 +909,7 @@ class TestWDL:
|
|
|
781
909
|
|
|
782
910
|
@needs_singularity_or_docker
|
|
783
911
|
def test_miniwdl_self_test(
|
|
784
|
-
self, tmp_path: Path, extra_args:
|
|
912
|
+
self, tmp_path: Path, extra_args: list[str] | None = None
|
|
785
913
|
) -> None:
|
|
786
914
|
"""Test if the MiniWDL self test runs and produces the expected output."""
|
|
787
915
|
with get_data("test/wdl/miniwdl_self_test/self_test.wdl") as wdl_file:
|
|
@@ -860,7 +988,7 @@ class TestWDL:
|
|
|
860
988
|
@pytest.mark.integrative
|
|
861
989
|
@needs_singularity_or_docker
|
|
862
990
|
def test_dockstore_trs(
|
|
863
|
-
self, tmp_path: Path, extra_args:
|
|
991
|
+
self, tmp_path: Path, extra_args: list[str] | None = None
|
|
864
992
|
) -> None:
|
|
865
993
|
wdl_file = "#workflow/github.com/dockstore/bcc2020-training/HelloWorld:master"
|
|
866
994
|
# Needs an input but doesn't provide a good one.
|
|
@@ -894,7 +1022,7 @@ class TestWDL:
|
|
|
894
1022
|
@pytest.mark.integrative
|
|
895
1023
|
@needs_singularity_or_docker
|
|
896
1024
|
def test_dockstore_metrics_publication(
|
|
897
|
-
self, tmp_path: Path, extra_args:
|
|
1025
|
+
self, tmp_path: Path, extra_args: list[str] | None = None
|
|
898
1026
|
) -> None:
|
|
899
1027
|
wdl_file = "#workflow/github.com/dockstore/bcc2020-training/HelloWorld:master"
|
|
900
1028
|
# Needs an input but doesn't provide a good one.
|
|
@@ -908,10 +1036,12 @@ class TestWDL:
|
|
|
908
1036
|
# Set credentials we got permission to publish from the Dockstore team,
|
|
909
1037
|
# and work on the staging Dockstore.
|
|
910
1038
|
env["TOIL_TRS_ROOT"] = "https://staging.dockstore.org"
|
|
911
|
-
env["TOIL_DOCKSTORE_TOKEN"] =
|
|
1039
|
+
env["TOIL_DOCKSTORE_TOKEN"] = (
|
|
1040
|
+
"99cf5578ebe94b194d7864630a86258fa3d6cedcc17d757b5dd49e64ee3b68c3"
|
|
1041
|
+
)
|
|
912
1042
|
# Enable history for when <https://github.com/DataBiosphere/toil/pull/5258> merges
|
|
913
1043
|
env["TOIL_HISTORY"] = "True"
|
|
914
|
-
|
|
1044
|
+
|
|
915
1045
|
try:
|
|
916
1046
|
output_log = subprocess.check_output(
|
|
917
1047
|
self.base_command
|
|
@@ -930,10 +1060,15 @@ class TestWDL:
|
|
|
930
1060
|
env=env,
|
|
931
1061
|
).decode("utf-8", errors="replace")
|
|
932
1062
|
except subprocess.CalledProcessError as e:
|
|
933
|
-
logger.error(
|
|
1063
|
+
logger.error(
|
|
1064
|
+
"Test run of Toil failed: %s",
|
|
1065
|
+
e.stdout.decode("utf-8", errors="replace"),
|
|
1066
|
+
)
|
|
934
1067
|
raise
|
|
935
1068
|
|
|
936
|
-
assert
|
|
1069
|
+
assert (
|
|
1070
|
+
"Workflow metrics were accepted by Dockstore." in output_log
|
|
1071
|
+
), f"No acceptance message in log: {output_log}"
|
|
937
1072
|
|
|
938
1073
|
@slow
|
|
939
1074
|
@needs_docker_cuda
|
|
@@ -943,27 +1078,10 @@ class TestWDL:
|
|
|
943
1078
|
|
|
944
1079
|
json_dir = tmp_path / "json"
|
|
945
1080
|
json_dir.mkdir()
|
|
946
|
-
base_uri = "https://raw.githubusercontent.com/vgteam/vg_wdl/
|
|
1081
|
+
base_uri = "https://raw.githubusercontent.com/vgteam/vg_wdl/fc6654db25e3e2c2bb85cc6dc5e3bb81dfe7a236"
|
|
947
1082
|
|
|
948
1083
|
wdl_file = f"{base_uri}/workflows/giraffe_and_deepvariant.wdl"
|
|
949
|
-
json_file =
|
|
950
|
-
with json_file.open("w") as fp:
|
|
951
|
-
# Write some inputs. We need to override the example inputs to use a GPU container, but that means we need absolute input URLs.
|
|
952
|
-
json.dump(
|
|
953
|
-
{
|
|
954
|
-
"GiraffeDeepVariant.INPUT_READ_FILE_1": f"{base_uri}/tests/small_sim_graph/reads_1.fastq.gz",
|
|
955
|
-
"GiraffeDeepVariant.INPUT_READ_FILE_2": f"{base_uri}/tests/small_sim_graph/reads_2.fastq.gz",
|
|
956
|
-
"GiraffeDeepVariant.XG_FILE": f"{base_uri}/tests/small_sim_graph/graph.xg",
|
|
957
|
-
"GiraffeDeepVariant.SAMPLE_NAME": "s0",
|
|
958
|
-
"GiraffeDeepVariant.GBWT_FILE": f"{base_uri}/tests/small_sim_graph/graph.gbwt",
|
|
959
|
-
"GiraffeDeepVariant.GGBWT_FILE": f"{base_uri}/tests/small_sim_graph/graph.gg",
|
|
960
|
-
"GiraffeDeepVariant.MIN_FILE": f"{base_uri}/tests/small_sim_graph/graph.min",
|
|
961
|
-
"GiraffeDeepVariant.DIST_FILE": f"{base_uri}/tests/small_sim_graph/graph.dist",
|
|
962
|
-
"GiraffeDeepVariant.OUTPUT_GAF": True,
|
|
963
|
-
"GiraffeDeepVariant.runDeepVariantCallVariants.in_dv_gpu_container": "google/deepvariant:1.3.0-gpu",
|
|
964
|
-
},
|
|
965
|
-
fp,
|
|
966
|
-
)
|
|
1084
|
+
json_file = f"{base_uri}/params/giraffe_and_deepvariant.json"
|
|
967
1085
|
|
|
968
1086
|
result_json = subprocess.check_output(
|
|
969
1087
|
self.base_command
|
|
@@ -1000,7 +1118,7 @@ class TestWDL:
|
|
|
1000
1118
|
# TODO: Reduce memory requests with custom/smaller inputs.
|
|
1001
1119
|
# TODO: Skip if node lacks enough memory.
|
|
1002
1120
|
|
|
1003
|
-
base_uri = "https://raw.githubusercontent.com/vgteam/vg_wdl/
|
|
1121
|
+
base_uri = "https://raw.githubusercontent.com/vgteam/vg_wdl/fc6654db25e3e2c2bb85cc6dc5e3bb81dfe7a236"
|
|
1004
1122
|
wdl_file = f"{base_uri}/workflows/giraffe.wdl"
|
|
1005
1123
|
json_file = f"{base_uri}/params/giraffe.json"
|
|
1006
1124
|
|
|
@@ -1055,19 +1173,24 @@ class TestWDL:
|
|
|
1055
1173
|
"""Test that Toil's lint check works"""
|
|
1056
1174
|
with get_data("test/wdl/lint_error.wdl") as wdl:
|
|
1057
1175
|
out = subprocess.check_output(
|
|
1058
|
-
self.base_command + [str(wdl), "-o", str(tmp_path), "--logInfo"],
|
|
1176
|
+
self.base_command + [str(wdl), "-o", str(tmp_path), "--logInfo"],
|
|
1177
|
+
stderr=subprocess.STDOUT,
|
|
1178
|
+
)
|
|
1059
1179
|
|
|
1060
|
-
assert b
|
|
1180
|
+
assert b"UnnecessaryQuantifier" in out
|
|
1061
1181
|
|
|
1062
1182
|
p = subprocess.Popen(
|
|
1063
|
-
self.base_command + [wdl, "--strict=True", "--logCritical"],
|
|
1183
|
+
self.base_command + [wdl, "--strict=True", "--logCritical"],
|
|
1184
|
+
stderr=subprocess.PIPE,
|
|
1185
|
+
)
|
|
1064
1186
|
# Not actually a test assert; we need this to teach MyPy that we
|
|
1065
1187
|
# get an stderr when we pass stderr=subprocess.PIPE.
|
|
1066
1188
|
assert p.stderr is not None
|
|
1067
1189
|
stderr = p.stderr.read()
|
|
1068
1190
|
p.wait()
|
|
1069
1191
|
assert p.returncode == 2
|
|
1070
|
-
assert b
|
|
1192
|
+
assert b"Workflow did not pass linting in strict mode" in stderr
|
|
1193
|
+
|
|
1071
1194
|
|
|
1072
1195
|
class TestWDLToilBench(unittest.TestCase):
|
|
1073
1196
|
"""Tests for Toil's MiniWDL-based implementation that don't run workflows."""
|
|
@@ -1178,14 +1301,16 @@ class TestWDLToilBench(unittest.TestCase):
|
|
|
1178
1301
|
assert "decl2" in result[0]
|
|
1179
1302
|
assert "successor" in result[1]
|
|
1180
1303
|
|
|
1181
|
-
def make_string_expr(
|
|
1304
|
+
def make_string_expr(
|
|
1305
|
+
self, to_parse: str, expr_type: type[WDL.Expr.String] = WDL.Expr.String
|
|
1306
|
+
) -> WDL.Expr.String:
|
|
1182
1307
|
"""
|
|
1183
1308
|
Parse pseudo-WDL for testing whitespace removal.
|
|
1184
1309
|
"""
|
|
1185
1310
|
|
|
1186
1311
|
pos = WDL.Error.SourcePosition("nowhere", "nowhere", 0, 0, 0, 0)
|
|
1187
1312
|
|
|
1188
|
-
parts: list[
|
|
1313
|
+
parts: list[str | WDL.Expr.Placeholder] = re.split("(~{[^}]*})", to_parse)
|
|
1189
1314
|
for i in range(1, len(parts), 2):
|
|
1190
1315
|
parts[i] = WDL.Expr.Placeholder(pos, {}, WDL.Expr.Null(pos))
|
|
1191
1316
|
|
|
@@ -1196,9 +1321,7 @@ class TestWDLToilBench(unittest.TestCase):
|
|
|
1196
1321
|
Test to make sure that we pick sensible but non-colliding directories to put files in.
|
|
1197
1322
|
"""
|
|
1198
1323
|
|
|
1199
|
-
from toil.wdl.wdltoil import
|
|
1200
|
-
choose_human_readable_directory,
|
|
1201
|
-
)
|
|
1324
|
+
from toil.wdl.wdltoil import choose_human_readable_directory
|
|
1202
1325
|
|
|
1203
1326
|
# The first time we should get a path with the task name
|
|
1204
1327
|
first_chosen = choose_human_readable_directory(
|