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
@@ -21,26 +21,28 @@ from contextlib import contextmanager
21
21
  from typing import (IO,
22
22
  Any,
23
23
  Callable,
24
+ ContextManager,
24
25
  DefaultDict,
25
26
  Dict,
26
27
  Generator,
27
28
  Iterator,
28
29
  List,
30
+ Literal,
29
31
  Optional,
30
32
  Union,
31
- cast)
33
+ cast,
34
+ overload)
32
35
 
33
36
  import dill
34
37
 
35
- from toil.common import getDirSizeRecursively, getFileSystemSize
38
+ from toil.common import getFileSystemSize
36
39
  from toil.fileStores import FileID
37
40
  from toil.fileStores.abstractFileStore import AbstractFileStore
38
41
  from toil.job import Job, JobDescription
39
42
  from toil.jobStores.abstractJobStore import AbstractJobStore
40
43
  from toil.lib.compatibility import deprecated
41
- from toil.lib.conversions import bytes2human
42
44
  from toil.lib.io import make_public_dir, robust_rmtree
43
- from toil.lib.retry import retry, ErrorCondition
45
+ from toil.lib.retry import ErrorCondition, retry
44
46
  from toil.lib.threading import get_process_name, process_name_exists
45
47
 
46
48
  logger: logging.Logger = logging.getLogger(__name__)
@@ -99,7 +101,6 @@ class NonCachingFileStore(AbstractFileStore):
99
101
 
100
102
  @contextmanager
101
103
  def open(self, job: Job) -> Generator[None, None, None]:
102
- jobReqs = job.disk
103
104
  startingDir = os.getcwd()
104
105
  self.localTempDir: str = make_public_dir(in_directory=self.localTempDir)
105
106
  self._removeDeadJobs(self.coordination_dir)
@@ -113,20 +114,14 @@ class NonCachingFileStore(AbstractFileStore):
113
114
  with super().open(job):
114
115
  yield
115
116
  finally:
116
- disk = getDirSizeRecursively(self.localTempDir)
117
- percent = float(disk) / jobReqs * 100 if jobReqs > 0 else 0.0
118
- disk_usage = (f"Job {self.jobName} used {percent:.2f}% disk ({bytes2human(disk)}B [{disk}B] used, "
119
- f"{bytes2human(jobReqs)}B [{jobReqs}B] requested).")
120
- if disk > jobReqs:
121
- self.logToMaster("Job used more disk than requested. For CWL, consider increasing the outdirMin "
122
- f"requirement, otherwise, consider increasing the disk requirement. {disk_usage}",
123
- level=logging.WARNING)
124
- else:
125
- self.logToMaster(disk_usage, level=logging.DEBUG)
126
117
  os.chdir(startingDir)
127
118
  # Finally delete the job from the worker
128
119
  self.check_for_state_corruption()
129
- os.remove(self.jobStateFile)
120
+ try:
121
+ os.remove(self.jobStateFile)
122
+ except FileNotFoundError:
123
+ logger.exception('Job state file %s has gone missing unexpectedly; some cleanup for failed jobs may be getting skipped!', self.jobStateFile)
124
+ pass
130
125
 
131
126
  def writeGlobalFile(self, localFileName: str, cleanup: bool=False) -> FileID:
132
127
  absLocalFileName = self._resolveAbsoluteLocalPath(localFileName)
@@ -152,7 +147,25 @@ class NonCachingFileStore(AbstractFileStore):
152
147
  self.logAccess(fileStoreID, localFilePath)
153
148
  return localFilePath
154
149
 
155
- @contextmanager
150
+ @overload
151
+ def readGlobalFileStream(
152
+ self,
153
+ fileStoreID: str,
154
+ encoding: Literal[None] = None,
155
+ errors: Optional[str] = None,
156
+ ) -> ContextManager[IO[bytes]]:
157
+ ...
158
+
159
+ @overload
160
+ def readGlobalFileStream(
161
+ self, fileStoreID: str, encoding: str, errors: Optional[str] = None
162
+ ) -> ContextManager[IO[str]]:
163
+ ...
164
+
165
+ # TODO: This seems to hit https://github.com/python/mypy/issues/11373
166
+ # But that is supposedly fixed.
167
+
168
+ @contextmanager # type: ignore
156
169
  def readGlobalFileStream(self, fileStoreID: str, encoding: Optional[str] = None, errors: Optional[str] = None) -> Iterator[Union[IO[bytes], IO[str]]]:
157
170
  with self.jobStore.read_file_stream(fileStoreID, encoding=encoding, errors=errors) as f:
158
171
  self.logAccess(fileStoreID)
@@ -194,18 +207,21 @@ class NonCachingFileStore(AbstractFileStore):
194
207
  if self.waitForPreviousCommit is not None:
195
208
  self.waitForPreviousCommit()
196
209
 
210
+ # We are going to commit synchronously, so no need to clone a snapshot
211
+ # of the job description or mess with its version numbering.
212
+
197
213
  if not jobState:
198
214
  # All our operations that need committing are job state related
199
215
  return
200
216
 
201
217
  try:
202
- # Indicate any files that should be deleted once the update of
203
- # the job wrapper is completed.
218
+ # Indicate any files that should be seen as deleted once the
219
+ # update of the job description is visible.
220
+ if len(self.jobDesc.filesToDelete) > 0:
221
+ raise RuntimeError("Job is already in the process of being committed!")
204
222
  self.jobDesc.filesToDelete = list(self.filesToDelete)
205
223
  # Complete the job
206
224
  self.jobStore.update_job(self.jobDesc)
207
- # Delete any remnant jobs
208
- list(map(self.jobStore.delete_job, self.jobsToDelete))
209
225
  # Delete any remnant files
210
226
  list(map(self.jobStore.delete_file, self.filesToDelete))
211
227
  # Remove the files to delete list, having successfully removed the files
@@ -217,6 +233,7 @@ class NonCachingFileStore(AbstractFileStore):
217
233
  self._terminateEvent.set()
218
234
  raise
219
235
 
236
+
220
237
  def __del__(self) -> None:
221
238
  """
222
239
  Cleanup function that is run when destroying the class instance. Nothing to do since there
@@ -299,6 +316,10 @@ class NonCachingFileStore(AbstractFileStore):
299
316
  # This is a FileNotFoundError.
300
317
  # job finished & deleted its jobState file since the jobState files were discovered
301
318
  continue
319
+ elif e.errno == 5:
320
+ # This is a OSError: [Errno 5] Input/output error (jobStatefile seems to disappear
321
+ # on network file system sometimes)
322
+ continue
302
323
  else:
303
324
  raise
304
325
 
@@ -329,7 +350,10 @@ class NonCachingFileStore(AbstractFileStore):
329
350
  jobState = {'jobProcessName': get_process_name(self.coordination_dir),
330
351
  'jobName': self.jobName,
331
352
  'jobDir': self.localTempDir}
332
- (fd, jobStateFile) = tempfile.mkstemp(suffix='.jobState.tmp', dir=self.coordination_dir)
353
+ try:
354
+ (fd, jobStateFile) = tempfile.mkstemp(suffix='.jobState.tmp', dir=self.coordination_dir)
355
+ except Exception as e:
356
+ raise RuntimeError("Could not make state file in " + self.coordination_dir) from e
333
357
  with open(fd, 'wb') as fH:
334
358
  # Write data
335
359
  dill.dump(jobState, fH)