toil 6.1.0a1__py3-none-any.whl → 8.0.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 (193) hide show
  1. toil/__init__.py +122 -315
  2. toil/batchSystems/__init__.py +1 -0
  3. toil/batchSystems/abstractBatchSystem.py +173 -89
  4. toil/batchSystems/abstractGridEngineBatchSystem.py +272 -148
  5. toil/batchSystems/awsBatch.py +244 -135
  6. toil/batchSystems/cleanup_support.py +26 -16
  7. toil/batchSystems/contained_executor.py +31 -28
  8. toil/batchSystems/gridengine.py +86 -50
  9. toil/batchSystems/htcondor.py +166 -89
  10. toil/batchSystems/kubernetes.py +632 -382
  11. toil/batchSystems/local_support.py +20 -15
  12. toil/batchSystems/lsf.py +134 -81
  13. toil/batchSystems/lsfHelper.py +13 -11
  14. toil/batchSystems/mesos/__init__.py +41 -29
  15. toil/batchSystems/mesos/batchSystem.py +290 -151
  16. toil/batchSystems/mesos/executor.py +79 -50
  17. toil/batchSystems/mesos/test/__init__.py +31 -23
  18. toil/batchSystems/options.py +46 -28
  19. toil/batchSystems/registry.py +53 -19
  20. toil/batchSystems/singleMachine.py +296 -125
  21. toil/batchSystems/slurm.py +603 -138
  22. toil/batchSystems/torque.py +47 -33
  23. toil/bus.py +186 -76
  24. toil/common.py +664 -368
  25. toil/cwl/__init__.py +1 -1
  26. toil/cwl/cwltoil.py +1136 -483
  27. toil/cwl/utils.py +17 -22
  28. toil/deferred.py +63 -42
  29. toil/exceptions.py +5 -3
  30. toil/fileStores/__init__.py +5 -5
  31. toil/fileStores/abstractFileStore.py +140 -60
  32. toil/fileStores/cachingFileStore.py +717 -269
  33. toil/fileStores/nonCachingFileStore.py +116 -87
  34. toil/job.py +1225 -368
  35. toil/jobStores/abstractJobStore.py +416 -266
  36. toil/jobStores/aws/jobStore.py +863 -477
  37. toil/jobStores/aws/utils.py +201 -120
  38. toil/jobStores/conftest.py +3 -2
  39. toil/jobStores/fileJobStore.py +292 -154
  40. toil/jobStores/googleJobStore.py +140 -74
  41. toil/jobStores/utils.py +36 -15
  42. toil/leader.py +668 -272
  43. toil/lib/accelerators.py +115 -18
  44. toil/lib/aws/__init__.py +74 -31
  45. toil/lib/aws/ami.py +122 -87
  46. toil/lib/aws/iam.py +284 -108
  47. toil/lib/aws/s3.py +31 -0
  48. toil/lib/aws/session.py +214 -39
  49. toil/lib/aws/utils.py +287 -231
  50. toil/lib/bioio.py +13 -5
  51. toil/lib/compatibility.py +11 -6
  52. toil/lib/conversions.py +104 -47
  53. toil/lib/docker.py +131 -103
  54. toil/lib/ec2.py +361 -199
  55. toil/lib/ec2nodes.py +174 -106
  56. toil/lib/encryption/_dummy.py +5 -3
  57. toil/lib/encryption/_nacl.py +10 -6
  58. toil/lib/encryption/conftest.py +1 -0
  59. toil/lib/exceptions.py +26 -7
  60. toil/lib/expando.py +5 -3
  61. toil/lib/ftp_utils.py +217 -0
  62. toil/lib/generatedEC2Lists.py +127 -19
  63. toil/lib/humanize.py +6 -2
  64. toil/lib/integration.py +341 -0
  65. toil/lib/io.py +141 -15
  66. toil/lib/iterables.py +4 -2
  67. toil/lib/memoize.py +12 -8
  68. toil/lib/misc.py +66 -21
  69. toil/lib/objects.py +2 -2
  70. toil/lib/resources.py +68 -15
  71. toil/lib/retry.py +126 -81
  72. toil/lib/threading.py +299 -82
  73. toil/lib/throttle.py +16 -15
  74. toil/options/common.py +843 -409
  75. toil/options/cwl.py +175 -90
  76. toil/options/runner.py +50 -0
  77. toil/options/wdl.py +73 -17
  78. toil/provisioners/__init__.py +117 -46
  79. toil/provisioners/abstractProvisioner.py +332 -157
  80. toil/provisioners/aws/__init__.py +70 -33
  81. toil/provisioners/aws/awsProvisioner.py +1145 -715
  82. toil/provisioners/clusterScaler.py +541 -279
  83. toil/provisioners/gceProvisioner.py +282 -179
  84. toil/provisioners/node.py +155 -79
  85. toil/realtimeLogger.py +34 -22
  86. toil/resource.py +137 -75
  87. toil/server/app.py +128 -62
  88. toil/server/celery_app.py +3 -1
  89. toil/server/cli/wes_cwl_runner.py +82 -53
  90. toil/server/utils.py +54 -28
  91. toil/server/wes/abstract_backend.py +64 -26
  92. toil/server/wes/amazon_wes_utils.py +21 -15
  93. toil/server/wes/tasks.py +121 -63
  94. toil/server/wes/toil_backend.py +142 -107
  95. toil/server/wsgi_app.py +4 -3
  96. toil/serviceManager.py +58 -22
  97. toil/statsAndLogging.py +224 -70
  98. toil/test/__init__.py +282 -183
  99. toil/test/batchSystems/batchSystemTest.py +460 -210
  100. toil/test/batchSystems/batch_system_plugin_test.py +90 -0
  101. toil/test/batchSystems/test_gridengine.py +173 -0
  102. toil/test/batchSystems/test_lsf_helper.py +67 -58
  103. toil/test/batchSystems/test_slurm.py +110 -49
  104. toil/test/cactus/__init__.py +0 -0
  105. toil/test/cactus/test_cactus_integration.py +56 -0
  106. toil/test/cwl/cwlTest.py +496 -287
  107. toil/test/cwl/measure_default_memory.cwl +12 -0
  108. toil/test/cwl/not_run_required_input.cwl +29 -0
  109. toil/test/cwl/scatter_duplicate_outputs.cwl +40 -0
  110. toil/test/cwl/seqtk_seq.cwl +1 -1
  111. toil/test/docs/scriptsTest.py +69 -46
  112. toil/test/jobStores/jobStoreTest.py +427 -264
  113. toil/test/lib/aws/test_iam.py +118 -50
  114. toil/test/lib/aws/test_s3.py +16 -9
  115. toil/test/lib/aws/test_utils.py +5 -6
  116. toil/test/lib/dockerTest.py +118 -141
  117. toil/test/lib/test_conversions.py +113 -115
  118. toil/test/lib/test_ec2.py +58 -50
  119. toil/test/lib/test_integration.py +104 -0
  120. toil/test/lib/test_misc.py +12 -5
  121. toil/test/mesos/MesosDataStructuresTest.py +23 -10
  122. toil/test/mesos/helloWorld.py +7 -6
  123. toil/test/mesos/stress.py +25 -20
  124. toil/test/options/__init__.py +13 -0
  125. toil/test/options/options.py +42 -0
  126. toil/test/provisioners/aws/awsProvisionerTest.py +320 -150
  127. toil/test/provisioners/clusterScalerTest.py +440 -250
  128. toil/test/provisioners/clusterTest.py +166 -44
  129. toil/test/provisioners/gceProvisionerTest.py +174 -100
  130. toil/test/provisioners/provisionerTest.py +25 -13
  131. toil/test/provisioners/restartScript.py +5 -4
  132. toil/test/server/serverTest.py +188 -141
  133. toil/test/sort/restart_sort.py +137 -68
  134. toil/test/sort/sort.py +134 -66
  135. toil/test/sort/sortTest.py +91 -49
  136. toil/test/src/autoDeploymentTest.py +141 -101
  137. toil/test/src/busTest.py +20 -18
  138. toil/test/src/checkpointTest.py +8 -2
  139. toil/test/src/deferredFunctionTest.py +49 -35
  140. toil/test/src/dockerCheckTest.py +32 -24
  141. toil/test/src/environmentTest.py +135 -0
  142. toil/test/src/fileStoreTest.py +539 -272
  143. toil/test/src/helloWorldTest.py +7 -4
  144. toil/test/src/importExportFileTest.py +61 -31
  145. toil/test/src/jobDescriptionTest.py +46 -21
  146. toil/test/src/jobEncapsulationTest.py +2 -0
  147. toil/test/src/jobFileStoreTest.py +74 -50
  148. toil/test/src/jobServiceTest.py +187 -73
  149. toil/test/src/jobTest.py +121 -71
  150. toil/test/src/miscTests.py +19 -18
  151. toil/test/src/promisedRequirementTest.py +82 -36
  152. toil/test/src/promisesTest.py +7 -6
  153. toil/test/src/realtimeLoggerTest.py +10 -6
  154. toil/test/src/regularLogTest.py +71 -37
  155. toil/test/src/resourceTest.py +80 -49
  156. toil/test/src/restartDAGTest.py +36 -22
  157. toil/test/src/resumabilityTest.py +9 -2
  158. toil/test/src/retainTempDirTest.py +45 -14
  159. toil/test/src/systemTest.py +12 -8
  160. toil/test/src/threadingTest.py +44 -25
  161. toil/test/src/toilContextManagerTest.py +10 -7
  162. toil/test/src/userDefinedJobArgTypeTest.py +8 -5
  163. toil/test/src/workerTest.py +73 -23
  164. toil/test/utils/toilDebugTest.py +103 -33
  165. toil/test/utils/toilKillTest.py +4 -5
  166. toil/test/utils/utilsTest.py +245 -106
  167. toil/test/wdl/wdltoil_test.py +818 -149
  168. toil/test/wdl/wdltoil_test_kubernetes.py +91 -0
  169. toil/toilState.py +120 -35
  170. toil/utils/toilConfig.py +13 -4
  171. toil/utils/toilDebugFile.py +44 -27
  172. toil/utils/toilDebugJob.py +214 -27
  173. toil/utils/toilDestroyCluster.py +11 -6
  174. toil/utils/toilKill.py +8 -3
  175. toil/utils/toilLaunchCluster.py +256 -140
  176. toil/utils/toilMain.py +37 -16
  177. toil/utils/toilRsyncCluster.py +32 -14
  178. toil/utils/toilSshCluster.py +49 -22
  179. toil/utils/toilStats.py +356 -273
  180. toil/utils/toilStatus.py +292 -139
  181. toil/utils/toilUpdateEC2Instances.py +3 -1
  182. toil/version.py +12 -12
  183. toil/wdl/utils.py +5 -5
  184. toil/wdl/wdltoil.py +3913 -1033
  185. toil/worker.py +367 -184
  186. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/LICENSE +25 -0
  187. toil-8.0.0.dist-info/METADATA +173 -0
  188. toil-8.0.0.dist-info/RECORD +253 -0
  189. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/WHEEL +1 -1
  190. toil-6.1.0a1.dist-info/METADATA +0 -125
  191. toil-6.1.0a1.dist-info/RECORD +0 -237
  192. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/entry_points.txt +0 -0
  193. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/top_level.txt +0 -0
