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
toil/test/src/jobTest.py CHANGED
@@ -29,6 +29,7 @@ logger = logging.getLogger(__name__)
29
29
 
30
30
  class JobTest(ToilTest):
31
31
  """Tests the job class."""
32
+
32
33
  @classmethod
33
34
  def setUpClass(cls):
34
35
  super().setUpClass()
@@ -121,9 +122,9 @@ class JobTest(ToilTest):
121
122
 
122
123
  @slow
123
124
  def testTrivialDAGConsistency(self):
124
- options = Job.Runner.getDefaultOptions(self._createTempDir() + '/jobStore')
125
- options.clean = 'always'
126
- options.logLevel = 'debug'
125
+ options = Job.Runner.getDefaultOptions(self._createTempDir() + "/jobStore")
126
+ options.clean = "always"
127
+ options.logLevel = "debug"
127
128
  i = Job.wrapJobFn(trivialParent)
128
129
  with Toil(options) as toil:
129
130
  try:
@@ -136,9 +137,9 @@ class JobTest(ToilTest):
136
137
 
137
138
  @pytest.mark.timeout(300)
138
139
  def testDAGConsistency(self):
139
- options = Job.Runner.getDefaultOptions(self._createTempDir() + '/jobStore')
140
- options.clean = 'always'
141
- options.logLevel = 'debug'
140
+ options = Job.Runner.getDefaultOptions(self._createTempDir() + "/jobStore")
141
+ options.clean = "always"
142
+ options.logLevel = "debug"
142
143
  i = Job.wrapJobFn(parent)
143
144
  with Toil(options) as toil:
144
145
  try:
@@ -155,9 +156,9 @@ class JobTest(ToilTest):
155
156
  Slightly more complex case. The stranded job's predecessors are siblings instead of
156
157
  parent/child.
