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/serviceManager.py CHANGED
@@ -15,9 +15,10 @@
15
15
 
16
16
  import logging
17
17
  import time
18
+ from collections.abc import Iterable
18
19
  from queue import Empty, Queue
19
20
  from threading import Event, Thread
20
- from typing import Iterable, Optional, Set
21
+ from typing import Optional
21
22
 
22
23
  from toil.job import ServiceJobDescription
23
24
  from toil.jobStores.abstractJobStore import AbstractJobStore
@@ -40,7 +41,7 @@ class ServiceManager:
40
41
 
41
42
  # These are all the client jobs that are waiting for their services to
42
43
  # start.
43
- self.__waiting_clients: Set[str] = set()
44
+ self.__waiting_clients: set[str] = set()
44
45
 
45
46
  # This is used to terminate the thread associated with the service
46
47
  # manager
@@ -123,7 +124,9 @@ class ServiceManager:
123
124
  client_id = self.__clients_out.get(timeout=maxWait)
124
125
  self.__waiting_clients.remove(client_id)
125
126
  if self.__service_manager_jobs < 0:
126
- raise RuntimeError("The number of jobs scheduled by the service manager cannot be negative.")
127
+ raise RuntimeError(
128
+ "The number of jobs scheduled by the service manager cannot be negative."
129
+ )
127
130
  self.__service_manager_jobs -= 1
128
131
  return client_id
129
132
  except Empty:
@@ -141,7 +144,9 @@ class ServiceManager:
141
144
  client_id = self.__failed_clients_out.get(timeout=maxWait)
142
145
  self.__waiting_clients.remove(client_id)
143
146
  if self.__service_manager_jobs < 0:
144
- raise RuntimeError("The number of jobs scheduled by the service manager cannot be negative.")
147
+ raise RuntimeError(
148
+ "The number of jobs scheduled by the service manager cannot be negative."
149
+ )
145
150
  self.__service_manager_jobs -= 1
146
151
  return client_id
147
152
  except Empty:
@@ -157,7 +162,9 @@ class ServiceManager:
157
162
  try:
158
163
  service_id = self.__services_out.get(timeout=maxWait)
159
164
  if self.__service_manager_jobs < 0:
160
- raise RuntimeError("The number of jobs scheduled by the service manager cannot be negative.")
165
+ raise RuntimeError(
166
+ "The number of jobs scheduled by the service manager cannot be negative."
167
+ )
161
168
  self.__service_manager_jobs -= 1
162
169
  return service_id
163
170
  except Empty:
@@ -226,7 +233,7 @@ class ServiceManager:
226
233
 
227
234
  Will block until all services are started and blocked.