@@ -30,7 +30,7 @@ from toil.version import exactPython
30
30
 
31
31
 
32
32
  @contextmanager
33
- def tempFileContaining(content, suffix=''):
33
+ def tempFileContaining(content, suffix=""):
34
34
  """
35
35
  Write a file with the given contents, and keep it on disk as long as the context is active.
36
36
  :param str content: The contents of the file.
@@ -38,7 +38,7 @@ def tempFileContaining(content, suffix=''):
38
38
  """
39
39
  fd, path = tempfile.mkstemp(suffix=suffix)
40
40
  try:
41
- encoded = content.encode('utf-8')
41
+ encoded = content.encode("utf-8")
42
42
  assert os.write(fd, encoded) == len(encoded)
43
43
  except:
44
44
  os.close(fd)
@@ -52,41 +52,55 @@ def tempFileContaining(content, suffix=''):
52
52
 
53
53
  class ResourceTest(ToilTest):
54
54
  """Test module descriptors and resources derived from them."""
55
+
55
56
  def testStandAlone(self):
56
- self._testExternal(moduleName='userScript', pyFiles=('userScript.py', 'helper.py'))
57
+ self._testExternal(
58
+ moduleName="userScript", pyFiles=("userScript.py", "helper.py")
59
+ )
57
60
 
