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.
Files changed (164) hide show
  1. toil/__init__.py +18 -13
  2. toil/batchSystems/abstractBatchSystem.py +39 -13
  3. toil/batchSystems/abstractGridEngineBatchSystem.py +24 -24
  4. toil/batchSystems/awsBatch.py +14 -14
  5. toil/batchSystems/cleanup_support.py +7 -3
  6. toil/batchSystems/contained_executor.py +3 -3
  7. toil/batchSystems/htcondor.py +0 -1
  8. toil/batchSystems/kubernetes.py +34 -31
  9. toil/batchSystems/local_support.py +3 -1
  10. toil/batchSystems/lsf.py +7 -7
  11. toil/batchSystems/mesos/batchSystem.py +7 -7
  12. toil/batchSystems/options.py +32 -83
  13. toil/batchSystems/registry.py +104 -23
  14. toil/batchSystems/singleMachine.py +16 -13
  15. toil/batchSystems/slurm.py +87 -16
  16. toil/batchSystems/torque.py +0 -1
  17. toil/bus.py +44 -8
  18. toil/common.py +544 -753
  19. toil/cwl/__init__.py +28 -32
  20. toil/cwl/cwltoil.py +595 -574
  21. toil/cwl/utils.py +55 -10
  22. toil/exceptions.py +1 -1
  23. toil/fileStores/__init__.py +2 -2
  24. toil/fileStores/abstractFileStore.py +88 -14
  25. toil/fileStores/cachingFileStore.py +610 -549
  26. toil/fileStores/nonCachingFileStore.py +46 -22
  27. toil/job.py +182 -101
  28. toil/jobStores/abstractJobStore.py +161 -95
  29. toil/jobStores/aws/jobStore.py +23 -9
  30. toil/jobStores/aws/utils.py +6 -6
  31. toil/jobStores/fileJobStore.py +116 -18
  32. toil/jobStores/googleJobStore.py +16 -7
  33. toil/jobStores/utils.py +5 -6
  34. toil/leader.py +87 -56
  35. toil/lib/accelerators.py +10 -5
  36. toil/lib/aws/__init__.py +3 -14
  37. toil/lib/aws/ami.py +22 -9
  38. toil/lib/aws/iam.py +21 -13
  39. toil/lib/aws/session.py +2 -16
  40. toil/lib/aws/utils.py +4 -5
  41. toil/lib/compatibility.py +1 -1
  42. toil/lib/conversions.py +26 -3
  43. toil/lib/docker.py +22 -23
  44. toil/lib/ec2.py +10 -6
  45. toil/lib/ec2nodes.py +106 -100
  46. toil/lib/encryption/_nacl.py +2 -1
  47. toil/lib/generatedEC2Lists.py +325 -18
  48. toil/lib/io.py +49 -2
  49. toil/lib/misc.py +1 -1
  50. toil/lib/resources.py +9 -2
  51. toil/lib/threading.py +101 -38
  52. toil/options/common.py +736 -0
  53. toil/options/cwl.py +336 -0
  54. toil/options/wdl.py +37 -0
  55. toil/provisioners/abstractProvisioner.py +9 -4
  56. toil/provisioners/aws/__init__.py +3 -6
  57. toil/provisioners/aws/awsProvisioner.py +6 -0
  58. toil/provisioners/clusterScaler.py +3 -2
  59. toil/provisioners/gceProvisioner.py +2 -2
  60. toil/realtimeLogger.py +2 -1
  61. toil/resource.py +24 -18
  62. toil/server/app.py +2 -3
  63. toil/server/cli/wes_cwl_runner.py +4 -4
  64. toil/server/utils.py +1 -1
  65. toil/server/wes/abstract_backend.py +3 -2
  66. toil/server/wes/amazon_wes_utils.py +5 -4
  67. toil/server/wes/tasks.py +2 -3
  68. toil/server/wes/toil_backend.py +2 -10
  69. toil/server/wsgi_app.py +2 -0
  70. toil/serviceManager.py +12 -10
  71. toil/statsAndLogging.py +41 -9
  72. toil/test/__init__.py +29 -54
  73. toil/test/batchSystems/batchSystemTest.py +11 -111
  74. toil/test/batchSystems/test_slurm.py +24 -8
  75. toil/test/cactus/__init__.py +0 -0
  76. toil/test/cactus/test_cactus_integration.py +58 -0
  77. toil/test/cwl/cwlTest.py +438 -223
  78. toil/test/cwl/glob_dir.cwl +15 -0
  79. toil/test/cwl/preemptible.cwl +21 -0
  80. toil/test/cwl/preemptible_expression.cwl +28 -0
  81. toil/test/cwl/revsort.cwl +1 -1
  82. toil/test/cwl/revsort2.cwl +1 -1
  83. toil/test/docs/scriptsTest.py +2 -3
  84. toil/test/jobStores/jobStoreTest.py +34 -21
  85. toil/test/lib/aws/test_iam.py +4 -14
  86. toil/test/lib/aws/test_utils.py +0 -3
  87. toil/test/lib/dockerTest.py +4 -4
  88. toil/test/lib/test_ec2.py +12 -17
  89. toil/test/mesos/helloWorld.py +4 -5
  90. toil/test/mesos/stress.py +1 -1
  91. toil/test/{wdl/conftest.py → options/__init__.py} +0 -10
  92. toil/test/options/options.py +37 -0
  93. toil/test/provisioners/aws/awsProvisionerTest.py +9 -5
  94. toil/test/provisioners/clusterScalerTest.py +6 -4
  95. toil/test/provisioners/clusterTest.py +23 -11
  96. toil/test/provisioners/gceProvisionerTest.py +0 -6
  97. toil/test/provisioners/restartScript.py +3 -2
  98. toil/test/server/serverTest.py +1 -1
  99. toil/test/sort/restart_sort.py +2 -1
  100. toil/test/sort/sort.py +2 -1
  101. toil/test/sort/sortTest.py +2 -13
  102. toil/test/src/autoDeploymentTest.py +45 -45
  103. toil/test/src/busTest.py +5 -5
  104. toil/test/src/checkpointTest.py +2 -2
  105. toil/test/src/deferredFunctionTest.py +1 -1
  106. toil/test/src/fileStoreTest.py +32 -16
  107. toil/test/src/helloWorldTest.py +1 -1
  108. toil/test/src/importExportFileTest.py +1 -1
  109. toil/test/src/jobDescriptionTest.py +2 -1
  110. toil/test/src/jobServiceTest.py +1 -1
  111. toil/test/src/jobTest.py +18 -18
  112. toil/test/src/miscTests.py +5 -3
  113. toil/test/src/promisedRequirementTest.py +3 -3
  114. toil/test/src/realtimeLoggerTest.py +1 -1
  115. toil/test/src/resourceTest.py +2 -2
  116. toil/test/src/restartDAGTest.py +1 -1
  117. toil/test/src/resumabilityTest.py +36 -2
  118. toil/test/src/retainTempDirTest.py +1 -1
  119. toil/test/src/systemTest.py +2 -2
  120. toil/test/src/toilContextManagerTest.py +2 -2
  121. toil/test/src/userDefinedJobArgTypeTest.py +1 -1
  122. toil/test/utils/toilDebugTest.py +98 -32
  123. toil/test/utils/toilKillTest.py +2 -2
  124. toil/test/utils/utilsTest.py +23 -3
  125. toil/test/wdl/wdltoil_test.py +223 -45
  126. toil/toilState.py +7 -6
  127. toil/utils/toilClean.py +1 -1
  128. toil/utils/toilConfig.py +36 -0
  129. toil/utils/toilDebugFile.py +60 -33
  130. toil/utils/toilDebugJob.py +39 -12
  131. toil/utils/toilDestroyCluster.py +1 -1
  132. toil/utils/toilKill.py +1 -1
  133. toil/utils/toilLaunchCluster.py +13 -2
  134. toil/utils/toilMain.py +3 -2
  135. toil/utils/toilRsyncCluster.py +1 -1
  136. toil/utils/toilSshCluster.py +1 -1
  137. toil/utils/toilStats.py +445 -305
  138. toil/utils/toilStatus.py +2 -5
  139. toil/version.py +10 -10
  140. toil/wdl/utils.py +2 -122
  141. toil/wdl/wdltoil.py +1257 -492
  142. toil/worker.py +55 -46
  143. toil-6.1.0.dist-info/METADATA +124 -0
  144. toil-6.1.0.dist-info/RECORD +241 -0
  145. {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/WHEEL +1 -1
  146. {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/entry_points.txt +0 -1
  147. toil/batchSystems/parasol.py +0 -379
  148. toil/batchSystems/tes.py +0 -459
  149. toil/test/batchSystems/parasolTestSupport.py +0 -117
  150. toil/test/wdl/builtinTest.py +0 -506
  151. toil/test/wdl/toilwdlTest.py +0 -522
  152. toil/wdl/toilwdl.py +0 -141
  153. toil/wdl/versions/dev.py +0 -107
  154. toil/wdl/versions/draft2.py +0 -980
  155. toil/wdl/versions/v1.py +0 -794
  156. toil/wdl/wdl_analysis.py +0 -116
  157. toil/wdl/wdl_functions.py +0 -997
  158. toil/wdl/wdl_synthesis.py +0 -1011
  159. toil/wdl/wdl_types.py +0 -243
  160. toil-5.12.0.dist-info/METADATA +0 -118
  161. toil-5.12.0.dist-info/RECORD +0 -244
  162. /toil/{wdl/versions → options}/__init__.py +0 -0
  163. {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/LICENSE +0 -0
  164. {toil-5.12.0.dist-info → toil-6.1.0.dist-info}/top_level.txt +0 -0
@@ -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, atomic_install, atomic_tmp_file
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(tempfile.mkdtemp(dir=random.choice(directories), prefix='test'))
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.assertEqual(maxValue, self.cpuCount // coresPerJob)
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.assertEqual(maxValue, self.cpuCount // coresPerJob)
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.logToMaster(f'{funcName}: {diskUsage}')
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=2, disk='3G')
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')
@@ -209,7 +209,7 @@ class ResourceTest(ToilTest):
209
209
  """
210
210
 
211
211
  def script():
212
- import argparse
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 = argparse.ArgumentParser()
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')
@@ -19,8 +19,8 @@ import shutil
19
19
  import signal
20
20
 
21
21
  from toil.common import Toil
22
- from toil.job import Job
23
22
  from toil.exceptions import FailedJobsException
23
+ from toil.job import Job
24
24
  from toil.test import ToilTest, slow
25
25
 
26
26
  logger = logging.getLogger(__name__)
@@ -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.
@@ -14,8 +14,8 @@
14
14
  import os
15
15
  import shutil
16
16
 
17
- from toil.job import Job
18
17
  from toil.exceptions import FailedJobsException
18
+ from toil.job import Job
19
19
  from toil.test import ToilTest
20
20
 
21
21
 
@@ -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 = tempfile.mkdtemp(dir=parent, prefix='child', suffix='.tmp')
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, cores=2, disk='1M')
64
+ Job.__init__(self, memory=100000, disk='1M')
65
65
 
66
66
  def run(self, fileStore):
67
- fileID = self.addChildJobFn(childFn, cores=1, memory='1M', disk='1M').rv()
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=2, disk="300M")
62
+ Job.__init__(self, memory=100000, cores=1, disk="300M")
63
63
  self.level = level
64
64
  self.foo = foo
65
65
 
@@ -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
- from pathlib import Path
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
- @pytest.fixture
30
- def workflow_debug_jobstore(tmp_path: Path) -> str:
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
- jobStorePath,
36
+ job_store_path,
37
37
  ]
38
38
  )
39
- return jobStorePath
39
+ return job_store_path
40
40
 
41
41
 
42
42
  @slow
43
- def testJobStoreContents(workflow_debug_jobstore: str):
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
- jobStoreDir,
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=" + outputDir,
103
- "--useSymlinks=" + str(symLink),
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(tmp_path: Path, workflow_debug_jobstore: str) -> None:
118
- """Test toilDebugFile.fetchJobStoreFiles() without using symlinks."""
119
- outputDir = tmp_path / "testoutput"
120
- outputDir.mkdir()
121
- fetchFiles(
122
- symLink=False, jobStoreDir=workflow_debug_jobstore, outputDir=str(outputDir)
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
- )
@@ -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, NoSuchJobStoreException
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
@@ -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 getStats, processData
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 = getStats(jobStore)
282
- collatedStats = processData(jobStore.config, stats)
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):