228
235
  """
229
- logger.debug('Waiting for service manager thread to finish ...')
236
+ logger.debug("Waiting for service manager thread to finish ...")
230
237
  start_time = time.time()
231
238
  self.__terminate.set()
232
239
  self.__service_starter.join()
@@ -251,13 +258,17 @@ class ServiceManager:
251
258
  while True:
252
259
  with throttle(1.0):
253
260
  if self.__terminate.is_set():
254
- logger.debug('Received signal to quit starting services.')
261
+ logger.debug("Received signal to quit starting services.")
255
262
  break
256
263
  try:
257
264
  client_id = self.__clients_in.get_nowait()
258
265
  client = self.__toil_state.get_job(client_id)
259
266
  host_id_batches = list(client.serviceHostIDsInBatches())
260
- logger.debug("Service manager processing client %s with %d batches of services", client, len(host_id_batches))
267
+ logger.debug(
268
+ "Service manager processing client %s with %d batches of services",
269
+ client,
270
+ len(host_id_batches),
271
+ )
261
272
  if len(host_id_batches) > 1:
262
273
  # Have to fall back to the old blocking behavior to
263
274
  # ensure entire service "groups" are issued as a whole.
@@ -288,7 +299,7 @@ class ServiceManager:
288
299
 
289
300
  pending_service_count = len(starting_services)
290
301
  if pending_service_count > 0 and log_limiter.throttle(False):
291
- logger.debug('%d services are starting...', pending_service_count)
302
+ logger.debug("%d services are starting...", pending_service_count)
292
303
 
293
304
  for service_id in list(starting_services):
294
305
  service_job_desc = self._get_service_job(service_id)
@@ -297,7 +308,9 @@ class ServiceManager:
297
308
  or service_job_desc.errorJobStoreID is None
298
309
  ):
299
310
  raise Exception("Must be a registered ServiceJobDescription")
300
- if not self.__job_store.file_exists(service_job_desc.startJobStoreID):
311
+ if not self.__job_store.file_exists(
312
+ service_job_desc.startJobStoreID
313
+ ):
301
314
  # Service has started (or failed)
302
315
  logger.debug(
303
316
  "Service %s has removed %s and is therefore started",
@@ -308,9 +321,13 @@ class ServiceManager:
308
321
  client_id = service_to_client[service_id]
309
322
  remaining_services_by_client[client_id] -= 1
310
323
  if remaining_services_by_client[client_id] < 0:
311
- raise RuntimeError("The number of remaining services cannot be negative.")
324
+ raise RuntimeError(
325
+ "The number of remaining services cannot be negative."
326
+ )
312
327
  del service_to_client[service_id]
313
- if not self.__job_store.file_exists(service_job_desc.errorJobStoreID):
328
+ if not self.__job_store.file_exists(
329
+ service_job_desc.errorJobStoreID
330
+ ):
314
331
  logger.error(
315
332
  "Service %s has immediately failed before it could be used",
316
333
  service_job_desc,
@@ -321,13 +338,22 @@ class ServiceManager:
321
338
 
322
339
  # Find if any clients have had *all* their services started.
323
340
  ready_clients = set()
324
- for client_id, remainingServices in remaining_services_by_client.items():
341
+ for (
342
+ client_id,
343
+ remainingServices,
344
+ ) in remaining_services_by_client.items():
325
345
  if remainingServices == 0:
326
346
  if client_id in clients_with_failed_services:
327
- logger.error('Job %s has had all its services try to start, but at least one failed', self.__toil_state.get_job(client_id))
347
+ logger.error(
348
+ "Job %s has had all its services try to start, but at least one failed",
349
+ self.__toil_state.get_job(client_id),
350
+ )
328
351
  self.__failed_clients_out.put(client_id)
329
352
  else:
330
- logger.debug('Job %s has all its services started', self.__toil_state.get_job(client_id))
353
+ logger.debug(
354
+ "Job %s has all its services started",
355
+ self.__toil_state.get_job(client_id),
356
+ )
331
357
  self.__clients_out.put(client_id)
332
358
  ready_clients.add(client_id)
333
359
  for client_id in ready_clients:
@@ -344,7 +370,9 @@ class ServiceManager:
344
370
 
345
371
  # Start the service jobs in batches, waiting for each batch
346
372
  # to become established before starting the next batch
347
- for service_job_list in self.__toil_state.get_job(client_id).serviceHostIDsInBatches():
373
+ for service_job_list in self.__toil_state.get_job(
374
+ client_id
375
+ ).serviceHostIDsInBatches():
348
376
  # When we get the job descriptions we store them here to go over them again.
349
377
  wait_on = []
350
378
  for service_id in service_job_list:
@@ -361,9 +389,13 @@ class ServiceManager:
361
389
  service_job_desc.startJobStoreID,
362
390
  )
363
391
  if not self.__job_store.file_exists(service_job_desc.startJobStoreID):
364
- raise RuntimeError(f"Service manager attempted to start service {service_job_desc} that has already started")
392
+ raise RuntimeError(
393
+ f"Service manager attempted to start service {service_job_desc} that has already started"
394
+ )
365
395
  if not self.__toil_state.job_exists(str(service_job_desc.jobStoreID)):
366
- raise RuntimeError(f"Service manager attempted to start service {service_job_desc} that is not in the job store")
396
+ raise RuntimeError(
397
+ f"Service manager attempted to start service {service_job_desc} that is not in the job store"
398
+ )
367
399
  # At this point the terminateJobStoreID and errorJobStoreID
368
400
  # could have been deleted, since the service can be killed at
369
401
  # any time! So we can't assert their presence here.
@@ -382,7 +414,7 @@ class ServiceManager:
382
414
  time.sleep(1.0)
383
415
 
384
416
  if log_limiter.throttle(False):
385
- logger.info('Service %s is starting...', service_job_desc)
417
+ logger.info("Service %s is starting...", service_job_desc)
386
418
 
387
419
  # Check if the thread should quit
388
420
  if self.__terminate.is_set():
@@ -395,9 +427,14 @@ class ServiceManager:
395
427
  ):
396
428
  # The service job has gone away but the service never flipped its start flag.
397
429
  # That's not what the worker is supposed to do when running a service at all.
398
- logger.error('Service %s has completed and been removed without ever starting', service_job_desc)
430
+ logger.error(
431
+ "Service %s has completed and been removed without ever starting",
432
+ service_job_desc,
433
+ )
399
434
  # Stop everything.
400
- raise RuntimeError(f"Service {service_job_desc} is in an inconsistent state")
435
+ raise RuntimeError(
436
+ f"Service {service_job_desc} is in an inconsistent state"
437
+ )
401
438
 
402
439
  # We don't bail out early here.
403
440
 
@@ -409,6 +446,5 @@ class ServiceManager:
409
446
  # though, so they should stop immediately when we run them. TODO:
410
447
  # this is a bad design!
411
448
 
412
-
413
449
  # Add the JobDescription to the output queue of jobs whose services have been started
414
450
  self.__clients_out.put(client_id)