58
61
  def testPackage(self):
59
- self._testExternal(moduleName='foo.userScript', pyFiles=('foo/__init__.py',
60
- 'foo/userScript.py',
61
- 'foo/bar/__init__.py',
62
- 'foo/bar/helper.py'))
62
+ self._testExternal(
63
+ moduleName="foo.userScript",
64
+ pyFiles=(
65
+ "foo/__init__.py",
66
+ "foo/userScript.py",
67
+ "foo/bar/__init__.py",
68
+ "foo/bar/helper.py",
69
+ ),
70
+ )
63
71
 
64
72
  def testVirtualEnv(self):
65
- self._testExternal(moduleName='foo.userScript',
66
- virtualenv=True,
67
- pyFiles=('foo/__init__.py',
68
- 'foo/userScript.py',
69
- 'foo/bar/__init__.py',
70
- 'foo/bar/helper.py',
71
- 'de/pen/dency.py',
72
- 'de/__init__.py',
73
- 'de/pen/__init__.py'))
73
+ self._testExternal(
74
+ moduleName="foo.userScript",
75
+ virtualenv=True,
76
+ pyFiles=(
77
+ "foo/__init__.py",
78
+ "foo/userScript.py",
79
+ "foo/bar/__init__.py",
80
+ "foo/bar/helper.py",
81
+ "de/pen/dency.py",
82
+ "de/__init__.py",
83
+ "de/pen/__init__.py",
84
+ ),
85
+ )
74
86
 
75
87
  def testStandAloneInPackage(self):
76
- self.assertRaises(ResourceException,
77
- self._testExternal,
78
- moduleName='userScript',
79
- pyFiles=('__init__.py', 'userScript.py', 'helper.py'))
88
+ self.assertRaises(
89
+ ResourceException,
90
+ self._testExternal,
91
+ moduleName="userScript",
92
+ pyFiles=("__init__.py", "userScript.py", "helper.py"),
93
+ )
80
94
 
