toil 8.0.0__py3-none-any.whl → 8.2.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 (270) hide show
  1. toil/__init__.py +4 -39
  2. toil/batchSystems/abstractBatchSystem.py +1 -1
  3. toil/batchSystems/abstractGridEngineBatchSystem.py +1 -1
  4. toil/batchSystems/awsBatch.py +1 -1
  5. toil/batchSystems/cleanup_support.py +1 -1
  6. toil/batchSystems/kubernetes.py +53 -7
  7. toil/batchSystems/local_support.py +1 -1
  8. toil/batchSystems/mesos/batchSystem.py +13 -8
  9. toil/batchSystems/mesos/test/__init__.py +3 -2
  10. toil/batchSystems/options.py +1 -0
  11. toil/batchSystems/singleMachine.py +1 -1
  12. toil/batchSystems/slurm.py +229 -84
  13. toil/bus.py +5 -3
  14. toil/common.py +198 -54
  15. toil/cwl/cwltoil.py +32 -11
  16. toil/job.py +110 -86
  17. toil/jobStores/abstractJobStore.py +24 -3
  18. toil/jobStores/aws/jobStore.py +46 -10
  19. toil/jobStores/fileJobStore.py +25 -1
  20. toil/jobStores/googleJobStore.py +104 -30
  21. toil/leader.py +9 -0
  22. toil/lib/accelerators.py +3 -1
  23. toil/lib/aws/session.py +14 -3
  24. toil/lib/aws/utils.py +92 -35
  25. toil/lib/aws/utils.py.orig +504 -0
  26. toil/lib/bioio.py +1 -1
  27. toil/lib/docker.py +252 -91
  28. toil/lib/dockstore.py +387 -0
  29. toil/lib/ec2nodes.py +3 -2
  30. toil/lib/exceptions.py +5 -3
  31. toil/lib/history.py +1345 -0
  32. toil/lib/history_submission.py +695 -0
  33. toil/lib/io.py +56 -23
  34. toil/lib/misc.py +25 -1
  35. toil/lib/resources.py +2 -1
  36. toil/lib/retry.py +10 -10
  37. toil/lib/threading.py +11 -10
  38. toil/lib/{integration.py → trs.py} +95 -46
  39. toil/lib/web.py +38 -0
  40. toil/options/common.py +25 -2
  41. toil/options/cwl.py +10 -0
  42. toil/options/wdl.py +11 -0
  43. toil/provisioners/gceProvisioner.py +4 -4
  44. toil/server/api_spec/LICENSE +201 -0
  45. toil/server/api_spec/README.rst +5 -0
  46. toil/server/cli/wes_cwl_runner.py +5 -4
  47. toil/server/utils.py +2 -3
  48. toil/statsAndLogging.py +35 -1
  49. toil/test/__init__.py +275 -115
  50. toil/test/batchSystems/batchSystemTest.py +227 -205
  51. toil/test/batchSystems/test_slurm.py +199 -2
  52. toil/test/cactus/pestis.tar.gz +0 -0
  53. toil/test/conftest.py +7 -0
  54. toil/test/cwl/2.fasta +11 -0
  55. toil/test/cwl/2.fastq +12 -0
  56. toil/test/cwl/conftest.py +39 -0
  57. toil/test/cwl/cwlTest.py +1015 -780
  58. toil/test/cwl/directory/directory/file.txt +15 -0
  59. toil/test/cwl/download_directory_file.json +4 -0
  60. toil/test/cwl/download_directory_s3.json +4 -0
  61. toil/test/cwl/download_file.json +6 -0
  62. toil/test/cwl/download_http.json +6 -0
  63. toil/test/cwl/download_https.json +6 -0
  64. toil/test/cwl/download_s3.json +6 -0
  65. toil/test/cwl/download_subdirectory_file.json +5 -0
  66. toil/test/cwl/download_subdirectory_s3.json +5 -0
  67. toil/test/cwl/empty.json +1 -0
  68. toil/test/cwl/mock_mpi/fake_mpi.yml +8 -0
  69. toil/test/cwl/mock_mpi/fake_mpi_run.py +42 -0
  70. toil/test/cwl/optional-file-exists.json +6 -0
  71. toil/test/cwl/optional-file-missing.json +6 -0
  72. toil/test/cwl/optional-file.cwl +18 -0
  73. toil/test/cwl/preemptible_expression.json +1 -0
  74. toil/test/cwl/revsort-job-missing.json +6 -0
  75. toil/test/cwl/revsort-job.json +6 -0
  76. toil/test/cwl/s3_secondary_file.json +16 -0
  77. toil/test/cwl/seqtk_seq_job.json +6 -0
  78. toil/test/cwl/stream.json +6 -0
  79. toil/test/cwl/test_filename_conflict_resolution.ms/table.dat +0 -0
  80. toil/test/cwl/test_filename_conflict_resolution.ms/table.f0 +0 -0
  81. toil/test/cwl/test_filename_conflict_resolution.ms/table.f1 +0 -0
  82. toil/test/cwl/test_filename_conflict_resolution.ms/table.f1i +0 -0
  83. toil/test/cwl/test_filename_conflict_resolution.ms/table.f2 +0 -0
  84. toil/test/cwl/test_filename_conflict_resolution.ms/table.f2_TSM0 +0 -0
  85. toil/test/cwl/test_filename_conflict_resolution.ms/table.f3 +0 -0
  86. toil/test/cwl/test_filename_conflict_resolution.ms/table.f3_TSM0 +0 -0
  87. toil/test/cwl/test_filename_conflict_resolution.ms/table.f4 +0 -0
  88. toil/test/cwl/test_filename_conflict_resolution.ms/table.f4_TSM0 +0 -0
  89. toil/test/cwl/test_filename_conflict_resolution.ms/table.f5 +0 -0
  90. toil/test/cwl/test_filename_conflict_resolution.ms/table.info +0 -0
  91. toil/test/cwl/test_filename_conflict_resolution.ms/table.lock +0 -0
  92. toil/test/cwl/whale.txt +16 -0
  93. toil/test/docs/scripts/example_alwaysfail.py +38 -0
  94. toil/test/docs/scripts/example_alwaysfail_with_files.wdl +33 -0
  95. toil/test/docs/scripts/example_cachingbenchmark.py +117 -0
  96. toil/test/docs/scripts/stagingExampleFiles/in.txt +1 -0
  97. toil/test/docs/scripts/stagingExampleFiles/out.txt +2 -0
  98. toil/test/docs/scripts/tutorial_arguments.py +23 -0
  99. toil/test/docs/scripts/tutorial_debugging.patch +12 -0
  100. toil/test/docs/scripts/tutorial_debugging_hangs.wdl +126 -0
  101. toil/test/docs/scripts/tutorial_debugging_works.wdl +129 -0
  102. toil/test/docs/scripts/tutorial_docker.py +20 -0
  103. toil/test/docs/scripts/tutorial_dynamic.py +24 -0
  104. toil/test/docs/scripts/tutorial_encapsulation.py +28 -0
  105. toil/test/docs/scripts/tutorial_encapsulation2.py +29 -0
  106. toil/test/docs/scripts/tutorial_helloworld.py +15 -0
  107. toil/test/docs/scripts/tutorial_invokeworkflow.py +27 -0
  108. toil/test/docs/scripts/tutorial_invokeworkflow2.py +30 -0
  109. toil/test/docs/scripts/tutorial_jobfunctions.py +22 -0
  110. toil/test/docs/scripts/tutorial_managing.py +29 -0
  111. toil/test/docs/scripts/tutorial_managing2.py +56 -0
  112. toil/test/docs/scripts/tutorial_multiplejobs.py +25 -0
  113. toil/test/docs/scripts/tutorial_multiplejobs2.py +21 -0
  114. toil/test/docs/scripts/tutorial_multiplejobs3.py +22 -0
  115. toil/test/docs/scripts/tutorial_promises.py +25 -0
  116. toil/test/docs/scripts/tutorial_promises2.py +30 -0
  117. toil/test/docs/scripts/tutorial_quickstart.py +22 -0
  118. toil/test/docs/scripts/tutorial_requirements.py +44 -0
  119. toil/test/docs/scripts/tutorial_services.py +45 -0
  120. toil/test/docs/scripts/tutorial_staging.py +45 -0
  121. toil/test/docs/scripts/tutorial_stats.py +64 -0
  122. toil/test/lib/aws/test_iam.py +3 -1
  123. toil/test/lib/dockerTest.py +205 -122
  124. toil/test/lib/test_history.py +236 -0
  125. toil/test/lib/test_trs.py +161 -0
  126. toil/test/provisioners/aws/awsProvisionerTest.py +12 -9
  127. toil/test/provisioners/clusterTest.py +4 -4
  128. toil/test/provisioners/gceProvisionerTest.py +16 -14
  129. toil/test/sort/sort.py +4 -1
  130. toil/test/src/busTest.py +17 -17
  131. toil/test/src/deferredFunctionTest.py +145 -132
  132. toil/test/src/importExportFileTest.py +71 -63
  133. toil/test/src/jobEncapsulationTest.py +27 -28
  134. toil/test/src/jobServiceTest.py +149 -133
  135. toil/test/src/jobTest.py +219 -211
  136. toil/test/src/miscTests.py +66 -60
  137. toil/test/src/promisedRequirementTest.py +163 -169
  138. toil/test/src/regularLogTest.py +24 -24
  139. toil/test/src/resourceTest.py +82 -76
  140. toil/test/src/restartDAGTest.py +51 -47
  141. toil/test/src/resumabilityTest.py +24 -19
  142. toil/test/src/retainTempDirTest.py +60 -57
  143. toil/test/src/systemTest.py +17 -13
  144. toil/test/src/threadingTest.py +29 -32
  145. toil/test/utils/ABCWorkflowDebug/B_file.txt +1 -0
  146. toil/test/utils/ABCWorkflowDebug/debugWorkflow.py +204 -0
  147. toil/test/utils/ABCWorkflowDebug/mkFile.py +16 -0
  148. toil/test/utils/ABCWorkflowDebug/sleep.cwl +12 -0
  149. toil/test/utils/ABCWorkflowDebug/sleep.yaml +1 -0
  150. toil/test/utils/toilDebugTest.py +117 -102
  151. toil/test/utils/toilKillTest.py +54 -53
  152. toil/test/utils/utilsTest.py +303 -229
  153. toil/test/wdl/lint_error.wdl +9 -0
  154. toil/test/wdl/md5sum/empty_file.json +1 -0
  155. toil/test/wdl/md5sum/md5sum-gs.json +1 -0
  156. toil/test/wdl/md5sum/md5sum.1.0.wdl +32 -0
  157. toil/test/wdl/md5sum/md5sum.input +1 -0
  158. toil/test/wdl/md5sum/md5sum.json +1 -0
  159. toil/test/wdl/md5sum/md5sum.wdl +25 -0
  160. toil/test/wdl/miniwdl_self_test/inputs-namespaced.json +1 -0
  161. toil/test/wdl/miniwdl_self_test/inputs.json +1 -0
  162. toil/test/wdl/miniwdl_self_test/self_test.wdl +40 -0
  163. toil/test/wdl/standard_library/as_map.json +16 -0
  164. toil/test/wdl/standard_library/as_map_as_input.wdl +23 -0
  165. toil/test/wdl/standard_library/as_pairs.json +7 -0
  166. toil/test/wdl/standard_library/as_pairs_as_input.wdl +23 -0
  167. toil/test/wdl/standard_library/ceil.json +3 -0
  168. toil/test/wdl/standard_library/ceil_as_command.wdl +16 -0
  169. toil/test/wdl/standard_library/ceil_as_input.wdl +16 -0
  170. toil/test/wdl/standard_library/collect_by_key.json +1 -0
  171. toil/test/wdl/standard_library/collect_by_key_as_input.wdl +23 -0
  172. toil/test/wdl/standard_library/cross.json +11 -0
  173. toil/test/wdl/standard_library/cross_as_input.wdl +19 -0
  174. toil/test/wdl/standard_library/flatten.json +7 -0
  175. toil/test/wdl/standard_library/flatten_as_input.wdl +18 -0
  176. toil/test/wdl/standard_library/floor.json +3 -0
  177. toil/test/wdl/standard_library/floor_as_command.wdl +16 -0
  178. toil/test/wdl/standard_library/floor_as_input.wdl +16 -0
  179. toil/test/wdl/standard_library/keys.json +8 -0
  180. toil/test/wdl/standard_library/keys_as_input.wdl +24 -0
  181. toil/test/wdl/standard_library/length.json +7 -0
  182. toil/test/wdl/standard_library/length_as_input.wdl +16 -0
  183. toil/test/wdl/standard_library/length_as_input_with_map.json +7 -0
  184. toil/test/wdl/standard_library/length_as_input_with_map.wdl +17 -0
  185. toil/test/wdl/standard_library/length_invalid.json +3 -0
  186. toil/test/wdl/standard_library/range.json +3 -0
  187. toil/test/wdl/standard_library/range_0.json +3 -0
  188. toil/test/wdl/standard_library/range_as_input.wdl +17 -0
  189. toil/test/wdl/standard_library/range_invalid.json +3 -0
  190. toil/test/wdl/standard_library/read_boolean.json +3 -0
  191. toil/test/wdl/standard_library/read_boolean_as_command.wdl +17 -0
  192. toil/test/wdl/standard_library/read_float.json +3 -0
  193. toil/test/wdl/standard_library/read_float_as_command.wdl +17 -0
  194. toil/test/wdl/standard_library/read_int.json +3 -0
  195. toil/test/wdl/standard_library/read_int_as_command.wdl +17 -0
  196. toil/test/wdl/standard_library/read_json.json +3 -0
  197. toil/test/wdl/standard_library/read_json_as_output.wdl +31 -0
  198. toil/test/wdl/standard_library/read_lines.json +3 -0
  199. toil/test/wdl/standard_library/read_lines_as_output.wdl +31 -0
  200. toil/test/wdl/standard_library/read_map.json +3 -0
  201. toil/test/wdl/standard_library/read_map_as_output.wdl +31 -0
  202. toil/test/wdl/standard_library/read_string.json +3 -0
  203. toil/test/wdl/standard_library/read_string_as_command.wdl +17 -0
  204. toil/test/wdl/standard_library/read_tsv.json +3 -0
  205. toil/test/wdl/standard_library/read_tsv_as_output.wdl +31 -0
  206. toil/test/wdl/standard_library/round.json +3 -0
  207. toil/test/wdl/standard_library/round_as_command.wdl +16 -0
  208. toil/test/wdl/standard_library/round_as_input.wdl +16 -0
  209. toil/test/wdl/standard_library/size.json +3 -0
  210. toil/test/wdl/standard_library/size_as_command.wdl +17 -0
  211. toil/test/wdl/standard_library/size_as_output.wdl +36 -0
  212. toil/test/wdl/standard_library/stderr.json +3 -0
  213. toil/test/wdl/standard_library/stderr_as_output.wdl +30 -0
  214. toil/test/wdl/standard_library/stdout.json +3 -0
  215. toil/test/wdl/standard_library/stdout_as_output.wdl +30 -0
  216. toil/test/wdl/standard_library/sub.json +3 -0
  217. toil/test/wdl/standard_library/sub_as_input.wdl +17 -0
  218. toil/test/wdl/standard_library/sub_as_input_with_file.wdl +17 -0
  219. toil/test/wdl/standard_library/transpose.json +6 -0
  220. toil/test/wdl/standard_library/transpose_as_input.wdl +18 -0
  221. toil/test/wdl/standard_library/write_json.json +6 -0
  222. toil/test/wdl/standard_library/write_json_as_command.wdl +17 -0
  223. toil/test/wdl/standard_library/write_lines.json +7 -0
  224. toil/test/wdl/standard_library/write_lines_as_command.wdl +17 -0
  225. toil/test/wdl/standard_library/write_map.json +6 -0
  226. toil/test/wdl/standard_library/write_map_as_command.wdl +17 -0
  227. toil/test/wdl/standard_library/write_tsv.json +6 -0
  228. toil/test/wdl/standard_library/write_tsv_as_command.wdl +17 -0
  229. toil/test/wdl/standard_library/zip.json +12 -0
  230. toil/test/wdl/standard_library/zip_as_input.wdl +19 -0
  231. toil/test/wdl/test.csv +3 -0
  232. toil/test/wdl/test.tsv +3 -0
  233. toil/test/wdl/testfiles/croo.wdl +38 -0
  234. toil/test/wdl/testfiles/drop_files.wdl +62 -0
  235. toil/test/wdl/testfiles/drop_files_subworkflow.wdl +13 -0
  236. toil/test/wdl/testfiles/empty.txt +0 -0
  237. toil/test/wdl/testfiles/not_enough_outputs.wdl +33 -0
  238. toil/test/wdl/testfiles/random.wdl +66 -0
  239. toil/test/wdl/testfiles/string_file_coercion.json +1 -0
  240. toil/test/wdl/testfiles/string_file_coercion.wdl +35 -0
  241. toil/test/wdl/testfiles/test.json +4 -0
  242. toil/test/wdl/testfiles/test_boolean.txt +1 -0
  243. toil/test/wdl/testfiles/test_float.txt +1 -0
  244. toil/test/wdl/testfiles/test_int.txt +1 -0
  245. toil/test/wdl/testfiles/test_lines.txt +5 -0
  246. toil/test/wdl/testfiles/test_map.txt +2 -0
  247. toil/test/wdl/testfiles/test_string.txt +1 -0
  248. toil/test/wdl/testfiles/url_to_file.wdl +13 -0
  249. toil/test/wdl/testfiles/url_to_optional_file.wdl +13 -0
  250. toil/test/wdl/testfiles/vocab.json +1 -0
  251. toil/test/wdl/testfiles/vocab.wdl +66 -0
  252. toil/test/wdl/testfiles/wait.wdl +34 -0
  253. toil/test/wdl/wdl_specification/type_pair.json +23 -0
  254. toil/test/wdl/wdl_specification/type_pair_basic.wdl +36 -0
  255. toil/test/wdl/wdl_specification/type_pair_with_files.wdl +36 -0
  256. toil/test/wdl/wdl_specification/v1_spec.json +1 -0
  257. toil/test/wdl/wdl_specification/v1_spec_declaration.wdl +39 -0
  258. toil/test/wdl/wdltoil_test.py +681 -408
  259. toil/test/wdl/wdltoil_test_kubernetes.py +2 -2
  260. toil/version.py +10 -10
  261. toil/wdl/wdltoil.py +350 -123
  262. toil/worker.py +113 -33
  263. {toil-8.0.0.dist-info → toil-8.2.0.dist-info}/METADATA +13 -7
  264. toil-8.2.0.dist-info/RECORD +439 -0
  265. {toil-8.0.0.dist-info → toil-8.2.0.dist-info}/WHEEL +1 -1
  266. toil/test/lib/test_integration.py +0 -104
  267. toil-8.0.0.dist-info/RECORD +0 -253
  268. {toil-8.0.0.dist-info → toil-8.2.0.dist-info}/entry_points.txt +0 -0
  269. {toil-8.0.0.dist-info → toil-8.2.0.dist-info/licenses}/LICENSE +0 -0
  270. {toil-8.0.0.dist-info → toil-8.2.0.dist-info}/top_level.txt +0 -0
