toil 5.12.0__py3-none-any.whl → 6.1.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 +18 -13
- toil/batchSystems/abstractBatchSystem.py +39 -13
- toil/batchSystems/abstractGridEngineBatchSystem.py +24 -24
- toil/batchSystems/awsBatch.py +14 -14
- toil/batchSystems/cleanup_support.py +7 -3
- 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/lsf.py +7 -7
- 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 +87 -16
- toil/batchSystems/torque.py +0 -1
- toil/bus.py +44 -8
- toil/common.py +544 -753
- toil/cwl/__init__.py +28 -32
- toil/cwl/cwltoil.py +595 -574
- toil/cwl/utils.py +55 -10
- toil/exceptions.py +1 -1
- toil/fileStores/__init__.py +2 -2
- toil/fileStores/abstractFileStore.py +88 -14
- toil/fileStores/cachingFileStore.py +610 -549
- toil/fileStores/nonCachingFileStore.py +46 -22
- toil/job.py +182 -101
- toil/jobStores/abstractJobStore.py +161 -95
- toil/jobStores/aws/jobStore.py +23 -9
- toil/jobStores/aws/utils.py +6 -6
- toil/jobStores/fileJobStore.py +116 -18
- toil/jobStores/googleJobStore.py +16 -7
- toil/jobStores/utils.py +5 -6
- toil/leader.py +87 -56
- 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 +26 -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 +49 -2
- toil/lib/misc.py +1 -1
- toil/lib/resources.py +9 -2
- toil/lib/threading.py +101 -38
- toil/options/common.py +736 -0
- toil/options/cwl.py +336 -0
- toil/options/wdl.py +37 -0
- toil/provisioners/abstractProvisioner.py +9 -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 +41 -9
- toil/test/__init__.py +29 -54
- toil/test/batchSystems/batchSystemTest.py +11 -111
- toil/test/batchSystems/test_slurm.py +24 -8
- toil/test/cactus/__init__.py +0 -0
- toil/test/cactus/test_cactus_integration.py +58 -0
- toil/test/cwl/cwlTest.py +438 -223
- 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 +2 -3
- toil/test/jobStores/jobStoreTest.py +34 -21
- 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 +12 -17
- toil/test/mesos/helloWorld.py +4 -5
- toil/test/mesos/stress.py +1 -1
- toil/test/{wdl/conftest.py → options/__init__.py} +0 -10
- toil/test/options/options.py +37 -0
- toil/test/provisioners/aws/awsProvisionerTest.py +9 -5
- toil/test/provisioners/clusterScalerTest.py +6 -4
- toil/test/provisioners/clusterTest.py +23 -11
- 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 +23 -3
- toil/test/wdl/wdltoil_test.py +223 -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 +445 -305
- toil/utils/toilStatus.py +2 -5
- toil/version.py +10 -10
- toil/wdl/utils.py +2 -122
- toil/wdl/wdltoil.py +1257 -492
- toil/worker.py +55 -46
- toil-6.1.0.dist-info/METADATA +124 -0
- toil-6.1.0.dist-info/RECORD +241 -0
- {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/WHEEL +1 -1
- {toil-5.12.0.dist-info → toil-6.1.0.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/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/METADATA +0 -118
- 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.0.dist-info}/LICENSE +0 -0
- {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/top_level.txt +0 -0
toil/test/src/miscTests.py
CHANGED
|
@@ -16,12 +16,14 @@ import logging
|
|
|
16
16
|
import os
|
|
17
17
|
import random
|
|
18
18
|
import sys
|
|
19
|
-
import tempfile
|
|
20
19
|
from uuid import uuid4
|
|
21
20
|
|
|
22
21
|
from toil.common import getNodeID
|
|
23
22
|
from toil.lib.exceptions import panic, raise_
|
|
24
|
-
from toil.lib.io import AtomicFileCreate,
|
|
23
|
+
from toil.lib.io import (AtomicFileCreate,
|
|
24
|
+
atomic_install,
|
|
25
|
+
atomic_tmp_file,
|
|
26
|
+
mkdtemp)
|
|
25
27
|
from toil.lib.misc import CalledProcessErrorStderr, call_command
|
|
26
28
|
from toil.test import ToilTest, slow
|
|
27
29
|
|
|
@@ -63,7 +65,7 @@ class MiscTests(ToilTest):
|
|
|
63
65
|
files = {}
|
|
64
66
|
# Create a random directory structure
|
|
65
67
|
for i in range(0,10):
|
|
66
|
-
directories.append(
|
|
68
|
+
directories.append(mkdtemp(dir=random.choice(directories), prefix='test'))
|
|
67
69
|
# Create 50 random file entries in different locations in the directories. 75% of the time
|
|
68
70
|
# these are fresh files of size [1, 10] MB and 25% of the time they are hard links to old
|
|
69
71
|
# files.
|
|
@@ -48,7 +48,7 @@ class hidden:
|
|
|
48
48
|
cores=1, memory='1M', disk='1M')
|
|
49
49
|
values = Job.Runner.startToil(root, self.getOptions(tempDir))
|
|
50
50
|
maxValue = max(values)
|
|
51
|
-
self.
|
|
51
|
+
self.assertLessEqual(maxValue, self.cpuCount // coresPerJob)
|
|
52
52
|
|
|
53
53
|
@slow
|
|
54
54
|
@retry_flaky_test(prepare=[batchSystemTest.hidden.AbstractBatchSystemJobTest.tearDown,
|
|
@@ -74,7 +74,7 @@ class hidden:
|
|
|
74
74
|
disk='1M'))
|
|
75
75
|
Job.Runner.startToil(root, self.getOptions(tempDir))
|
|
76
76
|
_, maxValue = batchSystemTest.getCounters(counterPath)
|
|
77
|
-
self.
|
|
77
|
+
self.assertLessEqual(maxValue, self.cpuCount // coresPerJob)
|
|
78
78
|
|
|
79
79
|
def getOptions(self, tempDir, caching=True):
|
|
80
80
|
options = super().getOptions(tempDir)
|
|
@@ -194,7 +194,7 @@ def logDiskUsage(job, funcName, sleep=0):
|
|
|
194
194
|
:return: job function's disk usage
|
|
195
195
|
"""
|
|
196
196
|
diskUsage = job.disk
|
|
197
|
-
job.fileStore.
|
|
197
|
+
job.fileStore.log_to_leader(f'{funcName}: {diskUsage}')
|
|
198
198
|
time.sleep(sleep)
|
|
199
199
|
return diskUsage
|
|
200
200
|
|
|
@@ -57,7 +57,7 @@ class MessageDetector(logging.StreamHandler):
|
|
|
57
57
|
|
|
58
58
|
class LogTest(Job):
|
|
59
59
|
def __init__(self):
|
|
60
|
-
Job.__init__(self, memory=100000, cores=
|
|
60
|
+
Job.__init__(self, memory=100000, cores=1, disk='3G')
|
|
61
61
|
|
|
62
62
|
def run(self, fileStore):
|
|
63
63
|
RealtimeLogger.info('This should be logged at info level')
|
toil/test/src/resourceTest.py
CHANGED
|
@@ -209,7 +209,7 @@ class ResourceTest(ToilTest):
|
|
|
209
209
|
"""
|
|
210
210
|
|
|
211
211
|
def script():
|
|
212
|
-
import
|
|
212
|
+
from configargparse import ArgumentParser
|
|
213
213
|
|
|
214
214
|
from toil.common import Toil
|
|
215
215
|
from toil.job import Job
|
|
@@ -218,7 +218,7 @@ class ResourceTest(ToilTest):
|
|
|
218
218
|
pass
|
|
219
219
|
|
|
220
220
|
if __name__ == '__main__':
|
|
221
|
-
parser =
|
|
221
|
+
parser = ArgumentParser()
|
|
222
222
|
Job.Runner.addToilOptions(parser)
|
|
223
223
|
options = parser.parse_args()
|
|
224
224
|
job = Job.wrapFn(fn, memory='10M', cores=0.1, disk='10M')
|
toil/test/src/restartDAGTest.py
CHANGED
|
@@ -14,17 +14,17 @@
|
|
|
14
14
|
|
|
15
15
|
import os
|
|
16
16
|
|
|
17
|
+
from toil.exceptions import FailedJobsException
|
|
17
18
|
from toil.job import Job
|
|
18
19
|
from toil.jobStores.abstractJobStore import NoSuchFileException
|
|
19
|
-
from toil.exceptions import FailedJobsException
|
|
20
20
|
from toil.test import ToilTest, slow
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
@slow
|
|
24
23
|
class ResumabilityTest(ToilTest):
|
|
25
24
|
"""
|
|
26
25
|
https://github.com/BD2KGenomics/toil/issues/808
|
|
27
26
|
"""
|
|
27
|
+
@slow
|
|
28
28
|
def test(self):
|
|
29
29
|
"""
|
|
30
30
|
Tests that a toil workflow that fails once can be resumed without a NoSuchJobException.
|
|
@@ -53,6 +53,34 @@ class ResumabilityTest(ToilTest):
|
|
|
53
53
|
# store ID: n/t/jobwbijqL failed with exit value 1"
|
|
54
54
|
self.assertTrue("failed with exit value" not in logString)
|
|
55
55
|
|
|
56
|
+
def test_chaining(self):
|
|
57
|
+
"""
|
|
58
|
+
Tests that a job which is chained to and fails can resume and succeed.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
options = Job.Runner.getDefaultOptions(self._getTestJobStorePath())
|
|
62
|
+
options.logLevel = "DEBUG"
|
|
63
|
+
options.retryCount = 0
|
|
64
|
+
tempDir = self._createTempDir()
|
|
65
|
+
options.logFile = os.path.join(tempDir, "log.txt")
|
|
66
|
+
|
|
67
|
+
root = Job.wrapJobFn(chaining_parent)
|
|
68
|
+
|
|
69
|
+
with self.assertRaises(FailedJobsException):
|
|
70
|
+
# This one is intended to fail.
|
|
71
|
+
Job.Runner.startToil(root, options)
|
|
72
|
+
|
|
73
|
+
with open(options.logFile, 'r') as f:
|
|
74
|
+
log_content = f.read()
|
|
75
|
+
# Make sure we actually did do chaining
|
|
76
|
+
assert "Chaining from" in log_content
|
|
77
|
+
|
|
78
|
+
# Because of the chaining, the problem we are looking for is the job
|
|
79
|
+
# with the root ID not being able to load the body of a job with a
|
|
80
|
+
# different ID. That doesn't look like a job deleted despite failure.
|
|
81
|
+
options.restart = True
|
|
82
|
+
Job.Runner.startToil(root, options)
|
|
83
|
+
|
|
56
84
|
def parent(job):
|
|
57
85
|
"""
|
|
58
86
|
Set up a bunch of dummy child jobs, and a bad job that needs to be
|
|
@@ -62,6 +90,12 @@ def parent(job):
|
|
|
62
90
|
job.addChildJobFn(goodChild)
|
|
63
91
|
job.addFollowOnJobFn(badChild)
|
|
64
92
|
|
|
93
|
+
def chaining_parent(job):
|
|
94
|
+
"""
|
|
95
|
+
Set up a failing job to chain to.
|
|
96
|
+
"""
|
|
97
|
+
job.addFollowOnJobFn(badChild)
|
|
98
|
+
|
|
65
99
|
def goodChild(job):
|
|
66
100
|
"""
|
|
67
101
|
Does nothing.
|
toil/test/src/systemTest.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import errno
|
|
2
2
|
import multiprocessing
|
|
3
3
|
import os
|
|
4
|
-
import tempfile
|
|
5
4
|
from functools import partial
|
|
6
5
|
|
|
6
|
+
from toil.lib.io import mkdtemp
|
|
7
7
|
from toil.lib.threading import cpu_count
|
|
8
8
|
from toil.test import ToilTest
|
|
9
9
|
|
|
@@ -37,7 +37,7 @@ class SystemTest(ToilTest):
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
def _testAtomicityOfNonEmptyDirectoryRenamesTask(parent, child, _):
|
|
40
|
-
tmpChildDir =
|
|
40
|
+
tmpChildDir = mkdtemp(dir=parent, prefix='child', suffix='.tmp')
|
|
41
41
|
grandChild = os.path.join(tmpChildDir, 'grandChild')
|
|
42
42
|
open(grandChild, 'w').close()
|
|
43
43
|
grandChildId = os.stat(grandChild).st_ino
|
|
@@ -61,10 +61,10 @@ class ToilContextManagerTest(ToilTest):
|
|
|
61
61
|
|
|
62
62
|
class HelloWorld(Job):
|
|
63
63
|
def __init__(self):
|
|
64
|
-
Job.__init__(self, memory=100000,
|
|
64
|
+
Job.__init__(self, memory=100000, disk='1M')
|
|
65
65
|
|
|
66
66
|
def run(self, fileStore):
|
|
67
|
-
fileID = self.addChildJobFn(childFn,
|
|
67
|
+
fileID = self.addChildJobFn(childFn, memory='1M', disk='1M').rv()
|
|
68
68
|
return self.addFollowOn(FollowOn(fileID)).rv()
|
|
69
69
|
|
|
70
70
|
|
|
@@ -59,7 +59,7 @@ class UserDefinedJobArgTypeTest(ToilTest):
|
|
|
59
59
|
|
|
60
60
|
class JobClass(Job):
|
|
61
61
|
def __init__(self, level, foo):
|
|
62
|
-
Job.__init__(self, memory=100000, cores=
|
|
62
|
+
Job.__init__(self, memory=100000, cores=1, disk="300M")
|
|
63
63
|
self.level = level
|
|
64
64
|
self.foo = foo
|
|
65
65
|
|
toil/test/utils/toilDebugTest.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"""A set of test cases for toilwdl.py"""
|
|
2
1
|
# Copyright (C) 2015-2021 Regents of the University of California
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -15,32 +14,33 @@
|
|
|
15
14
|
import logging
|
|
16
15
|
import os
|
|
17
16
|
import subprocess
|
|
18
|
-
|
|
17
|
+
import tempfile
|
|
18
|
+
|
|
19
|
+
import pytest
|
|
20
|
+
|
|
21
|
+
from toil.test import ToilTest
|
|
19
22
|
|
|
20
23
|
from toil.lib.resources import glob
|
|
21
24
|
from toil.test import slow
|
|
22
25
|
from toil.version import python
|
|
23
26
|
|
|
24
|
-
import pytest
|
|
25
|
-
|
|
26
27
|
logger = logging.getLogger(__name__)
|
|
27
28
|
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
jobStorePath = str(tmp_path / "toilWorkflowRun")
|
|
30
|
+
def workflow_debug_jobstore() -> str:
|
|
31
|
+
job_store_path = os.path.join(tempfile.mkdtemp(), "toilWorkflowRun")
|
|
32
32
|
subprocess.check_call(
|
|
33
33
|
[
|
|
34
34
|
python,
|
|
35
35
|
os.path.abspath("src/toil/test/utils/ABCWorkflowDebug/debugWorkflow.py"),
|
|
36
|
-
|
|
36
|
+
job_store_path,
|
|
37
37
|
]
|
|
38
38
|
)
|
|
39
|
-
return
|
|
39
|
+
return job_store_path
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
@slow
|
|
43
|
-
def testJobStoreContents(
|
|
43
|
+
def testJobStoreContents():
|
|
44
44
|
"""
|
|
45
45
|
Test toilDebugFile.printContentsOfJobStore().
|
|
46
46
|
|
|
@@ -48,14 +48,13 @@ def testJobStoreContents(workflow_debug_jobstore: str):
|
|
|
48
48
|
jobStore. 'A.txt', 'C.txt', 'ABC.txt' are then created. This checks to
|
|
49
49
|
make sure these contents are found in the jobStore and printed.
|
|
50
50
|
"""
|
|
51
|
-
jobStoreDir = workflow_debug_jobstore
|
|
52
51
|
contents = ["A.txt", "B.txt", "C.txt", "ABC.txt", "mkFile.py"]
|
|
53
52
|
|
|
54
53
|
subprocess.check_call(
|
|
55
54
|
[
|
|
56
55
|
python,
|
|
57
56
|
os.path.abspath("src/toil/utils/toilDebugFile.py"),
|
|
58
|
-
|
|
57
|
+
workflow_debug_jobstore(),
|
|
59
58
|
"--logDebug",
|
|
60
59
|
"--listFilesInJobStore=True",
|
|
61
60
|
]
|
|
@@ -78,7 +77,7 @@ def testJobStoreContents(workflow_debug_jobstore: str):
|
|
|
78
77
|
os.remove(jobstoreFileContents)
|
|
79
78
|
|
|
80
79
|
|
|
81
|
-
def fetchFiles(symLink, jobStoreDir: str, outputDir):
|
|
80
|
+
def fetchFiles(symLink: bool, jobStoreDir: str, outputDir: str):
|
|
82
81
|
"""
|
|
83
82
|
Fn for testFetchJobStoreFiles() and testFetchJobStoreFilesWSymlinks().
|
|
84
83
|
|
|
@@ -99,8 +98,8 @@ def fetchFiles(symLink, jobStoreDir: str, outputDir):
|
|
|
99
98
|
"*C.txt",
|
|
100
99
|
"*ABC.txt",
|
|
101
100
|
"*mkFile.py",
|
|
102
|
-
"--localFilePath="
|
|
103
|
-
"--useSymlinks="
|
|
101
|
+
f"--localFilePath={outputDir}",
|
|
102
|
+
f"--useSymlinks={symLink}",
|
|
104
103
|
]
|
|
105
104
|
print(cmd)
|
|
106
105
|
subprocess.check_call(cmd)
|
|
@@ -114,22 +113,89 @@ def fetchFiles(symLink, jobStoreDir: str, outputDir):
|
|
|
114
113
|
|
|
115
114
|
|
|
116
115
|
# expected run time = 4s
|
|
117
|
-
def testFetchJobStoreFiles(
|
|
118
|
-
"""Test toilDebugFile.fetchJobStoreFiles()
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
116
|
+
def testFetchJobStoreFiles() -> None:
|
|
117
|
+
"""Test toilDebugFile.fetchJobStoreFiles() symlinks."""
|
|
118
|
+
job_store_dir = workflow_debug_jobstore()
|
|
119
|
+
output_dir = os.path.join(os.path.dirname(job_store_dir), "testoutput")
|
|
120
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
121
|
+
for symlink in (True, False):
|
|
122
|
+
fetchFiles(symLink=symlink, jobStoreDir=job_store_dir, outputDir=output_dir)
|
|
123
|
+
|
|
124
|
+
class DebugJobTest(ToilTest):
|
|
125
|
+
"""
|
|
126
|
+
Test the toil debug-job command.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
def _get_job_store_and_job_id(self):
|
|
130
|
+
"""
|
|
131
|
+
Get a job store and the ID of a failing job within it.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
# First make a job store.
|
|
135
|
+
job_store = os.path.join(self._createTempDir(), "tree")
|
|
136
|
+
|
|
137
|
+
logger.info("Running workflow that always fails")
|
|
138
|
+
try:
|
|
139
|
+
# Run an always-failign workflow
|
|
140
|
+
subprocess.check_call([
|
|
141
|
+
python,
|
|
142
|
+
os.path.abspath("src/toil/test/docs/scripts/example_alwaysfail.py"),
|
|
143
|
+
"--retryCount=0",
|
|
144
|
+
"--logCritical",
|
|
145
|
+
"--disableProgress",
|
|
146
|
+
job_store
|
|
147
|
+
], stderr=subprocess.DEVNULL)
|
|
148
|
+
raise RuntimeError("Failing workflow succeeded!")
|
|
149
|
+
except subprocess.CalledProcessError:
|
|
150
|
+
# Should fail to run
|
|
151
|
+
logger.info("Task failed successfully")
|
|
152
|
+
pass
|
|
153
|
+
|
|
154
|
+
# Get the job ID.
|
|
155
|
+
# TODO: This assumes a lot about the FileJobStore. Use the MessageBus instead?
|
|
156
|
+
job_id = "kind-explode/" + os.listdir(os.path.join(job_store, "jobs/kind-explode"))[0]
|
|
157
|
+
|
|
158
|
+
return job_store, job_id
|
|
159
|
+
|
|
160
|
+
def test_run_job(self):
|
|
161
|
+
"""
|
|
162
|
+
Make sure that we can use toil debug-job to try and run a job in-process.
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
job_store, job_id = self._get_job_store_and_job_id()
|
|
166
|
+
|
|
167
|
+
logger.info("Trying to rerun job %s", job_id)
|
|
168
|
+
|
|
169
|
+
# Rerun the job, which should fail again
|
|
170
|
+
output = subprocess.check_output([
|
|
171
|
+
"toil",
|
|
172
|
+
"debug-job",
|
|
173
|
+
"--logDebug",
|
|
174
|
+
job_store,
|
|
175
|
+
job_id
|
|
176
|
+
], stderr=subprocess.STDOUT)
|
|
177
|
+
# Even if the job fails, the attempt to run it will succeed.
|
|
178
|
+
log = output.decode('utf-8')
|
|
179
|
+
assert "Boom!" in log, f"Did not find the expected exception message in: {log}"
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def test_print_job_info(self):
|
|
183
|
+
"""
|
|
184
|
+
Make sure that we can use --printJobInfo to get information on a job from a job store.
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
job_store, job_id = self._get_job_store_and_job_id()
|
|
188
|
+
|
|
189
|
+
logger.info("Trying to print job info for job %s", job_id)
|
|
190
|
+
|
|
191
|
+
# Print the job info and make sure that doesn't crash.
|
|
192
|
+
subprocess.check_call([
|
|
193
|
+
"toil",
|
|
194
|
+
"debug-job",
|
|
195
|
+
"--logDebug",
|
|
196
|
+
job_store,
|
|
197
|
+
"--printJobInfo",
|
|
198
|
+
job_id
|
|
199
|
+
])
|
|
124
200
|
|
|
125
201
|
|
|
126
|
-
# expected run time = 4s
|
|
127
|
-
def testFetchJobStoreFilesWSymlinks(
|
|
128
|
-
tmp_path: Path, workflow_debug_jobstore: str
|
|
129
|
-
) -> None:
|
|
130
|
-
"""Test toilDebugFile.fetchJobStoreFiles() using symlinks."""
|
|
131
|
-
outputDir = tmp_path / "testoutput"
|
|
132
|
-
outputDir.mkdir()
|
|
133
|
-
fetchFiles(
|
|
134
|
-
symLink=True, jobStoreDir=workflow_debug_jobstore, outputDir=str(outputDir)
|
|
135
|
-
)
|
toil/test/utils/toilKillTest.py
CHANGED
|
@@ -21,7 +21,8 @@ import time
|
|
|
21
21
|
import unittest
|
|
22
22
|
|
|
23
23
|
from toil.common import Toil
|
|
24
|
-
from toil.jobStores.abstractJobStore import NoSuchFileException,
|
|
24
|
+
from toil.jobStores.abstractJobStore import (NoSuchFileException,
|
|
25
|
+
NoSuchJobStoreException)
|
|
25
26
|
from toil.jobStores.utils import generate_locator
|
|
26
27
|
from toil.test import ToilTest, needs_aws_s3, needs_cwl
|
|
27
28
|
|
|
@@ -77,7 +78,6 @@ class ToilKillTest(ToilTest):
|
|
|
77
78
|
logger.info('Waiting for kill flag...')
|
|
78
79
|
except (NoSuchJobStoreException, NoSuchFileException):
|
|
79
80
|
logger.info('Waiting for job store to be openable...')
|
|
80
|
-
pass
|
|
81
81
|
time.sleep(2)
|
|
82
82
|
|
|
83
83
|
# run toil kill
|
toil/test/utils/utilsTest.py
CHANGED
|
@@ -39,7 +39,7 @@ from toil.test import (ToilTest,
|
|
|
39
39
|
needs_rsync3,
|
|
40
40
|
slow)
|
|
41
41
|
from toil.test.sort.sortTest import makeFileToSort
|
|
42
|
-
from toil.utils.toilStats import
|
|
42
|
+
from toil.utils.toilStats import get_stats, process_data
|
|
43
43
|
from toil.utils.toilStatus import ToilStatus
|
|
44
44
|
from toil.version import python
|
|
45
45
|
|
|
@@ -115,6 +115,26 @@ class UtilsTest(ToilTest):
|
|
|
115
115
|
commandTokens.append('--failIfNotComplete')
|
|
116
116
|
return commandTokens
|
|
117
117
|
|
|
118
|
+
def test_config_functionality(self):
|
|
119
|
+
"""Ensure that creating and reading back the config file works"""
|
|
120
|
+
config_file = os.path.abspath("config.yaml")
|
|
121
|
+
config_command = [self.toilMain, 'config', config_file]
|
|
122
|
+
# make sure the command `toil config file_path` works
|
|
123
|
+
try:
|
|
124
|
+
subprocess.check_call(config_command)
|
|
125
|
+
except subprocess.CalledProcessError:
|
|
126
|
+
self.fail("The toil config utility failed!")
|
|
127
|
+
|
|
128
|
+
parser = Job.Runner.getDefaultArgumentParser()
|
|
129
|
+
# make sure that toil can read from the generated config file
|
|
130
|
+
try:
|
|
131
|
+
parser.parse_args(["random_jobstore", "--config", config_file])
|
|
132
|
+
except SystemExit:
|
|
133
|
+
self.fail("Failed to parse the default generated config file!")
|
|
134
|
+
finally:
|
|
135
|
+
os.remove(config_file)
|
|
136
|
+
|
|
137
|
+
|
|
118
138
|
@needs_rsync3
|
|
119
139
|
@pytest.mark.timeout(1200)
|
|
120
140
|
@needs_aws_ec2
|
|
@@ -278,8 +298,8 @@ class UtilsTest(ToilTest):
|
|
|
278
298
|
config = Config()
|
|
279
299
|
config.setOptions(options)
|
|
280
300
|
jobStore = Toil.resumeJobStore(config.jobStore)
|
|
281
|
-
stats =
|
|
282
|
-
collatedStats =
|
|
301
|
+
stats = get_stats(jobStore)
|
|
302
|
+
collatedStats = process_data(jobStore.config, stats)
|
|
283
303
|
self.assertTrue(len(collatedStats.job_types) == 2, "Some jobs are not represented in the stats.")
|
|
284
304
|
|
|
285
305
|
def check_status(self, status, status_fn, seconds=20):
|