81
95
  def _testExternal(self, moduleName, pyFiles, virtualenv=False):
82
96
  dirPath = self._createTempDir()
83
97
  if virtualenv:
84
98
  self.assertTrue(inVirtualEnv())
85
99
  # --never-download prevents silent upgrades to pip, wheel and setuptools
86
- subprocess.check_call(['virtualenv', '--never-download', '--python', exactPython, dirPath])
87
- sitePackages = os.path.join(dirPath, 'lib',
88
- exactPython,
89
- 'site-packages')
100
+ subprocess.check_call(
101
+ ["virtualenv", "--never-download", "--python", exactPython, dirPath]
102
+ )
103
+ sitePackages = os.path.join(dirPath, "lib", exactPython, "site-packages")
90
104
  # tuple assignment is necessary to make this line immediately precede the try:
91
105
  oldPrefix, sys.prefix, dirPath = sys.prefix, dirPath, sitePackages
92
106
  else:
@@ -95,21 +109,23 @@ class ResourceTest(ToilTest):
95
109
  for relPath in pyFiles:
96
110
  path = os.path.join(dirPath, relPath)
97
111
  os.makedirs(os.path.dirname(path), exist_ok=True)
98
- with open(path, 'w') as f:
99
- f.write('pass\n')
112
+ with open(path, "w") as f:
113
+ f.write("pass\n")
100
114
  sys.path.append(dirPath)
101
115
  try:
102
116
  userScript = importlib.import_module(moduleName)
103
117
  try:
104
- self._test(userScript.__name__,
105
- expectedContents=pyFiles,
106
- allowExtraContents=True)
118
+ self._test(
119
+ userScript.__name__,
120
+ expectedContents=pyFiles,
121
+ allowExtraContents=True,
122
+ )
107
123
  finally:
108
124
  del userScript
109
125
  while moduleName:
110
126
  del sys.modules[moduleName]
111
127
  self.assertFalse(moduleName in sys.modules)
112
- moduleName = '.'.join(moduleName.split('.')[:-1])
128
+ moduleName = ".".join(moduleName.split(".")[:-1])
113
129
 
114
130
  finally:
115
131
  sys.path.remove(dirPath)
@@ -120,17 +136,22 @@ class ResourceTest(ToilTest):
120
136
  def testBuiltIn(self):
121
137
  # Create a ModuleDescriptor for the module containing ModuleDescriptor, i.e. toil.resource
122
138
  module_name = ModuleDescriptor.__module__
123
- self.assertEqual(module_name, 'toil.resource')
139
+ self.assertEqual(module_name, "toil.resource")
124
140
  self._test(module_name, shouldBelongToToil=True)
125
141
 
126
- def _test(self, module_name,
127
- shouldBelongToToil=False, expectedContents=None, allowExtraContents=True):
142
+ def _test(
143
+ self,
144
+ module_name,
145
+ shouldBelongToToil=False,
146
+ expectedContents=None,
147
+ allowExtraContents=True,
148
+ ):
128
149
  module = ModuleDescriptor.forModule(module_name)
129
150
  # Assert basic attributes and properties
130
151
  self.assertEqual(module.belongsToToil, shouldBelongToToil)
131
152
  self.assertEqual(module.name, module_name)
132
153
  if shouldBelongToToil:
133
- self.assertTrue(module.dirPath.endswith('/src'))
154
+ self.assertTrue(module.dirPath.endswith("/src"))
134
155
 
135
156
  # Before the module is saved as a resource, localize() and globalize() are identity
136
157
  # methods. This should log.warnings.
@@ -139,27 +160,32 @@ class ResourceTest(ToilTest):
139
160
  # Create a mock job store ...
140
161
  jobStore = MagicMock()
141
162
  # ... to generate a fake URL for the resource ...
142
- url = 'file://foo.zip'
163
+ url = "file://foo.zip"
143
164
  jobStore.getSharedPublicUrl.return_value = url
144
165
  # ... and save the resource to it.
145
166
  resource = module.saveAsResourceTo(jobStore)
146
167
  # Ensure that the URL generation method is actually called, ...
147
- jobStore.getSharedPublicUrl.assert_called_once_with(sharedFileName=resource.pathHash)
168
+ jobStore.getSharedPublicUrl.assert_called_once_with(
169
+ sharedFileName=resource.pathHash
170
+ )
148
171
  # ... and that ensure that write_shared_file_stream is called.
149
- jobStore.write_shared_file_stream.assert_called_once_with(shared_file_name=resource.pathHash,
150
- encrypted=False)
172
+ jobStore.write_shared_file_stream.assert_called_once_with(
173
+ shared_file_name=resource.pathHash, encrypted=False
174
+ )
151
175
  # Now it gets a bit complicated: Ensure that the context manager returned by the