@@ -1,17 +1,24 @@
1
+ import errno
1
2
  import textwrap
2
3
  from queue import Queue
3
4
 
5
+ import logging
4
6
  import pytest
7
+ import sys
5
8
 
6
9
  import toil.batchSystems.slurm
7
10
  from toil.batchSystems.abstractBatchSystem import (
8
11
  EXIT_STATUS_UNAVAILABLE_VALUE,
9
12
  BatchJobExitReason,
13
+ BatchSystemSupport,
10
14
  )
11
15
  from toil.common import Config
12
16
  from toil.lib.misc import CalledProcessErrorStderr
13
17
  from toil.test import ToilTest
14
18
 
19
+ logger = logging.getLogger(__name__)
20
+
21
+
15
22
  # TODO: Come up with a better way to mock the commands then monkey-patching the
16
23
  # command-calling functions.
17
24
 
@@ -29,6 +36,9 @@ def call_sacct(args, **_) -> str:
29
36
  1236|FAILED|0:2
30
37
  1236.extern|COMPLETED|0:0
31
38
  """
39
+ if sum(len(a) for a in args) > 1000:
40
+ # Simulate if the argument list is too long
41
+ raise OSError(errno.E2BIG, "Argument list is too long")
32
42
  # Fake output per fake job-id.
33
43
  sacct_info = {
34
44
  609663: "609663|FAILED|0:2\n609663.extern|COMPLETED|0:0\n",
@@ -173,14 +183,34 @@ def call_sacct_raises(*_):
173
183
  1, "sacct: error: Problem talking to the database: " "Connection timed out"
174
184
  )
175
185
 
186
+ def call_sinfo(*_) -> str:
187
+ """
188
+ Simulate asking for partition info from Slurm
189
+ """
190
+ stdout = textwrap.dedent(
191
+ """\
192
+ PARTITION GRES TIMELIMIT PRIO_TIER CPUS MEMORY
193
+ short* (null) 1:00:00 500 256+ 1996800+
194
+ medium (null) 12:00:00 500 256+ 1996800+
195
+ long (null) 14-00:00:00 500 256+ 1996800+
196
+ gpu gpu:A100:8 7-00:00:00 5000 256 996800
197
+ gpu gpu:A5500:8 7-00:00:00 5000 256 1996800
198
+ high_priority gpu:A5500:8 7-00:00:00 65000 256 1996800
199
+ high_priority (null) 7-00:00:00 65000 256+ 1996800+
200
+ simple_nodelist gpu:A100:8 1:00 65000 256 996800
201
+ simple_nodelist gpu:A5500:8 1:00 65000 256 1996800
202
+ simple_nodelist (null) 1:00 65000 256+ 1996800+
203
+ """
204
+ )
205
+ return stdout
176
206
 
177
- class FakeBatchSystem:
207
+ class FakeBatchSystem(BatchSystemSupport):
178
208
  """
