toil 9.1.2__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 +14 -14
- 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.2.dist-info → toil-9.2.0.dist-info}/METADATA +11 -14
- {toil-9.1.2.dist-info → toil-9.2.0.dist-info}/RECORD +150 -153
- {toil-9.1.2.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.2.dist-info → toil-9.2.0.dist-info}/entry_points.txt +0 -0
- {toil-9.1.2.dist-info → toil-9.2.0.dist-info}/licenses/LICENSE +0 -0
- {toil-9.1.2.dist-info → toil-9.2.0.dist-info}/top_level.txt +0 -0
toil/test/src/jobServiceTest.py
CHANGED
|
@@ -13,21 +13,21 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import codecs
|
|
15
15
|
import logging
|
|
16
|
-
from pathlib import Path
|
|
17
16
|
import random
|
|
18
17
|
import sys
|
|
19
18
|
import time
|
|
20
19
|
import traceback
|
|
21
|
-
from
|
|
20
|
+
from pathlib import Path
|
|
22
21
|
from threading import Event, Thread
|
|
22
|
+
from typing import Any, Literal, cast
|
|
23
23
|
|
|
24
24
|
import pytest
|
|
25
25
|
|
|
26
|
+
from toil.batchSystems import DeadlockException
|
|
26
27
|
from toil.batchSystems.singleMachine import SingleMachineBatchSystem
|
|
27
28
|
from toil.exceptions import FailedJobsException
|
|
28
29
|
from toil.job import Job, ServiceHostJob
|
|
29
30
|
from toil.jobStores.abstractJobStore import AbstractJobStore
|
|
30
|
-
from toil.batchSystems import DeadlockException
|
|
31
31
|
from toil.test import pslow as slow
|
|
32
32
|
|
|
33
33
|
logger = logging.getLogger(__name__)
|
|
@@ -177,9 +177,16 @@ class TestJobService:
|
|
|
177
177
|
total_jobs = BUNDLE_SIZE * BUNDLE_COUNT * 2 + 1
|
|
178
178
|
p_complete_job_failure = FAIL_FRACTION ** (RETRY_COUNT + 1)
|
|
179
179
|
p_workflow_success = (1 - p_complete_job_failure) ** total_jobs
|
|
180
|
-
logger.info(
|
|
180
|
+
logger.info(
|
|
181
|
+
"Going to run %s total jobs, each of which completely fails %s of the time, so the workflow will succeed with probability %s",
|
|
182
|
+
total_jobs,
|
|
183
|
+
p_complete_job_failure,
|
|
184
|
+
p_workflow_success,
|
|
185
|
+
)
|
|
181
186
|
p_test_failure = (1 - p_workflow_success) ** MAX_ATTEMPTS
|
|
182
|
-
logger.info(
|
|
187
|
+
logger.info(
|
|
188
|
+
"This test will fail spuriously with probability %s", p_test_failure
|
|
189
|
+
)
|
|
183
190
|
|
|
184
191
|
# We want to run the workflow through several times to test restarting, so we need it to often fail but reliably sometimes succeed, and almost always succeed when repeated.
|
|
185
192
|
|
|
@@ -192,7 +199,8 @@ class TestJobService:
|
|
|
192
199
|
outFiles = [tmp_path / f"test{test}_{j}" for j in range(BUNDLE_COUNT)]
|
|
193
200
|
# We send 3 messages each in 2 sets, each of which needs a service and a client
|
|
194
201
|
messageBundles = [
|
|
195
|
-
[random.randint(1, sys.maxsize) for i in range(BUNDLE_SIZE)]
|
|
202
|
+
[random.randint(1, sys.maxsize) for i in range(BUNDLE_SIZE)]
|
|
203
|
+
for j in range(BUNDLE_COUNT)
|
|
196
204
|
]
|
|
197
205
|
# Wire up the services/jobs
|
|
198
206
|
t = Job.wrapJobFn(
|
|
@@ -247,7 +255,12 @@ class TestJobService:
|
|
|
247
255
|
break
|
|
248
256
|
except FailedJobsException as e:
|
|
249
257
|
i = e.numberOfFailedJobs
|
|
250
|
-
logger.info(
|
|
258
|
+
logger.info(
|
|
259
|
+
"Workflow attempt %s/%s failed with %s failed jobs",
|
|
260
|
+
total_tries,
|
|
261
|
+
max_attempts,
|
|
262
|
+
i,
|
|
263
|
+
)
|
|
251
264
|
if total_tries == max_attempts:
|
|
252
265
|
pytest.fail(reason="Exceeded a reasonable number of restarts")
|
|
253
266
|
total_tries += 1
|
|
@@ -261,10 +274,7 @@ class TestPerfectServicet(TestJobService):
|
|
|
261
274
|
Let us run all the tests in the other service test class, but without worker failures.
|
|
262
275
|
"""
|
|
263
276
|
kwargs["badWorker"] = 0
|
|
264
|
-
super().runToil(
|
|
265
|
-
*args,
|
|
266
|
-
**kwargs
|
|
267
|
-
)
|
|
277
|
+
super().runToil(*args, **kwargs)
|
|
268
278
|
|
|
269
279
|
|
|
270
280
|
def serviceTest(job: Job, outFile: Path, messageInt: int) -> None:
|
|
@@ -278,9 +288,7 @@ def serviceTest(job: Job, outFile: Path, messageInt: int) -> None:
|
|
|
278
288
|
# the serviceAccessor, to prove that when service test is checkpointed and
|
|
279
289
|
# restarted there is never a connection made between an earlier service and
|
|
280
290
|
# later serviceAccessor, or vice versa.
|
|
281
|
-
to_subtract = random.randint(
|
|
282
|
-
1, sys.maxsize
|
|
283
|
-
)
|
|
291
|
+
to_subtract = random.randint(1, sys.maxsize)
|
|
284
292
|
job.addChildJobFn(
|
|
285
293
|
serviceAccessor,
|
|
286
294
|
job.addService(ToyService(messageInt + to_subtract)),
|
toil/test/src/jobTest.py
CHANGED
|
@@ -11,13 +11,12 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
from collections.abc import Callable
|
|
15
14
|
import collections
|
|
16
|
-
import logging
|
|
17
15
|
import os
|
|
18
|
-
from pathlib import Path
|
|
19
16
|
import random
|
|
20
|
-
from
|
|
17
|
+
from collections.abc import Callable
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Any, Callable, NoReturn, cast
|
|
21
20
|
|
|
22
21
|
import pytest
|
|
23
22
|
|
|
@@ -28,14 +27,12 @@ from toil.job import (
|
|
|
28
27
|
Job,
|
|
29
28
|
JobFunctionWrappingJob,
|
|
30
29
|
JobGraphDeadlockException,
|
|
31
|
-
ServiceHostJob,
|
|
32
30
|
Promise,
|
|
31
|
+
ServiceHostJob,
|
|
33
32
|
)
|
|
34
33
|
from toil.lib.misc import FileDescriptorOrPath
|
|
35
34
|
from toil.test import pslow as slow
|
|
36
35
|
|
|
37
|
-
from pytest_subtests import SubTests
|
|
38
|
-
|
|
39
36
|
|
|
40
37
|
class TestJob:
|
|
41
38
|
"""Tests the job class."""
|
|
@@ -155,6 +152,63 @@ class TestJob:
|
|
|
155
152
|
with pytest.raises(FailedJobsException):
|
|
156
153
|
toil.start(i)
|
|
157
154
|
|
|
155
|
+
def testDeadlockDetectionStatic(self) -> None:
|
|
156
|
+
"""
|
|
157
|
+
Test cycle detection on small example graphs.
|
|
158
|
+
"""
|
|
159
|
+
# Test 1: Simple 3-node graph with a child cycle: 0 -> 1 -> 2 -> 0
|
|
160
|
+
childEdges: set[tuple[int, int]] = {(0, 1), (1, 2)}
|
|
161
|
+
followOnEdges: set[tuple[int, int]] = set()
|
|
162
|
+
# Valid DAG should pass
|
|
163
|
+
rootJob = self.makeJobGraph(3, childEdges, followOnEdges, None, False)
|
|
164
|
+
rootJob.checkJobGraphAcylic()
|
|
165
|
+
rootJob.checkJobGraphConnected()
|
|
166
|
+
# Adding edge (2, 0) creates cycle
|
|
167
|
+
childEdges.add((2, 0))
|
|
168
|
+
with pytest.raises(JobGraphDeadlockException):
|
|
169
|
+
self.makeJobGraph(3, childEdges, followOnEdges, None, False).checkJobGraphAcylic()
|
|
170
|
+
|
|
171
|
+
# Test 2: Self-loop (0 -> 0)
|
|
172
|
+
childEdges = {(0, 1), (0, 0)}
|
|
173
|
+
with pytest.raises(JobGraphDeadlockException):
|
|
174
|
+
self.makeJobGraph(2, childEdges, followOnEdges, None, False).checkJobGraphAcylic()
|
|
175
|
+
|
|
176
|
+
# Test 3: Multiple roots detection (nodes 0 and 2 are both roots)
|
|
177
|
+
childEdges = {(0, 1), (2, 1)} # Both 0 and 2 point to 1, neither has incoming edges
|
|
178
|
+
with pytest.raises(JobGraphDeadlockException):
|
|
179
|
+
self.makeJobGraph(3, childEdges, followOnEdges, None, False).checkJobGraphConnected()
|
|
180
|
+
|
|
181
|
+
# Test 4: Follow-on creating a cycle
|
|
182
|
+
# Graph: 0 -> 1, with follow-on 1 -> 0
|
|
183
|
+
childEdges = {(0, 1)}
|
|
184
|
+
followOnEdges = {(1, 0)}
|
|
185
|
+
with pytest.raises(JobGraphDeadlockException):
|
|
186
|
+
self.makeJobGraph(2, childEdges, followOnEdges, None, False).checkJobGraphAcylic()
|
|
187
|
+
|
|
188
|
+
# Test 5: Self follow-on
|
|
189
|
+
childEdges = {(0, 1)}
|
|
190
|
+
followOnEdges = {(0, 0)}
|
|
191
|
+
with pytest.raises(JobGraphDeadlockException):
|
|
192
|
+
self.makeJobGraph(2, childEdges, followOnEdges, None, False).checkJobGraphAcylic()
|
|
193
|
+
|
|
194
|
+
# Test 6: Larger graph - 5 nodes in a chain, add back-edge
|
|
195
|
+
childEdges = {(0, 1), (1, 2), (2, 3), (3, 4)}
|
|
196
|
+
followOnEdges = set()
|
|
197
|
+
rootJob = self.makeJobGraph(5, childEdges, followOnEdges, None, False)
|
|
198
|
+
rootJob.checkJobGraphAcylic()
|
|
199
|
+
# Add back-edge from 4 to 2
|
|
200
|
+
childEdges.add((4, 2))
|
|
201
|
+
with pytest.raises(JobGraphDeadlockException):
|
|
202
|
+
self.makeJobGraph(5, childEdges, followOnEdges, None, False).checkJobGraphAcylic()
|
|
203
|
+
|
|
204
|
+
# We have this marked as xfail but allow it to pass also, to try and
|
|
205
|
+
# collect failing cases without breaking unrelated PRs.
|
|
206
|
+
# TODO: In the future, go through the CI logs and find the cases that
|
|
207
|
+
# manage to fail. No failure was found in many iterations locally.
|
|
208
|
+
@pytest.mark.xfail(
|
|
209
|
+
reason="Flaky test - see https://github.com/DataBiosphere/toil/issues/5354",
|
|
210
|
+
strict=False,
|
|
211
|
+
)
|
|
158
212
|
def testDeadlockDetection(self) -> None:
|
|
159
213
|
"""
|
|
160
214
|
Randomly generate job graphs with various types of cycle in them and
|
|
@@ -189,17 +243,31 @@ class TestJob:
|
|
|
189
243
|
rootJob2 = self.makeJobGraph(
|
|
190
244
|
nodeNumber + 1, childEdges2, followOnEdges, None, False
|
|
191
245
|
)
|
|
192
|
-
|
|
193
|
-
rootJob2.checkJobGraphConnected
|
|
246
|
+
self._assertDeadlockDetected(
|
|
247
|
+
rootJob2.checkJobGraphConnected,
|
|
248
|
+
"multiple roots",
|
|
249
|
+
nodeNumber + 1,
|
|
250
|
+
childEdges2,
|
|
251
|
+
followOnEdges,
|
|
252
|
+
)
|
|
194
253
|
|
|
195
254
|
def checkChildEdgeCycleDetection(fNode: int, tNode: int) -> None:
|
|
196
255
|
childEdges.add((fNode, tNode)) # Create a cycle
|
|
197
256
|
adjacencyList[fNode].add(tNode)
|
|
198
|
-
assert not self.isAcyclic(adjacencyList)
|
|
199
|
-
|
|
200
|
-
|
|
257
|
+
assert not self.isAcyclic(adjacencyList), (
|
|
258
|
+
f"isAcyclic incorrectly returned True after adding cycle edge "
|
|
259
|
+
f"({fNode}, {tNode}). nodeNumber={nodeNumber}, "
|
|
260
|
+
f"childEdges={childEdges}, followOnEdges={followOnEdges}"
|
|
261
|
+
)
|
|
262
|
+
self._assertDeadlockDetected(
|
|
263
|
+
lambda: self.makeJobGraph(
|
|
201
264
|
nodeNumber, childEdges, followOnEdges, None
|
|
202
|
-
).checkJobGraphAcylic()
|
|
265
|
+
).checkJobGraphAcylic(),
|
|
266
|
+
f"child edge cycle ({fNode}, {tNode})",
|
|
267
|
+
nodeNumber,
|
|
268
|
+
childEdges,
|
|
269
|
+
followOnEdges,
|
|
270
|
+
)
|
|
203
271
|
# Remove the edges
|
|
204
272
|
childEdges.remove((fNode, tNode))
|
|
205
273
|
adjacencyList[fNode].remove(tNode)
|
|
@@ -210,10 +278,15 @@ class TestJob:
|
|
|
210
278
|
|
|
211
279
|
def checkFollowOnEdgeCycleDetection(fNode: int, tNode: int) -> None:
|
|
212
280
|
followOnEdges.add((fNode, tNode)) # Create a cycle
|
|
213
|
-
|
|
214
|
-
self.makeJobGraph(
|
|
281
|
+
self._assertDeadlockDetected(
|
|
282
|
+
lambda: self.makeJobGraph(
|
|
215
283
|
nodeNumber, childEdges, followOnEdges, None, False
|
|
216
|
-
).checkJobGraphAcylic()
|
|
284
|
+
).checkJobGraphAcylic(),
|
|
285
|
+
f"follow-on edge cycle ({fNode}, {tNode})",
|
|
286
|
+
nodeNumber,
|
|
287
|
+
childEdges,
|
|
288
|
+
followOnEdges,
|
|
289
|
+
)
|
|
217
290
|
# Remove the edges
|
|
218
291
|
followOnEdges.remove((fNode, tNode))
|
|
219
292
|
# Check is now acyclic again
|
|
@@ -255,10 +328,33 @@ class TestJob:
|
|
|
255
328
|
):
|
|
256
329
|
checkFollowOnEdgeCycleDetection(fNode, tNode)
|
|
257
330
|
|
|
331
|
+
def _assertDeadlockDetected(
|
|
332
|
+
self,
|
|
333
|
+
check_fn: Callable[[], None],
|
|
334
|
+
description: str,
|
|
335
|
+
nodeNumber: int,
|
|
336
|
+
childEdges: set[tuple[int, int]],
|
|
337
|
+
followOnEdges: set[tuple[int, int]],
|
|
338
|
+
) -> None:
|
|
339
|
+
"""
|
|
340
|
+
Assert that check_fn raises JobGraphDeadlockException.
|
|
341
|
+
|
|
342
|
+
If it doesn't, provide detailed graph info for reproduction.
|
|
343
|
+
"""
|
|
344
|
+
try:
|
|
345
|
+
check_fn()
|
|
346
|
+
except JobGraphDeadlockException:
|
|
347
|
+
return # Expected
|
|
348
|
+
pytest.fail(
|
|
349
|
+
f"JobGraphDeadlockException not raised for {description}. "
|
|
350
|
+
f"Graph info for reproduction: nodeNumber={nodeNumber}, "
|
|
351
|
+
f"childEdges={repr(childEdges)}, followOnEdges={repr(followOnEdges)}"
|
|
352
|
+
)
|
|
353
|
+
|
|
258
354
|
@slow
|
|
259
355
|
@pytest.mark.slow
|
|
260
356
|
def testNewCheckpointIsLeafVertexNonRootCase(
|
|
261
|
-
self, tmp_path: Path, subtests:
|
|
357
|
+
self, tmp_path: Path, subtests: pytest.Subtests
|
|
262
358
|
) -> None:
|
|
263
359
|
"""
|
|
264
360
|
Test for issue #1465: Detection of checkpoint jobs that are not leaf vertices
|
|
@@ -285,7 +381,7 @@ class TestJob:
|
|
|
285
381
|
@slow
|
|
286
382
|
@pytest.mark.slow
|
|
287
383
|
def testNewCheckpointIsLeafVertexRootCase(
|
|
288
|
-
self, tmp_path: Path, subtests:
|
|
384
|
+
self, tmp_path: Path, subtests: pytest.Subtests
|
|
289
385
|
) -> None:
|
|
290
386
|
"""
|
|
291
387
|
Test for issue #1466: Detection of checkpoint jobs that are not leaf vertices
|
|
@@ -307,7 +403,7 @@ class TestJob:
|
|
|
307
403
|
def runNewCheckpointIsLeafVertexTest(
|
|
308
404
|
self,
|
|
309
405
|
tmp_path: Path,
|
|
310
|
-
subtests:
|
|
406
|
+
subtests: pytest.Subtests,
|
|
311
407
|
createWorkflowFn: Callable[[], tuple[Job, Job]],
|
|
312
408
|
) -> None:
|
|
313
409
|
"""
|
|
@@ -369,10 +465,10 @@ class TestJob:
|
|
|
369
465
|
workflowRootJob: Job,
|
|
370
466
|
checkpointJob: Job,
|
|
371
467
|
tmp_path: Path,
|
|
372
|
-
checkpointJobService:
|
|
373
|
-
checkpointJobChild:
|
|
374
|
-
checkpointJobFollowOn:
|
|
375
|
-
expectedException:
|
|
468
|
+
checkpointJobService: Job.Service | None = None,
|
|
469
|
+
checkpointJobChild: Job | None = None,
|
|
470
|
+
checkpointJobFollowOn: Job | None = None,
|
|
471
|
+
expectedException: type[Exception] | None = None,
|
|
376
472
|
) -> None:
|
|
377
473
|
"""
|
|
378
474
|
Modifies the checkpoint job according to the given parameters
|
|
@@ -590,7 +686,7 @@ class TestJob:
|
|
|
590
686
|
nodeNumber: int,
|
|
591
687
|
childEdges: set[tuple[int, int]],
|
|
592
688
|
followOnEdges: set[tuple[int, int]],
|
|
593
|
-
outPath:
|
|
689
|
+
outPath: Path | None,
|
|
594
690
|
addServices: bool = True,
|
|
595
691
|
) -> Job:
|
|
596
692
|
"""
|
|
@@ -666,7 +762,7 @@ class TestJob:
|
|
|
666
762
|
list.
|
|
667
763
|
"""
|
|
668
764
|
|
|
669
|
-
def cyclic(fNode: int, visited: set[int], stack: list[int]) ->
|
|
765
|
+
def cyclic(fNode: int, visited: set[int], stack: list[int]) -> bool | int:
|
|
670
766
|
if fNode not in visited:
|
|
671
767
|
visited.add(fNode)
|
|
672
768
|
assert fNode not in stack
|
toil/test/src/miscTests.py
CHANGED
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
import inspect
|
|
15
15
|
import logging
|
|
16
16
|
import os
|
|
17
|
-
import re
|
|
18
|
-
from pathlib import Path
|
|
19
17
|
import random
|
|
18
|
+
import re
|
|
20
19
|
import sys
|
|
21
|
-
from
|
|
20
|
+
from pathlib import Path
|
|
22
21
|
from uuid import uuid4
|
|
23
|
-
|
|
22
|
+
|
|
23
|
+
import pytest
|
|
24
24
|
|
|
25
25
|
from toil.common import getNodeID
|
|
26
26
|
from toil.lib.exceptions import panic, raise_
|
|
@@ -28,8 +28,6 @@ from toil.lib.io import AtomicFileCreate, atomic_install, atomic_tmp_file, mkdte
|
|
|
28
28
|
from toil.lib.misc import CalledProcessErrorStderr, StrPath, call_command
|
|
29
29
|
from toil.test import pslow as slow
|
|
30
30
|
|
|
31
|
-
import pytest
|
|
32
|
-
|
|
33
31
|
log = logging.getLogger(__name__)
|
|
34
32
|
logging.basicConfig()
|
|
35
33
|
|
|
@@ -63,7 +61,7 @@ class TestMisc:
|
|
|
63
61
|
# a list of the directories used in the test
|
|
64
62
|
directories: list[StrPath] = [tmp_path]
|
|
65
63
|
# A dict of {FILENAME: FILESIZE or FILELINK} for all files used in the test
|
|
66
|
-
files: dict[Path,
|
|
64
|
+
files: dict[Path, int | str] = {}
|
|
67
65
|
# Create a random directory structure
|
|
68
66
|
for i in range(0, 10):
|
|
69
67
|
directories.append(mkdtemp(dir=random.choice(directories), prefix="test"))
|
|
@@ -12,22 +12,23 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from collections.abc import Generator
|
|
16
15
|
import argparse
|
|
17
16
|
import logging
|
|
18
17
|
import os
|
|
19
|
-
from pathlib import Path
|
|
20
18
|
import time
|
|
19
|
+
from collections.abc import Generator
|
|
20
|
+
from pathlib import Path
|
|
21
21
|
from typing import Any
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
import pytest
|
|
24
|
+
|
|
24
25
|
from toil.batchSystems.mesos.test import MesosTestSupport
|
|
25
26
|
from toil.fileStores import FileID
|
|
26
|
-
from toil.job import Job,
|
|
27
|
+
from toil.job import Job, JobFunctionWrappingJob, Promise, PromisedRequirement
|
|
27
28
|
from toil.lib.retry import retry_flaky_test
|
|
28
|
-
from toil.test import pneeds_mesos as needs_mesos
|
|
29
|
-
|
|
30
|
-
import
|
|
29
|
+
from toil.test import pneeds_mesos as needs_mesos
|
|
30
|
+
from toil.test import pslow as slow
|
|
31
|
+
from toil.test.batchSystems import batchSystemTest
|
|
31
32
|
|
|
32
33
|
log = logging.getLogger(__name__)
|
|
33
34
|
|
toil/test/src/regularLogTest.py
CHANGED
|
@@ -14,10 +14,9 @@
|
|
|
14
14
|
import logging
|
|
15
15
|
import mimetypes
|
|
16
16
|
import os
|
|
17
|
-
from pathlib import Path
|
|
18
17
|
import subprocess
|
|
19
18
|
import sys
|
|
20
|
-
from
|
|
19
|
+
from pathlib import Path
|
|
21
20
|
|
|
22
21
|
from toil.test import pslow as slow
|
|
23
22
|
from toil.test.mesos import helloWorld
|
|
@@ -36,7 +35,7 @@ class RegularLogTest:
|
|
|
36
35
|
]
|
|
37
36
|
|
|
38
37
|
def _assertFileTypeExists(
|
|
39
|
-
self, dirpath: Path, extension: str, encoding:
|
|
38
|
+
self, dirpath: Path, extension: str, encoding: str | None = None
|
|
40
39
|
) -> None:
|
|
41
40
|
# an encoding of None implies no compression
|
|
42
41
|
logger.info("Checking for %s file in %s", extension, dirpath)
|
toil/test/src/resourceTest.py
CHANGED
|
@@ -11,27 +11,24 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
from collections.abc import Iterable
|
|
15
14
|
import importlib
|
|
16
15
|
import os
|
|
17
|
-
from pathlib import Path
|
|
18
16
|
import subprocess
|
|
19
17
|
import sys
|
|
20
|
-
import
|
|
21
|
-
from contextlib import contextmanager
|
|
18
|
+
from collections.abc import Iterable
|
|
22
19
|
from inspect import getsource
|
|
23
20
|
from io import BytesIO
|
|
21
|
+
from pathlib import Path
|
|
24
22
|
from textwrap import dedent
|
|
25
23
|
from unittest.mock import MagicMock, patch
|
|
26
24
|
from zipfile import ZipFile
|
|
27
|
-
|
|
25
|
+
|
|
26
|
+
import pytest
|
|
28
27
|
|
|
29
28
|
from toil import inVirtualEnv
|
|
30
29
|
from toil.resource import ModuleDescriptor, Resource, ResourceException
|
|
31
30
|
from toil.version import exactPython
|
|
32
31
|
|
|
33
|
-
import pytest
|
|
34
|
-
|
|
35
32
|
|
|
36
33
|
def tempFileContaining(directory: Path, content: str, suffix: str = "") -> str:
|
|
37
34
|
"""
|
|
@@ -151,7 +148,7 @@ class TestResource:
|
|
|
151
148
|
self,
|
|
152
149
|
module_name: str,
|
|
153
150
|
shouldBelongToToil: bool = False,
|
|
154
|
-
expectedContents:
|
|
151
|
+
expectedContents: Iterable[str] | None = None,
|
|
155
152
|
allowExtraContents: bool = True,
|
|
156
153
|
) -> None:
|
|
157
154
|
module = ModuleDescriptor.forModule(module_name)
|
toil/test/src/restartDAGTest.py
CHANGED
|
@@ -15,17 +15,16 @@
|
|
|
15
15
|
|
|
16
16
|
import logging
|
|
17
17
|
import os
|
|
18
|
-
from pathlib import Path
|
|
19
18
|
import signal
|
|
20
|
-
from
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
import pytest
|
|
21
22
|
|
|
22
23
|
from toil.common import Toil
|
|
23
24
|
from toil.exceptions import FailedJobsException
|
|
24
25
|
from toil.job import Job
|
|
25
26
|
from toil.test import pslow as slow
|
|
26
27
|
|
|
27
|
-
import pytest
|
|
28
|
-
|
|
29
28
|
logger = logging.getLogger(__name__)
|
|
30
29
|
|
|
31
30
|
|
|
@@ -89,7 +88,7 @@ class TestRestartDAG:
|
|
|
89
88
|
|
|
90
89
|
assert not childFile.exists()
|
|
91
90
|
|
|
92
|
-
errorRaised:
|
|
91
|
+
errorRaised: BaseException | None = None
|
|
93
92
|
# Run the test
|
|
94
93
|
for runMode in "start", "restart":
|
|
95
94
|
errorRaised = None
|
|
@@ -142,7 +141,7 @@ class TestRestartDAG:
|
|
|
142
141
|
)
|
|
143
142
|
|
|
144
143
|
|
|
145
|
-
def passingFn(job: Job, file:
|
|
144
|
+
def passingFn(job: Job, file: Path | None = None) -> None:
|
|
146
145
|
"""
|
|
147
146
|
This function is guaranteed to pass as it does nothing out of the ordinary.
|
|
148
147
|
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
|
|
17
|
+
import pytest
|
|
18
|
+
|
|
17
19
|
from toil.exceptions import FailedJobsException
|
|
18
20
|
from toil.job import Job, JobFunctionWrappingJob
|
|
19
21
|
from toil.jobStores.abstractJobStore import NoSuchFileException
|
|
20
22
|
from toil.test import pslow as slow
|
|
21
23
|
|
|
22
|
-
import pytest
|
|
23
|
-
|
|
24
24
|
|
|
25
25
|
class TestResumability:
|
|
26
26
|
"""
|
|
@@ -12,15 +12,15 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import argparse
|
|
15
|
-
from collections.abc import Callable
|
|
16
15
|
import os
|
|
16
|
+
from collections.abc import Callable
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
|
|
19
|
+
import pytest
|
|
20
|
+
|
|
19
21
|
from toil.exceptions import FailedJobsException
|
|
20
22
|
from toil.job import Job, JobFunctionWrappingJob
|
|
21
23
|
|
|
22
|
-
import pytest
|
|
23
|
-
|
|
24
24
|
|
|
25
25
|
class TestCleanWorkDir:
|
|
26
26
|
"""
|
toil/test/src/systemTest.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import errno
|
|
2
2
|
import multiprocessing
|
|
3
3
|
import os
|
|
4
|
-
from pathlib import Path
|
|
5
4
|
from functools import partial
|
|
6
|
-
from
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
from toil.lib.io import mkdtemp
|
|
9
9
|
from toil.lib.threading import cpu_count
|
|
@@ -44,7 +44,7 @@ class TestSystem:
|
|
|
44
44
|
|
|
45
45
|
def _testAtomicityOfNonEmptyDirectoryRenamesTask(
|
|
46
46
|
parent: Path, child: Path, _: Any
|
|
47
|
-
) ->
|
|
47
|
+
) -> int | None:
|
|
48
48
|
tmpChildDir = mkdtemp(dir=parent, prefix="child", suffix=".tmp")
|
|
49
49
|
grandChild = os.path.join(tmpChildDir, "grandChild")
|
|
50
50
|
open(grandChild, "w").close()
|
toil/test/src/threadingTest.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import multiprocessing
|
|
3
3
|
import os
|
|
4
|
-
from pathlib import Path
|
|
5
4
|
import random
|
|
6
5
|
import time
|
|
7
6
|
import traceback
|
|
8
7
|
from functools import partial
|
|
8
|
+
from pathlib import Path
|
|
9
9
|
|
|
10
10
|
from toil.lib.threading import LastProcessStandingArena, cpu_count, global_mutex
|
|
11
11
|
|
toil/test/src/workerTest.py
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from typing import Optional
|
|
16
15
|
|
|
17
16
|
from toil.common import Config
|
|
18
17
|
from toil.job import CheckpointJobDescription, JobDescription
|
|
@@ -42,7 +41,7 @@ class WorkerTests(ToilTest):
|
|
|
42
41
|
disk,
|
|
43
42
|
preemptible: bool = True,
|
|
44
43
|
checkpoint: bool = False,
|
|
45
|
-
local:
|
|
44
|
+
local: bool | None = None,
|
|
46
45
|
):
|
|
47
46
|
"""
|
|
48
47
|
Create a JobDescription with no command (representing a Job that
|
toil/test/utils/toilDebugTest.py
CHANGED
|
@@ -13,15 +13,17 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import logging
|
|
15
15
|
import os
|
|
16
|
-
from pathlib import Path
|
|
17
16
|
import subprocess
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
import pytest
|
|
18
20
|
|
|
19
21
|
from toil.lib.resources import glob
|
|
20
|
-
from toil.test import get_data
|
|
22
|
+
from toil.test import get_data
|
|
23
|
+
from toil.test import pneeds_wdl as needs_wdl
|
|
24
|
+
from toil.test import pslow as slow
|
|
21
25
|
from toil.version import python
|
|
22
26
|
|
|
23
|
-
import pytest
|
|
24
|
-
|
|
25
27
|
logger = logging.getLogger(__name__)
|
|
26
28
|
|
|
27
29
|
|
toil/test/utils/toilKillTest.py
CHANGED
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
|
|
15
15
|
import logging
|
|
16
16
|
import os
|
|
17
|
-
from pathlib import Path
|
|
18
17
|
import subprocess
|
|
19
18
|
import sys
|
|
20
19
|
import time
|
|
21
20
|
import unittest
|
|
21
|
+
from pathlib import Path
|
|
22
22
|
|
|
23
23
|
from toil.common import Toil
|
|
24
24
|
from toil.jobStores.abstractJobStore import NoSuchFileException, NoSuchJobStoreException
|