152
176
  # jobStore's write_shared_file_stream() method is entered and that the file handle yielded
153
177
  # by the context manager is written to once with the zipped source tree from which
154
178
  # 'toil.resource' was originally imported. Keep the zipped tree around such that we can
155
179
  # mock the download later.
156
- file_handle = jobStore.write_shared_file_stream.return_value.__enter__.return_value
180
+ file_handle = (
181
+ jobStore.write_shared_file_stream.return_value.__enter__.return_value
182
+ )
157
183
  # The first 0 index selects the first call of write(), the second 0 selects positional
158
184
  # instead of keyword arguments, and the third 0 selects the first positional, i.e. the
159
185
  # contents. This is a bit brittle since it assumes that all the data is written in a
160
186
  # single call to write(). If more calls are made we can easily concatenate them.
161
187
  zipFile = file_handle.write.call_args_list[0][0][0]
162
- self.assertTrue(zipFile.startswith(b'PK')) # the magic header for ZIP files
188
+ self.assertTrue(zipFile.startswith(b"PK")) # the magic header for ZIP files
163
189
 
164
190
  # Check contents if requested
165
191
  if expectedContents is not None:
@@ -186,7 +212,7 @@ class ResourceTest(ToilTest):
186
212
  # urlopen() that yields the zipped tree ...
187
213
  mock_urlopen = MagicMock()
188
214
  mock_urlopen.return_value.read.return_value = zipFile
189
- with patch('toil.resource.urlopen', mock_urlopen):
215
+ with patch("toil.resource.urlopen", mock_urlopen):
190
216
  # ... and use it to download and unpack the resource
191
217
  localModule = module.localize()
192
218
  # The name should be equal between original and localized resource ...
@@ -217,22 +243,27 @@ class ResourceTest(ToilTest):
217
243
  def fn():
218
244
  pass
219
245
 
220
- if __name__ == '__main__':
246
+ if __name__ == "__main__":
221
247
  parser = ArgumentParser()
222
248
  Job.Runner.addToilOptions(parser)
223
249
  options = parser.parse_args()
224
- job = Job.wrapFn(fn, memory='10M', cores=0.1, disk='10M')
250
+ job = Job.wrapFn(fn, memory="10M", cores=0.1, disk="10M")
225
251
  with Toil(options) as toil:
226
252
  toil.start(job)
227
253
 
228
- scriptBody = dedent('\n'.join(getsource(script).split('\n')[1:]))
229
- shebang = '#! %s\n' % sys.executable
254
+ scriptBody = dedent("\n".join(getsource(script).split("\n")[1:]))
255
+ shebang = "#! %s\n" % sys.executable
230
256
  with tempFileContaining(shebang + scriptBody) as scriptPath:
231
- self.assertFalse(scriptPath.endswith(('.py', '.pyc')))
257
+ self.assertFalse(scriptPath.endswith((".py", ".pyc")))
232
258
  os.chmod(scriptPath, 0o755)
233
- jobStorePath = scriptPath + '.jobStore'
234
- process = subprocess.Popen([scriptPath, jobStorePath], stderr=subprocess.PIPE)
259
+ jobStorePath = scriptPath + ".jobStore"
260
+ process = subprocess.Popen(
261
+ [scriptPath, jobStorePath], stderr=subprocess.PIPE
262
+ )
235
263
  stdout, stderr = process.communicate()
236
- self.assertTrue('The name of a user script/module must end in .py or .pyc.' in stderr.decode('utf-8'))
264
+ self.assertTrue(
265
+ "The name of a user script/module must end in .py or .pyc."
266
+ in stderr.decode("utf-8")
267
+ )
237
268
  self.assertNotEqual(0, process.returncode)
238
269
  self.assertFalse(os.path.exists(jobStorePath))
@@ -31,9 +31,10 @@ class RestartDAGTest(ToilTest):
31
31
  Tests that restarted job DAGs don't run children of jobs that failed in the first run till the
32
32
  parent completes successfully in the restart.
33
33
  """
34
+
34
35
  def setUp(self):
35
36
  super().setUp()
36
- self.tempDir = self._createTempDir(purpose='tempDir')
37
+ self.tempDir = self._createTempDir(purpose="tempDir")
37
38
  self.testJobStore = self._getTestJobStorePath()
38
39
 
39
40
  def tearDown(self):
@@ -42,11 +43,11 @@ class RestartDAGTest(ToilTest):
42
43
 
43
44
  @slow
44
45
  def testRestartedWorkflowSchedulesCorrectJobsOnFailedParent(self):
45
- self._testRestartedWorkflowSchedulesCorrectJobs('raise')
46
+ self._testRestartedWorkflowSchedulesCorrectJobs("raise")
46
47
 
47
48
  @slow
48
49
  def testRestartedWorkflowSchedulesCorrectJobsOnKilledParent(self):
49
- self._testRestartedWorkflowSchedulesCorrectJobs('kill')
50
+ self._testRestartedWorkflowSchedulesCorrectJobs("kill")
50
51
 
51
52
  def _testRestartedWorkflowSchedulesCorrectJobs(self, failType):
52
53
  """