179
209
  Class that implements a minimal Batch System, needed to create a Worker (see below).
180
210
  """
181
211
 
182
212
  def __init__(self):
183
- self.config = self.__fake_config()
213
+ super().__init__(self.__fake_config(), float("inf"), sys.maxsize, sys.maxsize)
184
214
 
185
215
  def getWaitDuration(self):
186
216
  return 10
@@ -198,8 +228,12 @@ class FakeBatchSystem:
198
228
 
199
229
  config.workflowID = str(uuid4())
200
230
  config.cleanWorkDir = "always"
231
+ toil.batchSystems.slurm.SlurmBatchSystem.setOptions(lambda o: setattr(config, o, None))
201
232
  return config
202
233
 
234
+ # Make the mock class not have abstract methods anymore, even though we don't
235
+ # implement them. See <https://stackoverflow.com/a/17345619>.
236
+ FakeBatchSystem.__abstractmethods__ = set()
203
237
 
204
238
  class SlurmTest(ToilTest):
205
239
  """
@@ -262,6 +296,13 @@ class SlurmTest(ToilTest):
262
296
  result = self.worker._getJobDetailsFromSacct(list(expected_result))
263
297
  assert result == expected_result, f"{result} != {expected_result}"
264
298
 
299
+ def test_getJobDetailsFromSacct_argument_list_too_big(self):
300
+ self.monkeypatch.setattr(toil.batchSystems.slurm, "call_command", call_sacct)
301
+ expected_result = {i: (None, None) for i in range(2000)}
302
+ result = self.worker._getJobDetailsFromSacct(list(expected_result))
303
+ assert result == expected_result, f"{result} != {expected_result}"
304
+
305
+
265
306
  ####