157
158
  """
158
- options = Job.Runner.getDefaultOptions(self._createTempDir() + '/jobStore')
159
- options.clean = 'always'
160
- options.logLevel = 'debug'
159
+ options = Job.Runner.getDefaultOptions(self._createTempDir() + "/jobStore")
160
+ options.clean = "always"
161
+ options.logLevel = "debug"
161
162
  i = Job.wrapJobFn(diamond)
162
163
  with Toil(options) as toil:
163
164
  try:
@@ -196,8 +197,12 @@ class JobTest(ToilTest):
196
197
 
197
198
  # Test making multiple roots
198
199
  childEdges2 = childEdges.copy()
199
- childEdges2.add((nodeNumber, 1)) # This creates an extra root at "nodeNumber"
200
- rootJob2 = self.makeJobGraph(nodeNumber + 1, childEdges2, followOnEdges, None, False)
200
+ childEdges2.add(
201
+ (nodeNumber, 1)
202
+ ) # This creates an extra root at "nodeNumber"
203
+ rootJob2 = self.makeJobGraph(
204
+ nodeNumber + 1, childEdges2, followOnEdges, None, False
205
+ )
201
206
  try:
202
207
  rootJob2.checkJobGraphConnected()
203
208
  self.assertTrue(False) # Multiple roots were not detected
@@ -209,8 +214,9 @@ class JobTest(ToilTest):
209
214
  adjacencyList[fNode].add(tNode)
210
215
  self.assertTrue(not self.isAcyclic(adjacencyList))
211
216
  try:
212
- self.makeJobGraph(nodeNumber, childEdges,
213
- followOnEdges, None).checkJobGraphAcylic()
217
+ self.makeJobGraph(
218
+ nodeNumber, childEdges, followOnEdges, None
219
+ ).checkJobGraphAcylic()
214
220
  self.assertTrue(False) # A cycle was not detected
215
221
  except JobGraphDeadlockException:
216
222
  pass # This is the expected behaviour
@@ -218,22 +224,25 @@ class JobTest(ToilTest):
218
224
  childEdges.remove((fNode, tNode))
219
225
  adjacencyList[fNode].remove(tNode)
220
226
  # Check is now acyclic again
221
- self.makeJobGraph(nodeNumber, childEdges,
222
- followOnEdges, None, False).checkJobGraphAcylic()
227
+ self.makeJobGraph(
228
+ nodeNumber, childEdges, followOnEdges, None, False
229
+ ).checkJobGraphAcylic()
223
230
 
224
231
  def checkFollowOnEdgeCycleDetection(fNode, tNode):
225
232
  followOnEdges.add((fNode, tNode)) # Create a cycle
226
233
  try:
227
- self.makeJobGraph(nodeNumber, childEdges,
228
- followOnEdges, None, False).checkJobGraphAcylic()
234
+ self.makeJobGraph(
235
+ nodeNumber, childEdges, followOnEdges, None, False
236
+ ).checkJobGraphAcylic()
229
237
  # self.assertTrue(False) #The cycle was not detected
230
238
  except JobGraphDeadlockException:
231
239
  pass # This is the expected behaviour
232
240
  # Remove the edges
233
241
  followOnEdges.remove((fNode, tNode))
234
242
  # Check is now acyclic again
235
- self.makeJobGraph(nodeNumber, childEdges,
236
- followOnEdges, None, False).checkJobGraphAcylic()
243
+ self.makeJobGraph(
244
+ nodeNumber, childEdges, followOnEdges, None, False
245
+ ).checkJobGraphAcylic()
237
246
 
238
247
  # Now try adding edges that create a cycle
239
248
 
@@ -257,9 +266,16 @@ class JobTest(ToilTest):
257
266
 
258
267
  # Try adding a follow on edge between two nodes with shared descendants
259
268
  fNode, tNode = self.getRandomEdge(nodeNumber)
260
- if (len(self.reachable(tNode, adjacencyList)
261
- .intersection(self.reachable(fNode, adjacencyList))) > 0
262
- and (fNode, tNode) not in childEdges and (fNode, tNode) not in followOnEdges):
269
+ if (
270
+ len(
271
+ self.reachable(tNode, adjacencyList).intersection(
272
+ self.reachable(fNode, adjacencyList)
273
+ )
274
+ )
275
+ > 0
276
+ and (fNode, tNode) not in childEdges
277
+ and (fNode, tNode) not in followOnEdges
278
+ ):
263
279
  checkFollowOnEdgeCycleDetection(fNode, tNode)
264
280
 
265
281
  @slow
@@ -268,7 +284,7 @@ class JobTest(ToilTest):
268
284
  Test for issue #1465: Detection of checkpoint jobs that are not leaf vertices
269
285
  identifies leaf vertices incorrectly
270
286
 
271
- Test verification of new checkpoint jobs being leaf verticies,
287
+ Test verification of new checkpoint jobs being leaf vertices,
272
288
  starting with the following baseline workflow::
273
289
 
274
290
  Parent
@@ -279,7 +295,9 @@ class JobTest(ToilTest):
279
295
 
280
296
  def createWorkflow():
281
297
  rootJob = Job.wrapJobFn(simpleJobFn, "Parent")
282
- childCheckpointJob = rootJob.addChildJobFn(simpleJobFn, "Child", checkpoint=True)
298
+ childCheckpointJob = rootJob.addChildJobFn(
299
+ simpleJobFn, "Child", checkpoint=True
300
+ )
283
301
  return rootJob, childCheckpointJob
284
302
 
285
303
  self.runNewCheckpointIsLeafVertexTest(createWorkflow)
@@ -315,35 +333,45 @@ class JobTest(ToilTest):
315
333
 
316
334
  """
317
335
 