@@ -63,12 +64,12 @@ class RestartDAGTest(ToilTest):
63
64
  """
64
65
  # Specify options
65
66
  options = Job.Runner.getDefaultOptions(self.testJobStore)
66
- options.logLevel = 'DEBUG'
67
+ options.logLevel = "DEBUG"
67
68
  options.retryCount = 0
68
69
  options.clean = "never"
69
70
 
70
- parentFile = os.path.join(self.tempDir, 'parent')
71
- childFile = os.path.join(self.tempDir, 'child')
71
+ parentFile = os.path.join(self.tempDir, "parent")
72
+ childFile = os.path.join(self.tempDir, "child")
72
73
 
73
74
  # Make the first job
74
75
  root = Job.wrapJobFn(passingFn)
@@ -87,11 +88,11 @@ class RestartDAGTest(ToilTest):
87
88
  assert not os.path.exists(childFile)
88
89
 
89
90
  # Run the test
90
- for runMode in 'start', 'restart':
91
+ for runMode in "start", "restart":
91
92
  self.errorRaised = None
92
93
  try:
93
94
  with Toil(options) as toil:
94
- if runMode == 'start':
95
+ if runMode == "start":
95
96
  toil.start(root)
96
97
  else:
97
98
  toil.restart()
@@ -103,19 +104,27 @@ class RestartDAGTest(ToilTest):
103
104
  # it together in this finally clause.
104
105
  if self.errorRaised is not None:
105
106
  if not os.path.exists(parentFile):
106
- failReasons.append('The failing parent file did not exist on toil "%s".'
107
- % runMode)
107
+ failReasons.append(
108
+ 'The failing parent file did not exist on toil "%s".'
109
+ % runMode
110
+ )
108
111
  if os.path.exists(childFile):
109
- failReasons.append('The child file existed. i.e. the child was run on '
110
- 'toil "%s".' % runMode)
112
+ failReasons.append(
113
+ "The child file existed. i.e. the child was run on "
114
+ 'toil "%s".' % runMode
115
+ )
111
116
  if isinstance(self.errorRaised, FailedJobsException):
112
117
  if self.errorRaised.numberOfFailedJobs != 3:
113
- failReasons.append('FailedJobsException was raised on toil "%s" but '
114
- 'the number of failed jobs (%s) was not 3.'
115
- % (runMode, self.errorRaised.numberOfFailedJobs))
118
+ failReasons.append(
119
+ 'FailedJobsException was raised on toil "%s" but '
120
+ "the number of failed jobs (%s) was not 3."
121
+ % (runMode, self.errorRaised.numberOfFailedJobs)
122
+ )
116
123
  elif isinstance(self.errorRaised, AssertionError):
117
- failReasons.append('Toil raised an AssertionError instead of a '
118
- 'FailedJobsException on toil "%s".' % runMode)
124
+ failReasons.append(
125
+ "Toil raised an AssertionError instead of a "
126
+ 'FailedJobsException on toil "%s".' % runMode
127
+ )
119
128
  else:
120
129
  failReasons.append("Toil raised error: %s" % self.errorRaised)
121
130
  self.errorRaised = None
@@ -123,8 +132,12 @@ class RestartDAGTest(ToilTest):
123
132
  else:
124
133
  self.fail('No errors were raised on toil "%s".' % runMode)
125
134
  if failReasons:
126
- self.fail('Test failed for ({}) reasons:\n\t{}'.format(len(failReasons),
127
- '\n\t'.join(failReasons)))
135
+ self.fail(
136
+ "Test failed for ({}) reasons:\n\t{}".format(
137
+ len(failReasons), "\n\t".join(failReasons)
138
+ )
139
+ )
140
+
128
141
 
129
142
  def passingFn(job, fileName=None):
130
143
  """
@@ -135,7 +148,8 @@ def passingFn(job, fileName=None):
135
148
  """
136
149
  if fileName is not None:
137
150
  # Emulates system touch.
138
- open(fileName, 'w').close()
151
+ open(fileName, "w").close()
152
+
139
153
 
140
154
  def failingFn(job, failType, fileName):
141
155
  """
@@ -145,11 +159,11 @@ def failingFn(job, failType, fileName):
145
159
  :param str failType: 'raise' or 'kill
146
160
  :param str fileName: The name of a file that must be created.
147
161
  """
148
- assert failType in ('raise', 'kill')
162
+ assert failType in ("raise", "kill")
149
163
  # Use that function to avoid code redundancy
150
164
  passingFn(job, fileName)
151
165
 
152
- if failType == 'raise':
166
+ if failType == "raise":
153
167
  assert False
154
168
  else:
155
169
  os.kill(os.getpid(), signal.SIGKILL)
@@ -24,6 +24,7 @@ class ResumabilityTest(ToilTest):
24
24
  """