266
307
  #### tests for _getJobDetailsFromScontrol()
267
308
  ####
@@ -449,3 +490,159 @@ class SlurmTest(ToilTest):
449
490
  pass
450
491
  else:
451
492
  assert False, "Exception CalledProcessErrorStderr not raised"
493
+
494
+ ###
495
+ ### Tests for partition selection
496
+ ##
497
+
498
+ def test_PartitionSet_get_partition(self):
499
+ self.monkeypatch.setattr(toil.batchSystems.slurm, "call_command", call_sinfo)
500
+ ps = toil.batchSystems.slurm.SlurmBatchSystem.PartitionSet()
501
+
502
+ # At zero. short will win because simple_nodelist has higher priority.
503
+ self.assertEqual(ps.get_partition(0), "short")
504
+ # Easily within the partition
505
+ self.assertEqual(ps.get_partition(10 * 60), "short")
506
+ # Exactly on the boundary
507
+ self.assertEqual(ps.get_partition(60 * 60), "short")
508
+ # Well within the next partition
509
+ self.assertEqual(ps.get_partition(2 * 60 * 60), "medium")
510
+ # Can only fit in long
511
+ self.assertEqual(ps.get_partition(8 * 24 * 60 * 60), "long")
512
+ # Could fit in gpu or long
513
+ self.assertEqual(ps.get_partition(6 * 24 * 60 * 60), "long")
514
+ # Can't fit in anything
515
+ with self.assertRaises(Exception):
516
+ ps.get_partition(365 * 24 * 60 * 60)
517
+
518
+ def test_PartitionSet_default_gpu_partition(self):
519
+ self.monkeypatch.setattr(toil.batchSystems.slurm, "call_command", call_sinfo)
520
+ ps = toil.batchSystems.slurm.SlurmBatchSystem.PartitionSet()
521
+
522
+ # Make sure we picked the useful-length GPU partition and not the super
523
+ # short one.
524
+ self.assertEqual(ps.default_gpu_partition.partition_name, "gpu")
525
+
526
+ def test_prepareSbatch_partition(self):
527
+ self.monkeypatch.setattr(toil.batchSystems.slurm, "call_command", call_sinfo)
528
+ ps = toil.batchSystems.slurm.SlurmBatchSystem.PartitionSet()
529
+ self.worker.boss.partitions = ps
530
+ # This is in seconds
531
+ self.worker.boss.config.slurm_time = 30
532
+
533
+ # Without a partition override in the environment, we should get the
534
+ # "short" partition for this job
535
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
536
+ assert "--partition=short" in command
537
+
538
+ # With a partition override, we should not. But the override will be rewritten.
539
+ self.worker.boss.config.slurm_args = "--something --partition foo --somethingElse"
540
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
541
+ assert "--partition=short" not in command
542
+ assert "--partition=foo" in command
543
+
544
+ # All ways of setting partition should work, including =
545
+ self.worker.boss.config.slurm_args = "--something --partition=foo --somethingElse"
546
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
547
+ assert "--partition=short" not in command
548
+ assert "--partition=foo" in command
549
+
550
+ # And short options
551
+ self.worker.boss.config.slurm_args = "--something -p foo --somethingElse"
552
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
553
+ assert "--partition=short" not in command
554
+ assert "--partition=foo" in command
555
+
556
+ # Partition settings from the config should override automatic selection
557
+ self.worker.boss.config.slurm_partition = "foobar"
558
+ self.worker.boss.config.slurm_args = "--something --somethingElse"
559
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
560
+ assert "--partition=foobar" in command
561
+
562
+ # But they should be overridden by the argument overrides
563
+ self.worker.boss.config.slurm_args = "--something --partition=baz --somethingElse"
564
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
565
+ assert "--partition=baz" in command
566
+
567
+ def test_prepareSbatch_time(self):
568
+ self.monkeypatch.setattr(toil.batchSystems.slurm, "call_command", call_sinfo)
569
+ ps = toil.batchSystems.slurm.SlurmBatchSystem.PartitionSet()
570
+ self.worker.boss.partitions = ps
571
+ # This is in seconds
572
+ self.worker.boss.config.slurm_time = 30
573
+
574
+ # Without a time override in the environment, we should use the normal
575
+ # time and the "short" partition
576
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
577
+ logger.debug("Command: %s", command)
578
+ assert "--time=0:30" in command
579
+ assert "--partition=short" in command
580
+
581
+ # With a time override, we should use it, slightly translated, and it
582
+ # should change the selected partition.
583
+ self.worker.boss.config.slurm_args = "--something --time 10:00:00 --somethingElse"
584
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
585
+ logger.debug("Command: %s", command)
586
+ assert "--partition=medium" in command
587
+ assert "--time=0:36000" in command
588
+
589
+ # All ways of setting time should work, including =
590
+ self.worker.boss.config.slurm_args = "--something --time=10:00:00 --somethingElse"
591
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
592
+ logger.debug("Command: %s", command)
593
+ assert "--partition=medium" in command
594
+ assert "--time=0:36000" in command
595
+
596
+ # And short options
597
+ self.worker.boss.config.slurm_args = "--something -t 10:00:00 --somethingElse"
598
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
599
+ logger.debug("Command: %s", command)
600
+ assert "--partition=medium" in command
601
+ assert "--time=0:36000" in command
602
+
603
+ def test_prepareSbatch_export(self):
604
+ self.monkeypatch.setattr(toil.batchSystems.slurm, "call_command", call_sinfo)
605
+ ps = toil.batchSystems.slurm.SlurmBatchSystem.PartitionSet()
606
+ self.worker.boss.partitions = ps
607
+
608
+ # Without any overrides, we need --export=ALL
609
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
610
+ assert "--export=ALL" in command
611
+
612
+ # With overrides, we don't get --export=ALL
613
+ self.worker.boss.config.slurm_args = "--export=foo"
614
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
615
+ assert "--export=ALL" not in command
616
+
617
+ # With --export-file, we don't get --export=ALL as documented.
618
+ self.worker.boss.config.slurm_args = "--export-file=./thefile.txt"
619
+ command = self.worker.prepareSbatch(1, 100, 5, "job5", None, None)
620
+ assert "--export=ALL" not in command
621
+
622
+ def test_option_detector(self):
623
+ detector = toil.batchSystems.slurm.option_detector("foobar", "f")
624
+
625
+ self.assertTrue(detector("--foobar"))
626
+ self.assertTrue(detector("--foobar=1"))
627
+ self.assertTrue(detector("-f"))
628
+ self.assertFalse(detector("-F"))
629
+ self.assertFalse(detector("--foo-bar"))
630
+ self.assertFalse(detector("foobar"))
631
+ self.assertFalse(detector("-foobar"))
632
+ self.assertFalse(detector("f"))
633
+
634
+ def test_any_option_detector(self):
635
+ detector = toil.batchSystems.slurm.any_option_detector([])
636
+ self.assertFalse(detector("--anything"))
637
+
638
+ detector = toil.batchSystems.slurm.any_option_detector([("foobar", "f"), "many-bothans", ("bazz-only", "B")])
639
+
640
+ self.assertTrue(detector("--foobar"))
641
+ self.assertTrue(detector("-f"))
642
+ self.assertTrue(detector("--many-bothans=False"))
643
+ self.assertTrue(detector("--bazz-only"))
644
+ self.assertTrue(detector("-B"))
645
+ self.assertFalse(detector("--no-bazz"))
646
+ self.assertFalse(detector("--foo-bar=--bazz-only"))
647
+
648
+
Binary file
toil/test/conftest.py ADDED
@@ -0,0 +1,7 @@
1
+ import pytest
2
+
3
+
4
+ @pytest.fixture(scope="class")
5
+ def rootpath(request: pytest.FixtureRequest) -> None:
6
+ """Records the rootpath at the class level, for use on a unittest.TestCase."""
7
+ request.cls._rootpath = request.config._rootpath
toil/test/cwl/2.fasta ADDED
@@ -0,0 +1,11 @@
1
+ >Sequence 561 BP; 135 A; 106 C; 98 G; 222 T; 0 other;
2
+ gttcgatgcc taaaatacct tcttttgtcc ctacacagac cacagttttc ctaatggctt
3
+ tacaccgact agaaattctt gtgcaagcac taattgaaag cggttggcct agagtgttac
4
+ cggtttgtat agctgagcgc gtctcttgcc ctgatcaaag gttcattttc tctactttgg
5
+ aagacgttgt ggaagaatac aacaagtacg agtctctccc ccctggtttg ctgattactg
6
+ gatacagttg taataccctt cgcaacaccg cgtaactatc tatatgaatt attttccctt
7
+ tattatatgt agtaggttcg tctttaatct tcctttagca agtcttttac tgttttcgac
8
+ ctcaatgttc atgttcttag gttgttttgg ataatatgcg gtcagtttaa tcttcgttgt
9
+ ttcttcttaa aatatttatt catggtttaa tttttggttt gtacttgttc aggggccagt
10
+ tcattattta ctctgtttgt atacagcagt tcttttattt ttagtatgat tttaatttaa
11
+ aacaattcta atggtcaaaa a
toil/test/cwl/2.fastq ADDED
@@ -0,0 +1,12 @@
1
+ @EAS54_6_R1_2_1_413_324
2
+ CCCTTCTTGTCTTCAGCGTTTCTCC
3
+ +
4
+ ;;3;;;;;;;;;;;;7;;;;;;;88
5
+ @EAS54_6_R1_2_1_540_792
6
+ TTGGCAGGCCAAGGCCGATGGATCA
7
+ +
8
+ ;;;;;;;;;;;7;;;;;-;;;3;83
9
+ @EAS54_6_R1_2_1_443_348
10
+ GTTGCTTCTGGCGTGGGTGGGGGGG
11
+ +EAS54_6_R1_2_1_443_348
12
+ ;;;;;;;;;;;9;7;;.7;393333
toil/test/cwl/conftest.py CHANGED
@@ -14,4 +14,43 @@
14
14
 
