toil 5.12.0__py3-none-any.whl → 6.1.0a1__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 +18 -13
- toil/batchSystems/abstractBatchSystem.py +21 -10
- toil/batchSystems/abstractGridEngineBatchSystem.py +2 -2
- toil/batchSystems/awsBatch.py +14 -14
- toil/batchSystems/contained_executor.py +3 -3
- toil/batchSystems/htcondor.py +0 -1
- toil/batchSystems/kubernetes.py +34 -31
- toil/batchSystems/local_support.py +3 -1
- toil/batchSystems/mesos/batchSystem.py +7 -7
- toil/batchSystems/options.py +32 -83
- toil/batchSystems/registry.py +104 -23
- toil/batchSystems/singleMachine.py +16 -13
- toil/batchSystems/slurm.py +3 -3
- toil/batchSystems/torque.py +0 -1
- toil/bus.py +6 -8
- toil/common.py +532 -743
- toil/cwl/__init__.py +28 -32
- toil/cwl/cwltoil.py +523 -520
- toil/cwl/utils.py +55 -10
- toil/fileStores/__init__.py +2 -2
- toil/fileStores/abstractFileStore.py +36 -11
- toil/fileStores/cachingFileStore.py +607 -530
- toil/fileStores/nonCachingFileStore.py +43 -10
- toil/job.py +140 -75
- toil/jobStores/abstractJobStore.py +147 -79
- toil/jobStores/aws/jobStore.py +23 -9
- toil/jobStores/aws/utils.py +1 -2
- toil/jobStores/fileJobStore.py +117 -19
- toil/jobStores/googleJobStore.py +16 -7
- toil/jobStores/utils.py +5 -6
- toil/leader.py +71 -43
- toil/lib/accelerators.py +10 -5
- toil/lib/aws/__init__.py +3 -14
- toil/lib/aws/ami.py +22 -9
- toil/lib/aws/iam.py +21 -13
- toil/lib/aws/session.py +2 -16
- toil/lib/aws/utils.py +4 -5
- toil/lib/compatibility.py +1 -1
- toil/lib/conversions.py +7 -3
- toil/lib/docker.py +22 -23
- toil/lib/ec2.py +10 -6
- toil/lib/ec2nodes.py +106 -100
- toil/lib/encryption/_nacl.py +2 -1
- toil/lib/generatedEC2Lists.py +325 -18
- toil/lib/io.py +21 -0
- toil/lib/misc.py +1 -1
- toil/lib/resources.py +1 -1
- toil/lib/threading.py +74 -26
- toil/options/common.py +738 -0
- toil/options/cwl.py +336 -0
- toil/options/wdl.py +32 -0
- toil/provisioners/abstractProvisioner.py +1 -4
- toil/provisioners/aws/__init__.py +3 -6
- toil/provisioners/aws/awsProvisioner.py +6 -0
- toil/provisioners/clusterScaler.py +3 -2
- toil/provisioners/gceProvisioner.py +2 -2
- toil/realtimeLogger.py +2 -1
- toil/resource.py +24 -18
- toil/server/app.py +2 -3
- toil/server/cli/wes_cwl_runner.py +4 -4
- toil/server/utils.py +1 -1
- toil/server/wes/abstract_backend.py +3 -2
- toil/server/wes/amazon_wes_utils.py +5 -4
- toil/server/wes/tasks.py +2 -3
- toil/server/wes/toil_backend.py +2 -10
- toil/server/wsgi_app.py +2 -0
- toil/serviceManager.py +12 -10
- toil/statsAndLogging.py +5 -1
- toil/test/__init__.py +29 -54
- toil/test/batchSystems/batchSystemTest.py +11 -111
- toil/test/batchSystems/test_slurm.py +3 -2
- toil/test/cwl/cwlTest.py +213 -90
- toil/test/cwl/glob_dir.cwl +15 -0
- toil/test/cwl/preemptible.cwl +21 -0
- toil/test/cwl/preemptible_expression.cwl +28 -0
- toil/test/cwl/revsort.cwl +1 -1
- toil/test/cwl/revsort2.cwl +1 -1
- toil/test/docs/scriptsTest.py +0 -1
- toil/test/jobStores/jobStoreTest.py +27 -16
- toil/test/lib/aws/test_iam.py +4 -14
- toil/test/lib/aws/test_utils.py +0 -3
- toil/test/lib/dockerTest.py +4 -4
- toil/test/lib/test_ec2.py +11 -16
- toil/test/mesos/helloWorld.py +4 -5
- toil/test/mesos/stress.py +1 -1
- toil/test/provisioners/aws/awsProvisionerTest.py +9 -5
- toil/test/provisioners/clusterScalerTest.py +6 -4
- toil/test/provisioners/clusterTest.py +14 -3
- toil/test/provisioners/gceProvisionerTest.py +0 -6
- toil/test/provisioners/restartScript.py +3 -2
- toil/test/server/serverTest.py +1 -1
- toil/test/sort/restart_sort.py +2 -1
- toil/test/sort/sort.py +2 -1
- toil/test/sort/sortTest.py +2 -13
- toil/test/src/autoDeploymentTest.py +45 -45
- toil/test/src/busTest.py +5 -5
- toil/test/src/checkpointTest.py +2 -2
- toil/test/src/deferredFunctionTest.py +1 -1
- toil/test/src/fileStoreTest.py +32 -16
- toil/test/src/helloWorldTest.py +1 -1
- toil/test/src/importExportFileTest.py +1 -1
- toil/test/src/jobDescriptionTest.py +2 -1
- toil/test/src/jobServiceTest.py +1 -1
- toil/test/src/jobTest.py +18 -18
- toil/test/src/miscTests.py +5 -3
- toil/test/src/promisedRequirementTest.py +3 -3
- toil/test/src/realtimeLoggerTest.py +1 -1
- toil/test/src/resourceTest.py +2 -2
- toil/test/src/restartDAGTest.py +1 -1
- toil/test/src/resumabilityTest.py +36 -2
- toil/test/src/retainTempDirTest.py +1 -1
- toil/test/src/systemTest.py +2 -2
- toil/test/src/toilContextManagerTest.py +2 -2
- toil/test/src/userDefinedJobArgTypeTest.py +1 -1
- toil/test/utils/toilDebugTest.py +98 -32
- toil/test/utils/toilKillTest.py +2 -2
- toil/test/utils/utilsTest.py +20 -0
- toil/test/wdl/wdltoil_test.py +148 -45
- toil/toilState.py +7 -6
- toil/utils/toilClean.py +1 -1
- toil/utils/toilConfig.py +36 -0
- toil/utils/toilDebugFile.py +60 -33
- toil/utils/toilDebugJob.py +39 -12
- toil/utils/toilDestroyCluster.py +1 -1
- toil/utils/toilKill.py +1 -1
- toil/utils/toilLaunchCluster.py +13 -2
- toil/utils/toilMain.py +3 -2
- toil/utils/toilRsyncCluster.py +1 -1
- toil/utils/toilSshCluster.py +1 -1
- toil/utils/toilStats.py +240 -143
- toil/utils/toilStatus.py +1 -4
- toil/version.py +11 -11
- toil/wdl/utils.py +2 -122
- toil/wdl/wdltoil.py +999 -386
- toil/worker.py +25 -31
- {toil-5.12.0.dist-info → toil-6.1.0a1.dist-info}/METADATA +60 -53
- toil-6.1.0a1.dist-info/RECORD +237 -0
- {toil-5.12.0.dist-info → toil-6.1.0a1.dist-info}/WHEEL +1 -1
- {toil-5.12.0.dist-info → toil-6.1.0a1.dist-info}/entry_points.txt +0 -1
- toil/batchSystems/parasol.py +0 -379
- toil/batchSystems/tes.py +0 -459
- toil/test/batchSystems/parasolTestSupport.py +0 -117
- toil/test/wdl/builtinTest.py +0 -506
- toil/test/wdl/conftest.py +0 -23
- toil/test/wdl/toilwdlTest.py +0 -522
- toil/wdl/toilwdl.py +0 -141
- toil/wdl/versions/dev.py +0 -107
- toil/wdl/versions/draft2.py +0 -980
- toil/wdl/versions/v1.py +0 -794
- toil/wdl/wdl_analysis.py +0 -116
- toil/wdl/wdl_functions.py +0 -997
- toil/wdl/wdl_synthesis.py +0 -1011
- toil/wdl/wdl_types.py +0 -243
- toil-5.12.0.dist-info/RECORD +0 -244
- /toil/{wdl/versions → options}/__init__.py +0 -0
- {toil-5.12.0.dist-info → toil-6.1.0a1.dist-info}/LICENSE +0 -0
- {toil-5.12.0.dist-info → toil-6.1.0a1.dist-info}/top_level.txt +0 -0
toil/test/wdl/builtinTest.py
DELETED
|
@@ -1,506 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import os
|
|
3
|
-
import shutil
|
|
4
|
-
import subprocess
|
|
5
|
-
import unittest
|
|
6
|
-
import uuid
|
|
7
|
-
from typing import List, Optional
|
|
8
|
-
|
|
9
|
-
from toil.test import ToilTest
|
|
10
|
-
from toil.version import exactPython
|
|
11
|
-
from toil.wdl.wdl_functions import (WDLPair,
|
|
12
|
-
WDLRuntimeError,
|
|
13
|
-
ceil,
|
|
14
|
-
cross,
|
|
15
|
-
floor,
|
|
16
|
-
length,
|
|
17
|
-
read_boolean,
|
|
18
|
-
read_float,
|
|
19
|
-
read_int,
|
|
20
|
-
read_json,
|
|
21
|
-
read_lines,
|
|
22
|
-
read_map,
|
|
23
|
-
read_string,
|
|
24
|
-
read_tsv,
|
|
25
|
-
sub,
|
|
26
|
-
transpose,
|
|
27
|
-
wdl_zip,
|
|
28
|
-
write_json,
|
|
29
|
-
write_lines,
|
|
30
|
-
write_map,
|
|
31
|
-
write_tsv)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class WdlStandardLibraryFunctionsTest(ToilTest):
|
|
35
|
-
""" A set of test cases for toil's wdl functions."""
|
|
36
|
-
|
|
37
|
-
def setUp(self):
|
|
38
|
-
"""Runs anew before each test to create farm fresh temp dirs."""
|
|
39
|
-
self.output_dir = os.path.join('/tmp/', 'toil-wdl-test-' + str(uuid.uuid4()))
|
|
40
|
-
os.makedirs(self.output_dir)
|
|
41
|
-
os.makedirs(os.path.join(self.output_dir, 'execution'))
|
|
42
|
-
|
|
43
|
-
@classmethod
|
|
44
|
-
def setUpClass(cls):
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
def tearDown(self):
|
|
48
|
-
"""Clean up outputs."""
|
|
49
|
-
if os.path.exists(self.output_dir):
|
|
50
|
-
shutil.rmtree(self.output_dir)
|
|
51
|
-
|
|
52
|
-
def _check_output(self, path, expected_result, strip=True):
|
|
53
|
-
""" Compare expected_result to content from file."""
|
|
54
|
-
with open(path) as f:
|
|
55
|
-
result = f.read()
|
|
56
|
-
if strip:
|
|
57
|
-
result = result.strip()
|
|
58
|
-
self.assertEqual(expected_result, result)
|
|
59
|
-
|
|
60
|
-
def _write_temp_file(self, function_name, content):
|
|
61
|
-
""" Write content to a temp file."""
|
|
62
|
-
path = os.path.join(self.output_dir, f'{function_name}_{uuid.uuid4()}.tmp')
|
|
63
|
-
with open(path, 'w') as f:
|
|
64
|
-
f.write(content + '\n')
|
|
65
|
-
return path
|
|
66
|
-
|
|
67
|
-
def testFn_Sub(self):
|
|
68
|
-
"""Test the wdl built-in functional equivalent of 'sub()'."""
|
|
69
|
-
# example from the WDL spec.
|
|
70
|
-
chocolike = "I like chocolate when it's late"
|
|
71
|
-
self.assertEqual("I love chocolate when it's late", sub(chocolike, 'like', 'love'))
|
|
72
|
-
self.assertEqual("I like chocoearly when it's early", sub(chocolike, 'late', 'early'))
|
|
73
|
-
self.assertEqual("I like chocolate when it's early", sub(chocolike, 'late$', 'early'))
|
|
74
|
-
|
|
75
|
-
def testFn_Ceil(self):
|
|
76
|
-
"""Test the wdl built-in functional equivalent of 'ceil()', which converts
|
|
77
|
-
a Float value into an Int by rounding up to the next higher integer"""
|
|
78
|
-
assert ceil(1.999) == 2
|
|
79
|
-
assert ceil(-1.5) == -1
|
|
80
|
-
|
|
81
|
-
def testFn_Floor(self):
|
|
82
|
-
"""Test the wdl built-in functional equivalent of 'floor()', which converts
|
|
83
|
-
a Float value into an Int by rounding down to the next lower integer"""
|
|
84
|
-
assert floor(1.999) == 1
|
|
85
|
-
assert floor(-1.5) == -2
|
|
86
|
-
|
|
87
|
-
def testFn_ReadLines(self):
|
|
88
|
-
"""Test the wdl built-in functional equivalent of 'read_lines()'."""
|
|
89
|
-
# trailing newlines are stripped; spaces are kept
|
|
90
|
-
lines = 'line 1\nline 2\t\t\n \n\n'
|
|
91
|
-
path = self._write_temp_file('read_lines', lines)
|
|
92
|
-
self.assertEqual(['line 1', 'line 2\t\t', ' '], read_lines(path))
|
|
93
|
-
|
|
94
|
-
# preceding newlines are kept
|
|
95
|
-
lines = '\n\n\nline 1\nline 2\t\t\n '
|
|
96
|
-
path = self._write_temp_file('read_lines', lines)
|
|
97
|
-
self.assertEqual(['', '', '', 'line 1', 'line 2\t\t', ' '], read_lines(path))
|
|
98
|
-
|
|
99
|
-
def testFn_ReadTsv(self):
|
|
100
|
-
"""Test the wdl built-in functional equivalent of 'read_tsv()'."""
|
|
101
|
-
tsv = [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]
|
|
102
|
-
tsv_str = '1\t2\t3\n4\t5\t6\n7\t8\t9'
|
|
103
|
-
|
|
104
|
-
path = self._write_temp_file('read_tsv', tsv_str)
|
|
105
|
-
self.assertEqual(tsv, read_tsv(path))
|
|
106
|
-
|
|
107
|
-
def testFn_ReadJson(self):
|
|
108
|
-
"""Test the wdl built-in functional equivalent of 'read_json()'."""
|
|
109
|
-
json_obj = {'str': 'some string', 'num': 3.14, 'bool': True, 'null': None, 'arr': ['test']}
|
|
110
|
-
json_arr = ['1', '2']
|
|
111
|
-
json_num = 3.14
|
|
112
|
-
|
|
113
|
-
path = self._write_temp_file('read_json', json.dumps(json_obj))
|
|
114
|
-
self.assertEqual(json_obj, read_json(path))
|
|
115
|
-
|
|
116
|
-
path = self._write_temp_file('read_json', json.dumps(json_arr))
|
|
117
|
-
self.assertEqual(json_arr, read_json(path))
|
|
118
|
-
|
|
119
|
-
path = self._write_temp_file('read_json', json.dumps(json_num))
|
|
120
|
-
self.assertEqual(json_num, read_json(path))
|
|
121
|
-
|
|
122
|
-
def testFn_ReadMap(self):
|
|
123
|
-
"""Test the wdl built-in functional equivalent of 'read_map()'."""
|
|
124
|
-
map_str = 'key1\tvalue1\nkey2\tvalue2'
|
|
125
|
-
path = self._write_temp_file('read_map', map_str)
|
|
126
|
-
self.assertEqual({'key1': 'value1', 'key2': 'value2'}, read_map(path))
|
|
127
|
-
|
|
128
|
-
# extra lines and spaces are stripped, except spaces in keys are kept.
|
|
129
|
-
map_str = '\n\n\nkey1 \tvalue1\nkey2\tvalue2 \n \n \t \n'
|
|
130
|
-
path = self._write_temp_file('read_map', map_str)
|
|
131
|
-
self.assertEqual({'key1 ': 'value1', 'key2': 'value2'}, read_map(path))
|
|
132
|
-
|
|
133
|
-
def testFn_ReadInt(self):
|
|
134
|
-
"""Test the wdl built-in functional equivalent of 'read_int()'."""
|
|
135
|
-
num = 10
|
|
136
|
-
path = self._write_temp_file('read_int', content=str(num))
|
|
137
|
-
self.assertEqual(num, read_int(path))
|
|
138
|
-
|
|
139
|
-
num = 10.0
|
|
140
|
-
path = self._write_temp_file('read_int', content=str(num))
|
|
141
|
-
self.assertRaises(ValueError, read_int, path)
|
|
142
|
-
|
|
143
|
-
num = 10.5
|
|
144
|
-
path = self._write_temp_file('read_int', content=str(num))
|
|
145
|
-
self.assertRaises(ValueError, read_int, path)
|
|
146
|
-
|
|
147
|
-
def testFn_ReadString(self):
|
|
148
|
-
"""Test the wdl built-in functional equivalent of 'read_string()'."""
|
|
149
|
-
some_str = 'some string'
|
|
150
|
-
path = self._write_temp_file('read_string', content=some_str)
|
|
151
|
-
self.assertEqual(some_str, read_string(path))
|
|
152
|
-
|
|
153
|
-
# with preceding newlines. Cromwell strips from the front and the end.
|
|
154
|
-
path = self._write_temp_file('read_string', content='\n\n\n' + some_str)
|
|
155
|
-
self.assertEqual(some_str, read_string(path))
|
|
156
|
-
|
|
157
|
-
# with trailing newlines
|
|
158
|
-
path = self._write_temp_file('read_string', content=some_str + '\n\n')
|
|
159
|
-
self.assertEqual(some_str, read_string(path))
|
|
160
|
-
|
|
161
|
-
def testFn_ReadFloat(self):
|
|
162
|
-
"""Test the wdl built-in functional equivalent of 'read_float()'."""
|
|
163
|
-
num = 2.718281828459045
|
|
164
|
-
path = self._write_temp_file('read_float', content=str(num))
|
|
165
|
-
self.assertEqual(num, read_float(path))
|
|
166
|
-
|
|
167
|
-
def testFn_ReadBoolean(self):
|
|
168
|
-
"""Test the wdl built-in functional equivalent of 'read_boolean()'."""
|
|
169
|
-
for val in (True, False):
|
|
170
|
-
path = self._write_temp_file('read_boolean', content=str(val))
|
|
171
|
-
self.assertEqual(val, read_boolean(path))
|
|
172
|
-
|
|
173
|
-
# upper
|
|
174
|
-
path = self._write_temp_file('read_boolean', content=str(val).upper())
|
|
175
|
-
self.assertEqual(val, read_boolean(path))
|
|
176
|
-
|
|
177
|
-
# lower
|
|
178
|
-
path = self._write_temp_file('read_boolean', content=str(val).lower())
|
|
179
|
-
self.assertEqual(val, read_boolean(path))
|
|
180
|
-
|
|
181
|
-
def testFn_WriteLines(self):
|
|
182
|
-
"""Test the wdl built-in functional equivalent of 'write_lines()'."""
|
|
183
|
-
# 'line 1' \n
|
|
184
|
-
# 'line 2\t\t' \n
|
|
185
|
-
# ' ' \n
|
|
186
|
-
# '\n' \n
|
|
187
|
-
path = write_lines(['line 1', 'line 2\t\t', ' ', '\n'], temp_dir=self.output_dir)
|
|
188
|
-
self._check_output(path, 'line 1\nline 2\t\t\n \n\n\n', strip=False)
|
|
189
|
-
|
|
190
|
-
def testFn_WriteTsv(self):
|
|
191
|
-
"""Test the wdl built-in functional equivalent of 'write_tsv()'."""
|
|
192
|
-
path = write_tsv([['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']], temp_dir=self.output_dir)
|
|
193
|
-
self._check_output(path, '1\t2\t3\n4\t5\t6\n7\t8\t9')
|
|
194
|
-
|
|
195
|
-
def testFn_WriteJson(self):
|
|
196
|
-
"""Test the wdl built-in functional equivalent of 'write_json()'."""
|
|
197
|
-
json_obj = {'str': 'some string', 'num': 3.14, 'bool': True, 'null': None, 'arr': ['test']}
|
|
198
|
-
json_arr = ['1', '2']
|
|
199
|
-
json_num = 3.14
|
|
200
|
-
json_str = 'test string'
|
|
201
|
-
json_bool = False
|
|
202
|
-
json_null = None
|
|
203
|
-
|
|
204
|
-
# Pair[Int, Pair[Int, Pair[Int, Pair[Int, Int]]]]
|
|
205
|
-
json_pairs = WDLPair(1, WDLPair(2, WDLPair(3, WDLPair(4, 5))))
|
|
206
|
-
|
|
207
|
-
path = write_json(json_obj, temp_dir=self.output_dir)
|
|
208
|
-
self._check_output(path, '{"str":"some string","num":3.14,"bool":true,"null":null,"arr":["test"]}')
|
|
209
|
-
|
|
210
|
-
path = write_json(json_arr, temp_dir=self.output_dir)
|
|
211
|
-
self._check_output(path, '["1","2"]')
|
|
212
|
-
|
|
213
|
-
path = write_json(json_num, temp_dir=self.output_dir)
|
|
214
|
-
self._check_output(path, '3.14')
|
|
215
|
-
|
|
216
|
-
path = write_json(json_str, temp_dir=self.output_dir)
|
|
217
|
-
self._check_output(path, '"test string"')
|
|
218
|
-
|
|
219
|
-
path = write_json(json_bool, temp_dir=self.output_dir)
|
|
220
|
-
self._check_output(path, 'false')
|
|
221
|
-
|
|
222
|
-
path = write_json(json_null, temp_dir=self.output_dir)
|
|
223
|
-
self._check_output(path, 'null')
|
|
224
|
-
|
|
225
|
-
path = write_json(json_pairs, temp_dir=self.output_dir)
|
|
226
|
-
self._check_output(path, '{"left":1,"right":{"left":2,"right":{"left":3,"right":{"left":4,"right":5}}}}')
|
|
227
|
-
|
|
228
|
-
def testFn_WriteMap(self):
|
|
229
|
-
"""Test the wdl built-in functional equivalent of 'write_map()'."""
|
|
230
|
-
path = write_map({'key1': 'value1', 'key2': 'value2'}, temp_dir=self.output_dir)
|
|
231
|
-
self._check_output(path, 'key1\tvalue1\nkey2\tvalue2')
|
|
232
|
-
|
|
233
|
-
def testFn_Transpose(self):
|
|
234
|
-
"""Test the wdl built-in functional equivalent of 'transpose()'."""
|
|
235
|
-
self.assertEqual([[0, 3], [1, 4], [2, 5]], transpose([[0, 1, 2], [3, 4, 5]]))
|
|
236
|
-
self.assertEqual([[0, 1, 2], [3, 4, 5]], transpose([[0, 3], [1, 4], [2, 5]]))
|
|
237
|
-
|
|
238
|
-
self.assertEqual([], transpose([]))
|
|
239
|
-
self.assertEqual([], transpose([[]])) # same as Cromwell
|
|
240
|
-
self.assertEqual([[0]], transpose([[0]]))
|
|
241
|
-
self.assertRaises(AssertionError, transpose, [[0, 1, 2], [3, 4, 5, 6]])
|
|
242
|
-
|
|
243
|
-
def testFn_Length(self):
|
|
244
|
-
"""Test the WDL 'length()' built-in."""
|
|
245
|
-
self.assertEqual(3, length([1, 2, 3]))
|
|
246
|
-
self.assertEqual(3, length(['a', 'b', 'c']))
|
|
247
|
-
self.assertEqual(0, length([]))
|
|
248
|
-
|
|
249
|
-
def testFn_Zip(self):
|
|
250
|
-
"""Test the wdl built-in functional equivalent of 'zip()'."""
|
|
251
|
-
left_array = [1, 2, 3]
|
|
252
|
-
right_array = ['a', 'b', 'c']
|
|
253
|
-
zipped = wdl_zip(left_array, right_array)
|
|
254
|
-
expected_results = [WDLPair(1, 'a'), WDLPair(2, 'b'), WDLPair(3, 'c')]
|
|
255
|
-
|
|
256
|
-
self.assertEqual(zipped, expected_results)
|
|
257
|
-
|
|
258
|
-
# input with different size should fail.
|
|
259
|
-
self.assertRaises(WDLRuntimeError, wdl_zip, [1, 2, 3], ['a', 'b'])
|
|
260
|
-
|
|
261
|
-
def testFn_Cross(self):
|
|
262
|
-
"""Test the wdl built-in functional equivalent of 'cross()'."""
|
|
263
|
-
left_array = [1, 2, 3]
|
|
264
|
-
right_array = ['a', 'b']
|
|
265
|
-
crossed = cross(left_array, right_array)
|
|
266
|
-
expected_results = [WDLPair(1, 'a'), WDLPair(1, 'b'),
|
|
267
|
-
WDLPair(2, 'a'), WDLPair(2, 'b'),
|
|
268
|
-
WDLPair(3, 'a'), WDLPair(3, 'b')]
|
|
269
|
-
|
|
270
|
-
self.assertEqual(crossed, expected_results)
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
class WdlWorkflowsTest(ToilTest):
|
|
274
|
-
"""
|
|
275
|
-
A set of test cases for toil's conformance with WDL.
|
|
276
|
-
|
|
277
|
-
All tests should include a simple wdl and json file for toil to run that checks the output.
|
|
278
|
-
"""
|
|
279
|
-
|
|
280
|
-
@classmethod
|
|
281
|
-
def setUpClass(cls):
|
|
282
|
-
super().setUpClass()
|
|
283
|
-
cls.program = os.path.abspath("src/toil/wdl/toilwdl.py")
|
|
284
|
-
cls.test_path = os.path.abspath("src/toil/test/wdl")
|
|
285
|
-
|
|
286
|
-
def check_function(self,
|
|
287
|
-
function_name: str,
|
|
288
|
-
cases: List[str],
|
|
289
|
-
json_file_name: Optional[str] = None,
|
|
290
|
-
expected_result: Optional[str] = None,
|
|
291
|
-
expected_exception: Optional[str] = None):
|
|
292
|
-
"""
|
|
293
|
-
Run the given WDL workflow and check its output. The WDL workflow
|
|
294
|
-
should store its output inside a 'output.txt' file that can be
|
|
295
|
-
compared to `expected_result`.
|
|
296
|
-
|
|
297
|
-
If `expected_exception` is set, this test passes only when both the
|
|
298
|
-
workflow fails and that the given `expected_exception` string is
|
|
299
|
-
present in standard error.
|
|
300
|
-
"""
|
|
301
|
-
wdl_files = [os.path.abspath(f'{self.test_path}/{function_name}_{case}.wdl')
|
|
302
|
-
for case in cases]
|
|
303
|
-
json_file = os.path.abspath(f'{self.test_path}/{json_file_name or function_name}.json')
|
|
304
|
-
for wdl_file in wdl_files:
|
|
305
|
-
with self.subTest(f'Testing: {wdl_file} {json_file}'):
|
|
306
|
-
output_dir = f'/tmp/toil-wdl-test-{uuid.uuid4()}'
|
|
307
|
-
os.makedirs(output_dir)
|
|
308
|
-
|
|
309
|
-
if expected_exception is not None:
|
|
310
|
-
with self.assertRaises(subprocess.CalledProcessError) as context:
|
|
311
|
-
# use check_output() here so that the output is read before return.
|
|
312
|
-
subprocess.check_output([exactPython, self.program, wdl_file, json_file, '-o', output_dir],
|
|
313
|
-
stderr=subprocess.PIPE)
|
|
314
|
-
|
|
315
|
-
stderr = context.exception.stderr
|
|
316
|
-
self.assertIsInstance(stderr, bytes)
|
|
317
|
-
self.assertIn(expected_exception, stderr.decode('utf-8'))
|
|
318
|
-
|
|
319
|
-
elif expected_result is not None:
|
|
320
|
-
subprocess.check_call([exactPython, self.program, wdl_file, json_file, '-o', output_dir])
|
|
321
|
-
output = os.path.join(output_dir, 'output.txt')
|
|
322
|
-
with open(output) as f:
|
|
323
|
-
result = f.read().strip()
|
|
324
|
-
self.assertEqual(result, expected_result)
|
|
325
|
-
|
|
326
|
-
else:
|
|
327
|
-
self.fail("Invalid test. Either `expected_result` or `expected_exception` must be set.")
|
|
328
|
-
|
|
329
|
-
shutil.rmtree(output_dir)
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
class WdlLanguageSpecWorkflowsTest(WdlWorkflowsTest):
|
|
333
|
-
"""
|
|
334
|
-
A set of test cases for toil's conformance with the WDL language specification:
|
|
335
|
-
|
|
336
|
-
https://github.com/openwdl/wdl/blob/main/versions/development/SPEC.md#language-specification
|
|
337
|
-
"""
|
|
338
|
-
|
|
339
|
-
@classmethod
|
|
340
|
-
def setUpClass(cls):
|
|
341
|
-
super().setUpClass()
|
|
342
|
-
cls.test_path = os.path.abspath("src/toil/test/wdl/wdl_specification")
|
|
343
|
-
|
|
344
|
-
def test_type_pair(self):
|
|
345
|
-
# NOTE: these tests depend on read_lines(), write_json(), and select_first().
|
|
346
|
-
|
|
347
|
-
expected_result = '[23,"twenty-three","a.bai",{"left":23,"right":"twenty-three"}]'
|
|
348
|
-
self.check_function('type_pair', cases=['basic'], expected_result=expected_result)
|
|
349
|
-
|
|
350
|
-
# tests if files from the pair type are correctly imported.
|
|
351
|
-
# the array of three arrays consists content from:
|
|
352
|
-
# 1. src/toil/test/wdl/testfiles/test_string.txt -> 'A Whale of a Tale.'
|
|
353
|
-
# 2. src/toil/test/wdl/testfiles/test_boolean.txt -> 'true'
|
|
354
|
-
# 3. src/toil/test/wdl/testfiles/test_int.txt -> '11'
|
|
355
|
-
expected_result = '[["A Whale of a Tale."],["true"],["11"]]'
|
|
356
|
-
self.check_function('type_pair', cases=['with_files'], expected_result=expected_result)
|
|
357
|
-
|
|
358
|
-
def test_v1_declaration(self):
|
|
359
|
-
"""
|
|
360
|
-
Basic declaration example modified from the WDL 1.0 spec:
|
|
361
|
-
|
|
362
|
-
https://github.com/openwdl/wdl/blob/main/versions/1.0/SPEC.md#declarations
|
|
363
|
-
"""
|
|
364
|
-
expected_result = 'Hello, x!; Hello, y!'
|
|
365
|
-
self.check_function('v1_spec', cases=['declaration'], expected_result=expected_result)
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
class WdlStandardLibraryWorkflowsTest(WdlWorkflowsTest):
|
|
369
|
-
"""
|
|
370
|
-
A set of test cases for toil's conformance with the WDL built-in standard library:
|
|
371
|
-
|
|
372
|
-
https://github.com/openwdl/wdl/blob/main/versions/development/SPEC.md#standard-library
|
|
373
|
-
"""
|
|
374
|
-
|
|
375
|
-
@classmethod
|
|
376
|
-
def setUpClass(cls):
|
|
377
|
-
super().setUpClass()
|
|
378
|
-
cls.test_path = os.path.abspath("src/toil/test/wdl/standard_library")
|
|
379
|
-
|
|
380
|
-
def test_sub(self):
|
|
381
|
-
# this workflow swaps the extension of a TSV file to CSV, with String and File inputs.
|
|
382
|
-
self.check_function('sub', cases=['as_input'], expected_result='src/toil/test/wdl/test.csv')
|
|
383
|
-
|
|
384
|
-
# NOTE: the result differs from Cromwell since we copy the file to the file store without
|
|
385
|
-
# preserving the path. Cromwell would return 'src/toil/test/wdl/test.csv' instead.
|
|
386
|
-
self.check_function('sub', cases=['as_input_with_file'], expected_result='test.csv')
|
|
387
|
-
|
|
388
|
-
def test_size(self):
|
|
389
|
-
self.check_function('size', cases=['as_command'], expected_result='19.0')
|
|
390
|
-
|
|
391
|
-
# this workflow outputs the size of a 22-byte file in 'B', 'K', and 'Ki' separated with spaces.
|
|
392
|
-
|
|
393
|
-
# NOTE: Cromwell treats the decimal and binary units (e.g.: 'K' and 'Ki') the same, which differs from
|
|
394
|
-
# the spec (https://github.com/openwdl/wdl/blob/main/versions/development/SPEC.md#float-sizefile-string).
|
|
395
|
-
# The correct output should be '22.0 0.022 0.021484375' not '22.0 0.021484375 0.021484375'
|
|
396
|
-
self.check_function('size', cases=['as_output'], expected_result='22.0 0.022 0.021484375')
|
|
397
|
-
|
|
398
|
-
def test_ceil(self):
|
|
399
|
-
self.check_function('ceil', cases=['as_input', 'as_command'], expected_result='12')
|
|
400
|
-
|
|
401
|
-
def test_floor(self):
|
|
402
|
-
self.check_function('floor', cases=['as_input', 'as_command'], expected_result='11')
|
|
403
|
-
|
|
404
|
-
def test_round(self):
|
|
405
|
-
self.check_function('round', cases=['as_input', 'as_command'], expected_result='11')
|
|
406
|
-
|
|
407
|
-
def test_stdout(self):
|
|
408
|
-
self.check_function('stdout', cases=['as_output'], expected_result='A Whale of a Tale.')
|
|
409
|
-
self.check_function('stderr', cases=['as_output'], expected_result='a journey straight to stderr')
|
|
410
|
-
|
|
411
|
-
def test_read(self):
|
|
412
|
-
""" Test the set of WDL read functions."""
|
|
413
|
-
# NOTE: these tests depend on stdout() and the write_*() functions.
|
|
414
|
-
|
|
415
|
-
self.check_function('read_lines', cases=['as_output'],
|
|
416
|
-
expected_result='line 1\n\t\tline 2 with tabs\n line 3\n\nline 5')
|
|
417
|
-
|
|
418
|
-
self.check_function('read_tsv', cases=['as_output'],
|
|
419
|
-
expected_result='1\t2\t3\n4\t5\t6\n7\t8\t9')
|
|
420
|
-
|
|
421
|
-
self.check_function('read_json', cases=['as_output'],
|
|
422
|
-
expected_result='{"key1":"value1","key2":"value2"}')
|
|
423
|
-
|
|
424
|
-
self.check_function('read_map', cases=['as_output'],
|
|
425
|
-
expected_result='key1\tvalue1\nkey2\tvalue2')
|
|
426
|
-
|
|
427
|
-
# primitives
|
|
428
|
-
self.check_function('read_int', cases=['as_command'], expected_result='11')
|
|
429
|
-
self.check_function('read_string', cases=['as_command'], expected_result='A Whale of a Tale.')
|
|
430
|
-
self.check_function('read_float', cases=['as_command'], expected_result='11.2345')
|
|
431
|
-
self.check_function('read_boolean', cases=['as_command'], expected_result='True')
|
|
432
|
-
|
|
433
|
-
def test_write(self):
|
|
434
|
-
""" Test the set of WDL write functions."""
|
|
435
|
-
self.check_function('write_lines', cases=['as_command'],
|
|
436
|
-
expected_result='first\nsecond\nthird')
|
|
437
|
-
|
|
438
|
-
self.check_function('write_tsv', cases=['as_command'],
|
|
439
|
-
expected_result='one\ttwo\tthree\nun\tdeux\ttrois')
|
|
440
|
-
|
|
441
|
-
self.check_function('write_json', cases=['as_command'],
|
|
442
|
-
expected_result='{"key1":"value1","key2":"value2"}')
|
|
443
|
-
|
|
444
|
-
self.check_function('write_map', cases=['as_command'],
|
|
445
|
-
expected_result='key1\tvalue1\nkey2\tvalue2')
|
|
446
|
-
|
|
447
|
-
def test_range(self):
|
|
448
|
-
# NOTE: this test depends on write_lines().
|
|
449
|
-
self.check_function('range', cases=['as_input'],
|
|
450
|
-
expected_result='0\n1\n2\n3\n4\n5\n6\n7')
|
|
451
|
-
|
|
452
|
-
self.check_function('range', cases=['as_input'],
|
|
453
|
-
json_file_name='range_0',
|
|
454
|
-
expected_result='')
|
|
455
|
-
|
|
456
|
-
self.check_function('range', cases=['as_input'],
|
|
457
|
-
json_file_name='range_invalid',
|
|
458
|
-
expected_exception='WDLRuntimeError')
|
|
459
|
-
|
|
460
|
-
def test_transpose(self):
|
|
461
|
-
# NOTE: this test depends on write_tsv().
|
|
462
|
-
|
|
463
|
-
# this workflow writes a transposed 2-dimensional array as a TSV file.
|
|
464
|
-
self.check_function('transpose', cases=['as_input'], expected_result='0\t3\n1\t4\n2\t5')
|
|
465
|
-
|
|
466
|
-
def test_length(self):
|
|
467
|
-
self.check_function('length', cases=['as_input'], expected_result='3')
|
|
468
|
-
|
|
469
|
-
self.check_function('length', cases=['as_input'],
|
|
470
|
-
json_file_name='length_invalid',
|
|
471
|
-
expected_exception='WDLRuntimeError')
|
|
472
|
-
|
|
473
|
-
# length() should not work with Map[X, Y].
|
|
474
|
-
self.check_function('length', cases=['as_input_with_map'],
|
|
475
|
-
expected_exception='WDLRuntimeError')
|
|
476
|
-
|
|
477
|
-
def test_zip(self):
|
|
478
|
-
self.check_function('zip', cases=['as_input'],
|
|
479
|
-
expected_result='[{"left":1,"right":"a"},{"left":2,"right":"b"},{"left":3,"right":"c"}]')
|
|
480
|
-
|
|
481
|
-
def test_cross(self):
|
|
482
|
-
self.check_function('cross', cases=['as_input'],
|
|
483
|
-
expected_result='[{"left":1,"right":"a"},{"left":1,"right":"b"},'
|
|
484
|
-
'{"left":2,"right":"a"},{"left":2,"right":"b"},'
|
|
485
|
-
'{"left":3,"right":"a"},{"left":3,"right":"b"}]')
|
|
486
|
-
|
|
487
|
-
def test_as_pairs(self):
|
|
488
|
-
self.check_function('as_pairs', cases=['as_input'],
|
|
489
|
-
expected_result='[{"left":"a","right":1},{"left":"b","right":2},{"left":"c","right":3}]')
|
|
490
|
-
|
|
491
|
-
def test_as_map(self):
|
|
492
|
-
self.check_function('as_map', cases=['as_input'], expected_result='{"a":1,"b":2,"c":3}')
|
|
493
|
-
|
|
494
|
-
def test_keys(self):
|
|
495
|
-
self.check_function('keys', cases=['as_input'], expected_result='["a","b","c"]')
|
|
496
|
-
|
|
497
|
-
def test_collect_by_key(self):
|
|
498
|
-
# NOTE: this result is expected according to the spec but differs from Cromwell.
|
|
499
|
-
self.check_function('collect_by_key', cases=['as_input'], expected_result='{"a":[1,3],"b":[2]}')
|
|
500
|
-
|
|
501
|
-
def test_flatten(self):
|
|
502
|
-
self.check_function('flatten', cases=['as_input'], expected_result='[1,2,3,1,21,22]')
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
if __name__ == "__main__":
|
|
506
|
-
unittest.main()
|
toil/test/wdl/conftest.py
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# Copyright (C) 2015-2021 Regents of the University of California
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
# https://pytest.org/latest/example/pythoncollection.html
|
|
16
|
-
|
|
17
|
-
collect_ignore = []
|
|
18
|
-
|
|
19
|
-
try:
|
|
20
|
-
import wdlparse
|
|
21
|
-
print(wdlparse.__file__) # keep this import from being removed
|
|
22
|
-
except ImportError:
|
|
23
|
-
collect_ignore.append("toilwdl.py")
|