25
25
  https://github.com/BD2KGenomics/toil/issues/808
26
26
  """
27
+
27
28
  @slow
28
29
  def test(self):
29
30
  """
@@ -70,7 +71,7 @@ class ResumabilityTest(ToilTest):
70
71
  # This one is intended to fail.
71
72
  Job.Runner.startToil(root, options)
72
73
 
73
- with open(options.logFile, 'r') as f:
74
+ with open(options.logFile) as f:
74
75
  log_content = f.read()
75
76
  # Make sure we actually did do chaining
76
77
  assert "Chaining from" in log_content
@@ -81,6 +82,7 @@ class ResumabilityTest(ToilTest):
81
82
  options.restart = True
82
83
  Job.Runner.startToil(root, options)
83
84
 
85
+
84
86
  def parent(job):
85
87
  """
86
88
  Set up a bunch of dummy child jobs, and a bad job that needs to be
@@ -90,18 +92,21 @@ def parent(job):
90
92
  job.addChildJobFn(goodChild)
91
93
  job.addFollowOnJobFn(badChild)
92
94
 
95
+
93
96
  def chaining_parent(job):
94
97
  """
95
98
  Set up a failing job to chain to.
96
99
  """
97
100
  job.addFollowOnJobFn(badChild)
98
101
 
102
+
99
103
  def goodChild(job):
100
104
  """
101
105
  Does nothing.
102
106
  """
103
107
  return
104
108
 
109
+
105
110
  def badChild(job):
106
111
  """
107
112
  Fails the first time it's run, succeeds the second time.
@@ -110,6 +115,8 @@ def badChild(job):
110
115
  with job.fileStore.jobStore.read_shared_file_stream("alreadyRun") as fileHandle:
111
116
  fileHandle.read()
112
117
  except NoSuchFileException as ex:
113
- with job.fileStore.jobStore.write_shared_file_stream("alreadyRun", encrypted=False) as fileHandle:
118
+ with job.fileStore.jobStore.write_shared_file_stream(
119
+ "alreadyRun", encrypted=False
120
+ ) as fileHandle:
114
121
  fileHandle.write(b"failed once\n")
115
122
  raise RuntimeError(f"this is an expected error: {str(ex)}")
@@ -23,6 +23,7 @@ class CleanWorkDirTest(ToilTest):
23
23
  """
24
24
  Tests testing :class:toil.fileStores.abstractFileStore.AbstractFileStore
25
25
  """
26
+
26
27
  def setUp(self):
27
28
  super().setUp()
28
29
  self.testDir = self._createTempDir()
@@ -33,33 +34,61 @@ class CleanWorkDirTest(ToilTest):
33
34
 
34
35
  def testNever(self):
35
36
  retainedTempData = self._runAndReturnWorkDir("never", job=tempFileTestJob)
36
- self.assertNotEqual(retainedTempData, [], "The worker's temporary workspace was deleted despite "
37
- "cleanWorkDir being set to 'never'")
37
+ self.assertNotEqual(
38
+ retainedTempData,
39
+ [],
40
+ "The worker's temporary workspace was deleted despite "
41
+ "cleanWorkDir being set to 'never'",
42
+ )
38
43
 
39
44
  def testAlways(self):
40
45
  retainedTempData = self._runAndReturnWorkDir("always", job=tempFileTestJob)
41
- self.assertEqual(retainedTempData, [], "The worker's temporary workspace was not deleted despite "
42
- "cleanWorkDir being set to 'always'")
46
+ self.assertEqual(
47
+ retainedTempData,
48
+ [],
49
+ "The worker's temporary workspace was not deleted despite "
50
+ "cleanWorkDir being set to 'always'",
51
+ )
43
52
 
44
53
  def testOnErrorWithError(self):
45
- retainedTempData = self._runAndReturnWorkDir("onError", job=tempFileTestErrorJob, expectError=True)
46
- self.assertEqual(retainedTempData, [], "The worker's temporary workspace was not deleted despite "
47
- "an error occurring and cleanWorkDir being set to 'onError'")
54
+ retainedTempData = self._runAndReturnWorkDir(
55
+ "onError", job=tempFileTestErrorJob, expectError=True
56
+ )
57
+ self.assertEqual(
58
+ retainedTempData,
59
+ [],
60
+ "The worker's temporary workspace was not deleted despite "
61
+ "an error occurring and cleanWorkDir being set to 'onError'",
62
+ )
48
63
 
49
64
  def testOnErrorWithNoError(self):
50
65
  retainedTempData = self._runAndReturnWorkDir("onError", job=tempFileTestJob)