15
15
  # https://pytest.org/latest/example/pythoncollection.html
16
16
 
17
+ import json
18
+ import logging
19
+ from io import StringIO
20
+ from typing import Any, Dict, List, Optional, Tuple
21
+
22
+ from cwltest import utils
23
+ logger = logging.getLogger(__name__)
24
+
17
25
  collect_ignore = ["spec"]
26
+
27
+
28
+ # Hook into Pytest for testing CWL conformance with Toil
29
+ # https://pytest.org/en/6.2.x/writing_plugins.html?highlight=conftest#conftest-py-local-per-directory-plugins
30
+ # See cwltool's reference implementation:
31
+ # https://github.com/common-workflow-language/cwltool/blob/05af6c1357c327b3146e9f5da40e7c0aa3e6d976/tests/cwl-conformance/cwltool-conftest.py
32
+ def pytest_cwl_execute_test(
33
+ config: utils.CWLTestConfig,
34
+ processfile: str,
35
+ jobfile: Optional[str]
36
+ ) -> Tuple[int, Optional[Dict[str, Any]]]:
37
+ """Use Toil to execute CWL tests (equivalent to running toil-cwl-runner)."""
38
+ from toil.cwl.cwltoil import main
39
+
40
+ stdout = StringIO()
41
+ argsl: List[str] = [f"--outdir={config.outdir}"]
42
+ if config.runner_quiet:
43
+ argsl.append("--quiet")
44
+ elif config.verbose:
45
+ argsl.append("--debug")
46
+ argsl.extend(config.args)
47
+ argsl.append(processfile)
48
+ if jobfile:
49
+ argsl.append(jobfile)
50
+ try:
51
+ result = main(args=argsl, stdout=stdout)
52
+ except Exception as e:
53
+ logger.error(e)
54
+ return 1, {}
55
+ out = stdout.getvalue()
56
+ return result, json.loads(out) if out else {}