318
- logger.debug('Test checkpoint job that is a leaf vertex')
319
- self.runCheckpointVertexTest(*createWorkflowFn(),
320
- expectedException=None)
321
-
322
- logger.debug('Test checkpoint job that is not a leaf vertex due to the presence of a service')
323
- self.runCheckpointVertexTest(*createWorkflowFn(),
324
- checkpointJobService=TrivialService("LeafTestService"),
325
- expectedException=JobGraphDeadlockException)
326
-
327
- logger.debug('Test checkpoint job that is not a leaf vertex due to the presence of a child job')
328
- self.runCheckpointVertexTest(*createWorkflowFn(),
329
- checkpointJobChild=Job.wrapJobFn(
330
- simpleJobFn, "LeafTestChild"),
331
- expectedException=JobGraphDeadlockException)
332
-
333
- logger.debug('Test checkpoint job that is not a leaf vertex due to the presence of a follow-on job')
334
- self.runCheckpointVertexTest(*createWorkflowFn(),
335
- checkpointJobFollowOn=Job.wrapJobFn(
336
- simpleJobFn,
337
- "LeafTestFollowOn"),
338
- expectedException=JobGraphDeadlockException)
339
-
340
- def runCheckpointVertexTest(self,
341
- workflowRootJob,
342
- checkpointJob,
343
- checkpointJobService=None,
344
- checkpointJobChild=None,
345
- checkpointJobFollowOn=None,
346
- expectedException=None):
336
+ logger.debug("Test checkpoint job that is a leaf vertex")
337
+ self.runCheckpointVertexTest(*createWorkflowFn(), expectedException=None)
338
+
339
+ logger.debug(
340
+ "Test checkpoint job that is not a leaf vertex due to the presence of a service"
341
+ )
342
+ self.runCheckpointVertexTest(
343
+ *createWorkflowFn(),
344
+ checkpointJobService=TrivialService("LeafTestService"),
345
+ expectedException=JobGraphDeadlockException
346
+ )
347
+
348
+ logger.debug(
349
+ "Test checkpoint job that is not a leaf vertex due to the presence of a child job"
350
+ )
351
+ self.runCheckpointVertexTest(
352
+ *createWorkflowFn(),
353
+ checkpointJobChild=Job.wrapJobFn(simpleJobFn, "LeafTestChild"),
354
+ expectedException=JobGraphDeadlockException
355
+ )
356
+
357
+ logger.debug(
358
+ "Test checkpoint job that is not a leaf vertex due to the presence of a follow-on job"
359
+ )
360
+ self.runCheckpointVertexTest(
361
+ *createWorkflowFn(),
362
+ checkpointJobFollowOn=Job.wrapJobFn(simpleJobFn, "LeafTestFollowOn"),
363
+ expectedException=JobGraphDeadlockException
364
+ )
365
+
366
+ def runCheckpointVertexTest(
367
+ self,
368
+ workflowRootJob,
369
+ checkpointJob,
370
+ checkpointJobService=None,
371
+ checkpointJobChild=None,
372
+ checkpointJobFollowOn=None,
373
+ expectedException=None,
374
+ ):
347
375
  """
348
376
  Modifies the checkpoint job according to the given parameters
349
377
  then runs the workflow, checking for the expected exception, if any.
@@ -380,7 +408,7 @@ class JobTest(ToilTest):
380
408
  jobStore = self._getTestJobStorePath()
381
409
  for test in range(5):
382
410
  # Temporary file
383
- tempDir = self._createTempDir(purpose='tempDir')
411
+ tempDir = self._createTempDir(purpose="tempDir")
384
412
  # Make a random DAG for the set of child edges
385
413
  nodeNumber = random.choice(range(2, 8))
386
414
  childEdges = self.makeRandomDAG(nodeNumber)
@@ -421,8 +449,8 @@ class JobTest(ToilTest):
421
449
  numberOfFailedJobs = 0
422
450
  except FailedJobsException as e:
423
451
  numberOfFailedJobs = e.numberOfFailedJobs
424
- if totalTrys > 32: #p(fail after this many restarts) ~= 0.5**32
425
- self.fail() #Exceeded a reasonable number of restarts
452
+ if totalTrys > 32: # p(fail after this many restarts) ~= 0.5**32
453
+ self.fail() # Exceeded a reasonable number of restarts
426
454
  totalTrys += 1
427
455
 
428
456
  # For each job check it created a valid output file and add the ordering
@@ -447,7 +475,7 @@ class JobTest(ToilTest):
447
475
  def getRandomEdge(nodeNumber):
448
476
  assert nodeNumber > 1
449
477
  fNode = random.choice(range(nodeNumber - 1))
450
- return fNode, random.choice(range(fNode+1, nodeNumber))
478
+ return fNode, random.choice(range(fNode + 1, nodeNumber))
451
479
 
452
480
  @staticmethod
453
481
  def makeRandomDAG(nodeNumber):
@@ -457,7 +485,9 @@ class JobTest(ToilTest):
457
485
  referring to nodes and the edge is from a to b.
458
486
  """