51
- self.assertNotEqual(retainedTempData, [], "The worker's temporary workspace was deleted despite "
52
- "no error occurring and cleanWorkDir being set to 'onError'")
66
+ self.assertNotEqual(
67
+ retainedTempData,
68
+ [],
69
+ "The worker's temporary workspace was deleted despite "
70
+ "no error occurring and cleanWorkDir being set to 'onError'",
71
+ )
53
72
 
54
73
  def testOnSuccessWithError(self):
55
- retainedTempData = self._runAndReturnWorkDir("onSuccess", job=tempFileTestErrorJob, expectError=True)
56
- self.assertNotEqual(retainedTempData, [], "The worker's temporary workspace was deleted despite "
57
- "an error occurring and cleanWorkDir being set to 'onSuccesss'")
74
+ retainedTempData = self._runAndReturnWorkDir(
75
+ "onSuccess", job=tempFileTestErrorJob, expectError=True
76
+ )
77
+ self.assertNotEqual(
78
+ retainedTempData,
79
+ [],
80
+ "The worker's temporary workspace was deleted despite "
81
+ "an error occurring and cleanWorkDir being set to 'onSuccesss'",
82
+ )
58
83
 
59
84
  def testOnSuccessWithSuccess(self):
60
85
  retainedTempData = self._runAndReturnWorkDir("onSuccess", job=tempFileTestJob)
61
- self.assertEqual(retainedTempData, [], "The worker's temporary workspace was not deleted despite "
62
- "a successful job execution and cleanWorkDir being set to 'onSuccesss'")
86
+ self.assertEqual(
87
+ retainedTempData,
88
+ [],
89
+ "The worker's temporary workspace was not deleted despite "
90
+ "a successful job execution and cleanWorkDir being set to 'onSuccesss'",
91
+ )
63
92
 
64
93
  def _runAndReturnWorkDir(self, cleanWorkDir, job, expectError=False):
65
94
  """
@@ -89,10 +118,12 @@ class CleanWorkDirTest(ToilTest):
89
118
  else:
90
119
  self.fail("Toil run succeeded unexpectedly")
91
120
 
121
+
92
122
  def tempFileTestJob(job):
93
123
  with open(job.fileStore.getLocalTempFile(), "w") as f:
94
124
  f.write("test file retention")
95
125
 
126
+
96
127
  def tempFileTestErrorJob(job):
97
128
  with open(job.fileStore.getLocalTempFile(), "w") as f:
98
129
  f.write("test file retention")
@@ -10,17 +10,21 @@ from toil.test import ToilTest
10
10
 
11
11
  class SystemTest(ToilTest):
12
12
  """Test various assumptions about the operating system's behavior."""
13
+
13
14
  def testAtomicityOfNonEmptyDirectoryRenames(self):
14
15
  for _ in range(100):
15
- parent = self._createTempDir(purpose='parent')
16
- child = os.path.join(parent, 'child')
16
+ parent = self._createTempDir(purpose="parent")
17
+ child = os.path.join(parent, "child")
17
18
  # Use processes (as opposed to threads) to prevent GIL from ordering things artificially
18
19
  pool = multiprocessing.Pool(processes=cpu_count())
19
20
  try:
20
21
  numTasks = cpu_count() * 10
21
22
  grandChildIds = pool.map_async(
22
- func=partial(_testAtomicityOfNonEmptyDirectoryRenamesTask, parent, child),
23
- iterable=list(range(numTasks)))
23
+ func=partial(
24
+ _testAtomicityOfNonEmptyDirectoryRenamesTask, parent, child
25
+ ),
26
+ iterable=list(range(numTasks)),
27
+ )
24
28
  grandChildIds = grandChildIds.get()
25
29
  finally:
26
30
  pool.close()
@@ -31,15 +35,15 @@ class SystemTest(ToilTest):
31
35
  self.assertEqual(len(grandChildIds), 1)
32
36
  # Assert that the winner's grandChild wasn't silently overwritten by a looser
33
37
  expectedGrandChildId = grandChildIds[0]
34
- actualGrandChild = os.path.join(child, 'grandChild')
38
+ actualGrandChild = os.path.join(child, "grandChild")
35
39
  actualGrandChildId = os.stat(actualGrandChild).st_ino
36
40
  self.assertEqual(actualGrandChildId, expectedGrandChildId)
37
41
 
38
42
 
39
43
  def _testAtomicityOfNonEmptyDirectoryRenamesTask(parent, child, _):
40
- tmpChildDir = mkdtemp(dir=parent, prefix='child', suffix='.tmp')
41
- grandChild = os.path.join(tmpChildDir, 'grandChild')
42
- open(grandChild, 'w').close()
44
+ tmpChildDir = mkdtemp(dir=parent, prefix="child", suffix=".tmp")
45
+ grandChild = os.path.join(tmpChildDir, "grandChild")
46
+ open(grandChild, "w").close()
43
47
  grandChildId = os.stat(grandChild).st_ino
44
48
  try:
45
49
  os.rename(tmpChildDir, child)