459
487
  # Pick number of total edges to create
460
- edgeNumber = random.choice(range(nodeNumber - 1, 1 + (nodeNumber * (nodeNumber - 1) // 2)))
488
+ edgeNumber = random.choice(
489
+ range(nodeNumber - 1, 1 + (nodeNumber * (nodeNumber - 1) // 2))
490
+ )
461
491
  # Make a spanning tree of edges so that nodes are connected
462
492
  edges = {(random.choice(range(i)), i) for i in range(1, nodeNumber)}
463
493
  # Add extra random edges until there are edgeNumber edges
@@ -499,8 +529,10 @@ class JobTest(ToilTest):
499
529
  """
500
530
 
501
531
  def makeAugmentedAdjacencyList():
502
- augmentedAdjacencyList = [childAdjacencyList[i].union(followOnAdjacencyList[i])
503
- for i in range(len(childAdjacencyList))]
532
+ augmentedAdjacencyList = [
533
+ childAdjacencyList[i].union(followOnAdjacencyList[i])
534
+ for i in range(len(childAdjacencyList))
535
+ ]
504
536
 
505
537
  def addImpliedEdges(node, followOnEdges):
506
538
  # Let node2 be a child of node or a successor of a child of node.
@@ -550,7 +582,9 @@ class JobTest(ToilTest):
550
582
 
551
583
  return followOnEdges
552
584
 
553
- def makeJobGraph(self, nodeNumber, childEdges, followOnEdges, outPath, addServices=True):
585
+ def makeJobGraph(
586
+ self, nodeNumber, childEdges, followOnEdges, outPath, addServices=True
587
+ ):
554
588
  """
555
589
  Converts a DAG into a job graph. childEdges and followOnEdges are the lists of child and
556
590
  followOn edges.
@@ -560,9 +594,15 @@ class JobTest(ToilTest):
560
594
 
561
595
  def makeJob(string):
562
596
  promises = []
563
- job = Job.wrapFn(fn2Test, promises, string,
564
- None if outPath is None else os.path.join(outPath, string),
565
- cores=0.1, memory="0.5G", disk="0.1G")
597
+ job = Job.wrapFn(
598
+ fn2Test,
599
+ promises,
600
+ string,
601
+ None if outPath is None else os.path.join(outPath, string),
602
+ cores=0.1,
603
+ memory="0.5G",
604
+ disk="0.1G",
605
+ )
566
606
  jobsToPromisesMap[job] = promises
567
607
  return job
568
608
 
@@ -581,7 +621,16 @@ class JobTest(ToilTest):
581
621
  predecessors[jobs[tNode]].append(jobs[fNode])
582
622
 
583
623
  # Map of jobs to return values
584
- jobsToRvs = {job: job.addService(TrivialService(job.rv(), cores=0.1, memory="0.5G", disk="0.1G")) if addServices else job.rv() for job in jobs}
624
+ jobsToRvs = {
625
+ job: (
626
+ job.addService(
627
+ TrivialService(job.rv(), cores=0.1, memory="0.5G", disk="0.1G")
628
+ )
629
+ if addServices
630
+ else job.rv()
631
+ )
632
+ for job in jobs
633
+ }
585
634
 
586
635
  def getRandomPredecessor(job):
587
636
  predecessor = random.choice(list(predecessors[job]))
@@ -622,9 +671,11 @@ class JobTest(ToilTest):
622
671
  return False
623
672
  return True
624
673
 
674
+
625
675
  def simpleJobFn(job, value):
626
676
  job.fileStore.log_to_leader(value)
627
677
 
678
+
628
679
  def fn1Test(string, outputFile):
629
680
  """
630
681
  Function appends the next character after the last character in the given
@@ -633,7 +684,7 @@ def fn1Test(string, outputFile):
633
684
  """
634
685
 
635
686
  rV = string + chr(ord(string[-1]) + 1)
636
- with open(outputFile, 'w') as fH:
687
+ with open(outputFile, "w") as fH:
637
688
  fH.write(rV)
638
689
  return rV
639
690
 
@@ -643,7 +694,7 @@ def fn2Test(pStrings, s, outputFile):
643
694
  Function concatenates the strings in pStrings and s, in that order, and writes the result to
644
695
  the output file. Returns s.
645
696
  """
646
- with open(outputFile, 'w') as fH:
697
+ with open(outputFile, "w") as fH:
647
698
  fH.write(" ".join(pStrings) + " " + s)
648
699
  return s
649
700
 
@@ -687,13 +738,12 @@ def child(job):
687
738
 
688
739
 
689
740
  def errorChild(job):
690
- raise RuntimeError('Child failure')
741
+ raise RuntimeError("Child failure")
691
742
 
692
743
 
693
744
  class TrivialService(Job.Service):
694
745
  def __init__(self, message, *args, **kwargs):
695
- """ Service that does nothing, used to check for deadlocks
696
- """
746
+ """Service that does nothing, used to check for deadlocks"""
697
747
  Job.Service.__init__(self, *args, **kwargs)
698
748
  self.message = message
699
749
 
@@ -707,5 +757,5 @@ class TrivialService(Job.Service):
707
757
  pass
708
758
 
709
759
 
710
- if __name__ == '__main__':
760
+ if __name__ == "__main__":
711
761
  unittest.main()
@@ -20,10 +20,7 @@ from uuid import uuid4
20
20
 
21
21
  from toil.common import getNodeID
22
22
  from toil.lib.exceptions import panic, raise_
23
- from toil.lib.io import (AtomicFileCreate,
24
- atomic_install,
25
- atomic_tmp_file,
26
- mkdtemp)
23
+ from toil.lib.io import AtomicFileCreate, atomic_install, atomic_tmp_file, mkdtemp
27
24
  from toil.lib.misc import CalledProcessErrorStderr, call_command
28
25
  from toil.test import ToilTest, slow
29
26
 
@@ -36,6 +33,7 @@ class MiscTests(ToilTest):
36
33
  This class contains miscellaneous tests that don't have enough content to be their own test
37
34
  file, and that don't logically fit in with any of the other test suites.
38
35
  """
36
+
39
37
  def setUp(self):
40
38
  super().setUp()
41
39
  self.testDir = self._createTempDir()
@@ -49,14 +47,14 @@ class MiscTests(ToilTest):
49
47
 
50
48
  @slow
51
49
  def testGetSizeOfDirectoryWorks(self):
52
- '''A test to make sure toil.common.getDirSizeRecursively does not
50
+ """A test to make sure toil.common.getDirSizeRecursively does not
53
51
  underestimate the amount of disk space needed.
54
52
 
55
53
  Disk space allocation varies from system to system. The computed value
56
54
  should always be equal to or slightly greater than the creation value.
57
55
  This test generates a number of random directories and randomly sized
58
56
  files to test this using getDirSizeRecursively.
59
- '''
57
+ """
60
58
  from toil.common import getDirSizeRecursively
61
59
 
62
60
  # a list of the directories used in the test
@@ -64,17 +62,17 @@ class MiscTests(ToilTest):
64
62
  # A dict of {FILENAME: FILESIZE} for all files used in the test
65
63
  files = {}
66
64
  # Create a random directory structure
67
- for i in range(0,10):
68
- directories.append(mkdtemp(dir=random.choice(directories), prefix='test'))
65
+ for i in range(0, 10):
66
+ directories.append(mkdtemp(dir=random.choice(directories), prefix="test"))
69
67
  # Create 50 random file entries in different locations in the directories. 75% of the time
70
68
  # these are fresh files of size [1, 10] MB and 25% of the time they are hard links to old
71
69
  # files.
72
70
  while len(files) <= 50:
73
71
  fileName = os.path.join(random.choice(directories), self._getRandomName())
74
- if random.randint(0,100) < 75:
72
+ if random.randint(0, 100) < 75:
75
73
  # Create a fresh file in the range of 1-10 MB
76
74
  fileSize = int(round(random.random(), 2) * 10 * 1024 * 1024)
77
- with open(fileName, 'wb') as fileHandle:
75
+ with open(fileName, "wb") as fileHandle:
78
76
  fileHandle.write(os.urandom(fileSize))
79
77
  files[fileName] = fileSize
80
78
  else:
@@ -83,7 +81,7 @@ class MiscTests(ToilTest):
83
81
  continue
84
82
  linkSrc = random.choice(list(files.keys()))
85
83
  os.link(linkSrc, fileName)
86
- files[fileName] = 'Link to %s' % linkSrc
84
+ files[fileName] = "Link to %s" % linkSrc
87
85
 
88
86
  computedDirectorySize = getDirSizeRecursively(self.testDir)
89
87
  totalExpectedSize = sum(x for x in list(files.values()) if isinstance(x, int))
@@ -101,7 +99,7 @@ class MiscTests(ToilTest):
101
99
 
102
100
  def _write_test_file(self, outf_tmp):
103
101
  with open(outf_tmp, "w") as fh:
104
- fh.write(self.id() + '\n')
102
+ fh.write(self.id() + "\n")
105
103
 
106
104
  def test_atomic_install(self):
107
105
  outf = self._get_test_out_file(".foo.gz")
@@ -111,7 +109,7 @@ class MiscTests(ToilTest):
111
109
  self.assertTrue(os.path.exists(outf))
112
110
 
113
111
  def test_atomic_install_dev(self):
114
- devn = '/dev/null'
112
+ devn = "/dev/null"
115
113
  tmp = atomic_tmp_file(devn)
116
114
  self.assertEqual(tmp, devn)
117
115
  atomic_install(tmp, devn)
@@ -138,10 +136,13 @@ class MiscTests(ToilTest):
138
136
  self.assertTrue(isinstance(o, str), str(type(o)))
139
137
 
140
138
  def test_call_command_err(self):
141
- with self.assertRaisesRegex(CalledProcessErrorStderr,
142
- "^Command '\\['cat', '/dev/Frankenheimer']' exit status 1: cat: /dev/Frankenheimer: No such file or directory\n$"):
139
+ with self.assertRaisesRegex(
140
+ CalledProcessErrorStderr,
141
+ "^Command '\\['cat', '/dev/Frankenheimer']' exit status 1: cat: /dev/Frankenheimer: No such file or directory\n$",
142
+ ):
143
143
  call_command(["cat", "/dev/Frankenheimer"])
144
144
 
145
+
145
146
  class TestPanic(ToilTest):
146
147
  def test_panic_by_hand(self):
147
148
  try:
@@ -192,7 +193,7 @@ class TestPanic(ToilTest):
192
193
  self.line_of_primary_exc = inspect.currentframe().f_lineno + 1
193
194
  raise ValueError("primary")
194
195
  except:
195
- with panic( log ):
196
+ with panic(log):
196
197
  raise RuntimeError("secondary")
197
198
 
198
199
  def try_and_nested_panic_with_secondary(self):
@@ -200,8 +201,8 @@ class TestPanic(ToilTest):
200
201
  self.line_of_primary_exc = inspect.currentframe().f_lineno + 1
201
202
  raise ValueError("primary")
202
203
  except:
203
- with panic( log ):
204
- with panic( log ):
204
+ with panic(log):
205
+ with panic(log):
205
206
  raise RuntimeError("secondary")
206
207
 
207
208
  def __assert_raised_exception_is_primary(self):