toil 8.1.0b1__py3-none-any.whl → 9.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 (275) hide show
  1. toil/__init__.py +0 -35
  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/registry.py +15 -118
  11. toil/batchSystems/singleMachine.py +1 -1
  12. toil/batchSystems/slurm.py +27 -26
  13. toil/bus.py +5 -3
  14. toil/common.py +59 -12
  15. toil/cwl/cwltoil.py +81 -38
  16. toil/cwl/utils.py +103 -3
  17. toil/job.py +64 -49
  18. toil/jobStores/abstractJobStore.py +35 -239
  19. toil/jobStores/aws/jobStore.py +2 -1
  20. toil/jobStores/fileJobStore.py +27 -2
  21. toil/jobStores/googleJobStore.py +110 -33
  22. toil/leader.py +9 -0
  23. toil/lib/accelerators.py +4 -2
  24. toil/lib/aws/utils.py.orig +504 -0
  25. toil/lib/bioio.py +1 -1
  26. toil/lib/docker.py +252 -91
  27. toil/lib/dockstore.py +11 -3
  28. toil/lib/exceptions.py +5 -3
  29. toil/lib/generatedEC2Lists.py +81 -19
  30. toil/lib/history.py +87 -13
  31. toil/lib/history_submission.py +23 -9
  32. toil/lib/io.py +34 -22
  33. toil/lib/misc.py +8 -2
  34. toil/lib/plugins.py +106 -0
  35. toil/lib/resources.py +2 -1
  36. toil/lib/threading.py +11 -10
  37. toil/lib/url.py +320 -0
  38. toil/options/common.py +8 -0
  39. toil/options/cwl.py +13 -1
  40. toil/options/runner.py +17 -10
  41. toil/options/wdl.py +22 -0
  42. toil/provisioners/aws/awsProvisioner.py +25 -2
  43. toil/server/api_spec/LICENSE +201 -0
  44. toil/server/api_spec/README.rst +5 -0
  45. toil/server/app.py +12 -6
  46. toil/server/cli/wes_cwl_runner.py +3 -2
  47. toil/server/wes/abstract_backend.py +21 -43
  48. toil/server/wes/toil_backend.py +2 -2
  49. toil/test/__init__.py +275 -115
  50. toil/test/batchSystems/batchSystemTest.py +228 -213
  51. toil/test/batchSystems/batch_system_plugin_test.py +7 -0
  52. toil/test/batchSystems/test_slurm.py +27 -0
  53. toil/test/cactus/pestis.tar.gz +0 -0
  54. toil/test/conftest.py +7 -0
  55. toil/test/cwl/2.fasta +11 -0
  56. toil/test/cwl/2.fastq +12 -0
  57. toil/test/cwl/conftest.py +1 -1
  58. toil/test/cwl/cwlTest.py +1175 -870
  59. toil/test/cwl/directory/directory/file.txt +15 -0
  60. toil/test/cwl/download_directory_file.json +4 -0
  61. toil/test/cwl/download_directory_s3.json +4 -0
  62. toil/test/cwl/download_file.json +6 -0
  63. toil/test/cwl/download_http.json +6 -0
  64. toil/test/cwl/download_https.json +6 -0
  65. toil/test/cwl/download_s3.json +6 -0
  66. toil/test/cwl/download_subdirectory_file.json +5 -0
  67. toil/test/cwl/download_subdirectory_s3.json +5 -0
  68. toil/test/cwl/empty.json +1 -0
  69. toil/test/cwl/mock_mpi/fake_mpi.yml +8 -0
  70. toil/test/cwl/mock_mpi/fake_mpi_run.py +42 -0
  71. toil/test/cwl/optional-file-exists.json +6 -0
  72. toil/test/cwl/optional-file-missing.json +6 -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/docs/scriptsTest.py +2 -1
  123. toil/test/lib/aws/test_iam.py +3 -1
  124. toil/test/lib/dockerTest.py +205 -122
  125. toil/test/lib/test_history.py +101 -77
  126. toil/test/lib/test_url.py +69 -0
  127. toil/test/lib/url_plugin_test.py +105 -0
  128. toil/test/provisioners/aws/awsProvisionerTest.py +13 -10
  129. toil/test/provisioners/clusterTest.py +17 -4
  130. toil/test/provisioners/gceProvisionerTest.py +17 -15
  131. toil/test/server/serverTest.py +78 -36
  132. toil/test/sort/sort.py +4 -1
  133. toil/test/src/busTest.py +17 -17
  134. toil/test/src/deferredFunctionTest.py +145 -132
  135. toil/test/src/importExportFileTest.py +71 -63
  136. toil/test/src/jobEncapsulationTest.py +27 -28
  137. toil/test/src/jobServiceTest.py +149 -133
  138. toil/test/src/jobTest.py +219 -211
  139. toil/test/src/miscTests.py +66 -60
  140. toil/test/src/promisedRequirementTest.py +163 -169
  141. toil/test/src/regularLogTest.py +24 -24
  142. toil/test/src/resourceTest.py +82 -76
  143. toil/test/src/restartDAGTest.py +51 -47
  144. toil/test/src/resumabilityTest.py +24 -19
  145. toil/test/src/retainTempDirTest.py +60 -57
  146. toil/test/src/systemTest.py +17 -13
  147. toil/test/src/threadingTest.py +29 -32
  148. toil/test/utils/ABCWorkflowDebug/B_file.txt +1 -0
  149. toil/test/utils/ABCWorkflowDebug/debugWorkflow.py +204 -0
  150. toil/test/utils/ABCWorkflowDebug/mkFile.py +16 -0
  151. toil/test/utils/ABCWorkflowDebug/sleep.cwl +12 -0
  152. toil/test/utils/ABCWorkflowDebug/sleep.yaml +1 -0
  153. toil/test/utils/toilDebugTest.py +117 -102
  154. toil/test/utils/toilKillTest.py +54 -53
  155. toil/test/utils/utilsTest.py +303 -229
  156. toil/test/wdl/lint_error.wdl +9 -0
  157. toil/test/wdl/md5sum/empty_file.json +1 -0
  158. toil/test/wdl/md5sum/md5sum-gs.json +1 -0
  159. toil/test/wdl/md5sum/md5sum.1.0.wdl +32 -0
  160. toil/test/wdl/md5sum/md5sum.input +1 -0
  161. toil/test/wdl/md5sum/md5sum.json +1 -0
  162. toil/test/wdl/md5sum/md5sum.wdl +25 -0
  163. toil/test/wdl/miniwdl_self_test/inputs-namespaced.json +1 -0
  164. toil/test/wdl/miniwdl_self_test/inputs.json +1 -0
  165. toil/test/wdl/miniwdl_self_test/self_test.wdl +40 -0
  166. toil/test/wdl/standard_library/as_map.json +16 -0
  167. toil/test/wdl/standard_library/as_map_as_input.wdl +23 -0
  168. toil/test/wdl/standard_library/as_pairs.json +7 -0
  169. toil/test/wdl/standard_library/as_pairs_as_input.wdl +23 -0
  170. toil/test/wdl/standard_library/ceil.json +3 -0
  171. toil/test/wdl/standard_library/ceil_as_command.wdl +16 -0
  172. toil/test/wdl/standard_library/ceil_as_input.wdl +16 -0
  173. toil/test/wdl/standard_library/collect_by_key.json +1 -0
  174. toil/test/wdl/standard_library/collect_by_key_as_input.wdl +23 -0
  175. toil/test/wdl/standard_library/cross.json +11 -0
  176. toil/test/wdl/standard_library/cross_as_input.wdl +19 -0
  177. toil/test/wdl/standard_library/flatten.json +7 -0
  178. toil/test/wdl/standard_library/flatten_as_input.wdl +18 -0
  179. toil/test/wdl/standard_library/floor.json +3 -0
  180. toil/test/wdl/standard_library/floor_as_command.wdl +16 -0
  181. toil/test/wdl/standard_library/floor_as_input.wdl +16 -0
  182. toil/test/wdl/standard_library/keys.json +8 -0
  183. toil/test/wdl/standard_library/keys_as_input.wdl +24 -0
  184. toil/test/wdl/standard_library/length.json +7 -0
  185. toil/test/wdl/standard_library/length_as_input.wdl +16 -0
  186. toil/test/wdl/standard_library/length_as_input_with_map.json +7 -0
  187. toil/test/wdl/standard_library/length_as_input_with_map.wdl +17 -0
  188. toil/test/wdl/standard_library/length_invalid.json +3 -0
  189. toil/test/wdl/standard_library/range.json +3 -0
  190. toil/test/wdl/standard_library/range_0.json +3 -0
  191. toil/test/wdl/standard_library/range_as_input.wdl +17 -0
  192. toil/test/wdl/standard_library/range_invalid.json +3 -0
  193. toil/test/wdl/standard_library/read_boolean.json +3 -0
  194. toil/test/wdl/standard_library/read_boolean_as_command.wdl +17 -0
  195. toil/test/wdl/standard_library/read_float.json +3 -0
  196. toil/test/wdl/standard_library/read_float_as_command.wdl +17 -0
  197. toil/test/wdl/standard_library/read_int.json +3 -0
  198. toil/test/wdl/standard_library/read_int_as_command.wdl +17 -0
  199. toil/test/wdl/standard_library/read_json.json +3 -0
  200. toil/test/wdl/standard_library/read_json_as_output.wdl +31 -0
  201. toil/test/wdl/standard_library/read_lines.json +3 -0
  202. toil/test/wdl/standard_library/read_lines_as_output.wdl +31 -0
  203. toil/test/wdl/standard_library/read_map.json +3 -0
  204. toil/test/wdl/standard_library/read_map_as_output.wdl +31 -0
  205. toil/test/wdl/standard_library/read_string.json +3 -0
  206. toil/test/wdl/standard_library/read_string_as_command.wdl +17 -0
  207. toil/test/wdl/standard_library/read_tsv.json +3 -0
  208. toil/test/wdl/standard_library/read_tsv_as_output.wdl +31 -0
  209. toil/test/wdl/standard_library/round.json +3 -0
  210. toil/test/wdl/standard_library/round_as_command.wdl +16 -0
  211. toil/test/wdl/standard_library/round_as_input.wdl +16 -0
  212. toil/test/wdl/standard_library/size.json +3 -0
  213. toil/test/wdl/standard_library/size_as_command.wdl +17 -0
  214. toil/test/wdl/standard_library/size_as_output.wdl +36 -0
  215. toil/test/wdl/standard_library/stderr.json +3 -0
  216. toil/test/wdl/standard_library/stderr_as_output.wdl +30 -0
  217. toil/test/wdl/standard_library/stdout.json +3 -0
  218. toil/test/wdl/standard_library/stdout_as_output.wdl +30 -0
  219. toil/test/wdl/standard_library/sub.json +3 -0
  220. toil/test/wdl/standard_library/sub_as_input.wdl +17 -0
  221. toil/test/wdl/standard_library/sub_as_input_with_file.wdl +17 -0
  222. toil/test/wdl/standard_library/transpose.json +6 -0
  223. toil/test/wdl/standard_library/transpose_as_input.wdl +18 -0
  224. toil/test/wdl/standard_library/write_json.json +6 -0
  225. toil/test/wdl/standard_library/write_json_as_command.wdl +17 -0
  226. toil/test/wdl/standard_library/write_lines.json +7 -0
  227. toil/test/wdl/standard_library/write_lines_as_command.wdl +17 -0
  228. toil/test/wdl/standard_library/write_map.json +6 -0
  229. toil/test/wdl/standard_library/write_map_as_command.wdl +17 -0
  230. toil/test/wdl/standard_library/write_tsv.json +6 -0
  231. toil/test/wdl/standard_library/write_tsv_as_command.wdl +17 -0
  232. toil/test/wdl/standard_library/zip.json +12 -0
  233. toil/test/wdl/standard_library/zip_as_input.wdl +19 -0
  234. toil/test/wdl/test.csv +3 -0
  235. toil/test/wdl/test.tsv +3 -0
  236. toil/test/wdl/testfiles/croo.wdl +38 -0
  237. toil/test/wdl/testfiles/drop_files.wdl +62 -0
  238. toil/test/wdl/testfiles/drop_files_subworkflow.wdl +13 -0
  239. toil/test/wdl/testfiles/empty.txt +0 -0
  240. toil/test/wdl/testfiles/not_enough_outputs.wdl +33 -0
  241. toil/test/wdl/testfiles/random.wdl +66 -0
  242. toil/test/wdl/testfiles/read_file.wdl +18 -0
  243. toil/test/wdl/testfiles/string_file_coercion.json +1 -0
  244. toil/test/wdl/testfiles/string_file_coercion.wdl +35 -0
  245. toil/test/wdl/testfiles/test.json +4 -0
  246. toil/test/wdl/testfiles/test_boolean.txt +1 -0
  247. toil/test/wdl/testfiles/test_float.txt +1 -0
  248. toil/test/wdl/testfiles/test_int.txt +1 -0
  249. toil/test/wdl/testfiles/test_lines.txt +5 -0
  250. toil/test/wdl/testfiles/test_map.txt +2 -0
  251. toil/test/wdl/testfiles/test_string.txt +1 -0
  252. toil/test/wdl/testfiles/url_to_file.wdl +13 -0
  253. toil/test/wdl/testfiles/url_to_optional_file.wdl +14 -0
  254. toil/test/wdl/testfiles/vocab.json +1 -0
  255. toil/test/wdl/testfiles/vocab.wdl +66 -0
  256. toil/test/wdl/testfiles/wait.wdl +34 -0
  257. toil/test/wdl/wdl_specification/type_pair.json +23 -0
  258. toil/test/wdl/wdl_specification/type_pair_basic.wdl +36 -0
  259. toil/test/wdl/wdl_specification/type_pair_with_files.wdl +36 -0
  260. toil/test/wdl/wdl_specification/v1_spec.json +1 -0
  261. toil/test/wdl/wdl_specification/v1_spec_declaration.wdl +39 -0
  262. toil/test/wdl/wdltoil_test.py +751 -529
  263. toil/test/wdl/wdltoil_test_kubernetes.py +2 -2
  264. toil/utils/toilSshCluster.py +23 -0
  265. toil/utils/toilUpdateEC2Instances.py +1 -0
  266. toil/version.py +5 -5
  267. toil/wdl/wdltoil.py +518 -437
  268. toil/worker.py +11 -6
  269. {toil-8.1.0b1.dist-info → toil-9.0.0.dist-info}/METADATA +25 -24
  270. toil-9.0.0.dist-info/RECORD +444 -0
  271. {toil-8.1.0b1.dist-info → toil-9.0.0.dist-info}/WHEEL +1 -1
  272. toil-8.1.0b1.dist-info/RECORD +0 -259
  273. {toil-8.1.0b1.dist-info → toil-9.0.0.dist-info}/entry_points.txt +0 -0
  274. {toil-8.1.0b1.dist-info → toil-9.0.0.dist-info/licenses}/LICENSE +0 -0
  275. {toil-8.1.0b1.dist-info → toil-9.0.0.dist-info}/top_level.txt +0 -0
@@ -33,7 +33,7 @@ except ImportError:
33
33
  # extra wasn't installed. We'll then skip them all.
34
34
  pass
35
35
 
36
- from toil.test import ToilTest, needs_aws_s3, needs_celery_broker, needs_server
36
+ from toil.test import ToilTest, needs_aws_s3, needs_celery_broker, needs_cwl, needs_server, integrative
37
37
 
38
38
  logger = logging.getLogger(__name__)
39
39
  logging.basicConfig(level=logging.INFO)
@@ -185,6 +185,7 @@ class FileStateStoreURLTest(hidden.AbstractStateStoreTest):
185
185
 
186
186
 
187
187
  @needs_aws_s3
188
+ @integrative
188
189
  class BucketUsingTest(ToilTest):
189
190
  """
190
191
  Base class for tests that need a bucket.
@@ -268,6 +269,35 @@ class AWSStateStoreTest(hidden.AbstractStateStoreTest, BucketUsingTest):
268
269
  self.assertEqual(obj.content_length, len("testvalue"))
269
270
 
270
271
 
272
+ # Problem: httpx (which the Connexion test client uses the API of)
273
+ # automatically decides whether to send posts in
274
+ # application/x-www-form-urlencoded or multipart/form-data format
275
+ # based on whether they are uploading any files. But the GA4GH WES
276
+ # API run workflow endpoint only accepts multipart/form-data. It takes
277
+ # workflow_attachment as an array of binary strings officially, but this is
278
+ # actually how Swagger takes multiple-file upload fields. See
279
+ # <https://swagger.io/docs/specification/v2_0/file-upload/#multiple-upload>.
280
+ # (httpx doesn't seem to support actually sending multiple files to one field
281
+ # either, but if we send just one file it ends up as the only value in
282
+ # Swagger's array.)
283
+ #
284
+ # The apparently-official workaround for forcing multipart encoding is to
285
+ # construct an empty dict-saped data structure that is truthy, and pass that as
286
+ # your file list. See
287
+ # <https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186>
288
+ class TrueDict(dict):
289
+ """
290
+ Dict that is truthy even when empty.
291
+
292
+ Used as a workaround to set httpx post request encoding as recommended in
293
+ <https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186>.
294
+ """
295
+ def __bool__(self) -> bool:
296
+ """
297
+ Always say the object is truthy.
298
+ """
299
+ return True
300
+
271
301
  @needs_server
272
302
  class AbstractToilWESServerTest(ToilTest):
273
303
  """
@@ -296,11 +326,12 @@ class AbstractToilWESServerTest(ToilTest):
296
326
  )
297
327
 
298
328
  # Make the FlaskApp
299
- server_app = create_app(args)
329
+ self.app = create_app(args)
300
330
 
301
- # Fish out the actual Flask
302
- self.app: Flask = server_app.app
303
- self.app.testing = True
331
+ # Neither <https://flask.palletsprojects.com/en/stable/testing/> nor
332
+ # <https://connexion.readthedocs.io/en/latest/testing.html#testing>
333
+ # suggests setting a testing flag on the Connexion app or its internal
334
+ # Flask app, so we don't.
304
335
 
305
336
  self.example_cwl = textwrap.dedent(
306
337
  """
@@ -345,7 +376,6 @@ class AbstractToilWESServerTest(ToilTest):
345
376
  """
346
377
  rv = client.get(f"/ga4gh/wes/v1/runs/{run_id}")
347
378
  self.assertEqual(rv.status_code, 200)
348
- self.assertTrue(rv.is_json)
349
379
  return rv
350
380
 
351
381
  def _check_successful_log(self, client: "FlaskClient", run_id: str) -> None:
@@ -354,15 +384,16 @@ class AbstractToilWESServerTest(ToilTest):
354
384
  The workflow should succeed, it should have some tasks, and they should have all succeeded.
355
385
  """
356
386
  rv = self._fetch_run_log(client, run_id)
387
+ rv_json = rv.json()
357
388
  logger.debug("Log info: %s", rv.json)
358
- run_log = rv.json.get("run_log")
389
+ run_log = rv_json.get("run_log")
359
390
  self.assertEqual(type(run_log), dict)
360
391
  if "exit_code" in run_log:
361
392
  # The workflow succeeded if it has an exit code
362
393
  self.assertEqual(run_log["exit_code"], 0)
363
394
  # The workflow is complete
364
- self.assertEqual(rv.json.get("state"), "COMPLETE")
365
- task_logs = rv.json.get("task_logs")
395
+ self.assertEqual(rv_json.get("state"), "COMPLETE")
396
+ task_logs = rv_json.get("task_logs")
366
397
  # There are tasks reported
367
398
  self.assertEqual(type(task_logs), list)
368
399
  self.assertGreater(len(task_logs), 0)
@@ -375,7 +406,7 @@ class AbstractToilWESServerTest(ToilTest):
375
406
  """Report the log for the given workflow run."""
376
407
  rv = self._fetch_run_log(client, run_id)
377
408
  logger.debug(f"Report log response: {rv.json}")
378
- run_log = rv.json.get("run_log")
409
+ run_log = rv.json().get("run_log")
379
410
  self.assertEqual(type(run_log), dict)
380
411
  self.assertEqual(type(run_log.get("stdout")), str)
381
412
  self.assertEqual(type(run_log.get("stderr")), str)
@@ -395,12 +426,13 @@ class AbstractToilWESServerTest(ToilTest):
395
426
  logger.info("Fetch %s", url)
396
427
  rv = client.get(url)
397
428
  self.assertEqual(rv.status_code, 200)
398
- logger.info("Got %s:\n%s", url, rv.data.decode("utf-8"))
429
+ logger.info("Got %s:\n%s", url, rv.content.decode("utf-8"))
399
430
 
400
431
  def _start_slow_workflow(self, client: "FlaskClient") -> str:
401
432
  """
402
433
  Start a slow workflow and return its ID.
403
434
  """
435
+
404
436
  rv = client.post(
405
437
  "/ga4gh/wes/v1/runs",
406
438
  data={
@@ -408,15 +440,18 @@ class AbstractToilWESServerTest(ToilTest):
408
440
  "workflow_type": "CWL",
409
441
  "workflow_type_version": "v1.0",
410
442
  "workflow_params": json.dumps({"delay": "5"}),
411
- "workflow_attachment": [
412
- (BytesIO(self.slow_cwl.encode()), "slow.cwl"),
413
- ],
443
+ },
444
+ files={
445
+ "workflow_attachment": (
446
+ "slow.cwl",
447
+ BytesIO(self.slow_cwl.encode()),
448
+ "application/octet-stream",
449
+ ),
414
450
  },
415
451
  )
416
452
  # workflow is submitted successfully
417
453
  self.assertEqual(rv.status_code, 200)
418
- self.assertTrue(rv.is_json)
419
- run_id = rv.json.get("run_id")
454
+ run_id = rv.json().get("run_id")
420
455
  self.assertIsNotNone(run_id)
421
456
 
422
457
  return run_id
@@ -428,11 +463,11 @@ class AbstractToilWESServerTest(ToilTest):
428
463
 
429
464
  rv = client.get(f"/ga4gh/wes/v1/runs/{run_id}/status")
430
465
  self.assertEqual(rv.status_code, 200)
431
- self.assertTrue(rv.is_json)
432
- self.assertIn("run_id", rv.json)
433
- self.assertEqual(rv.json.get("run_id"), run_id)
434
- self.assertIn("state", rv.json)
435
- state = rv.json.get("state")
466
+ rv_json = rv.json()
467
+ self.assertIn("run_id", rv_json)
468
+ self.assertEqual(rv_json.get("run_id"), run_id)
469
+ self.assertIn("state", rv_json)
470
+ state = rv_json.get("state")
436
471
  self.assertIn(
437
472
  state,
438
473
  [
@@ -492,7 +527,10 @@ class ToilWESServerBenchTest(AbstractToilWESServerTest):
492
527
  """Test the homepage endpoint."""
493
528
  with self.app.test_client() as client:
494
529
  rv = client.get("/")
495
- self.assertEqual(rv.status_code, 302)
530
+ # The client will follow the redirect and populate the url on the response
531
+ self.assertEqual(rv.url.path, "/ga4gh/wes/v1/service-info")
532
+ # We see the final 200 OK status code
533
+ self.assertEqual(rv.status_code, 200)
496
534
 
497
535
  def test_health(self) -> None:
498
536
  """Test the health check endpoint."""
@@ -505,7 +543,7 @@ class ToilWESServerBenchTest(AbstractToilWESServerTest):
505
543
  with self.app.test_client() as client:
506
544
  rv = client.get("/ga4gh/wes/v1/service-info")
507
545
  self.assertEqual(rv.status_code, 200)
508
- service_info = json.loads(rv.data)
546
+ service_info = rv.json()
509
547
 
510
548
  self.assertIn("version", service_info)
511
549
  self.assertIn("workflow_type_versions", service_info)
@@ -519,7 +557,7 @@ class ToilWESServerBenchTest(AbstractToilWESServerTest):
519
557
  self.assertIn("system_state_counts", service_info)
520
558
  self.assertIn("tags", service_info)
521
559
 
522
-
560
+ @needs_cwl
523
561
  class ToilWESServerWorkflowTest(AbstractToilWESServerTest):
524
562
  """
525
563
  Tests of the WES server running workflows.
@@ -548,11 +586,10 @@ class ToilWESServerWorkflowTest(AbstractToilWESServerTest):
548
586
  {"message": "Hello, world!"} if include_message else {}
549
587
  )
550
588
  with self.app.test_client() as client:
551
- rv = client.post("/ga4gh/wes/v1/runs", data=post_data)
589
+ rv = client.post("/ga4gh/wes/v1/runs", data=post_data, files=TrueDict())
552
590
  # workflow is submitted successfully
553
591
  self.assertEqual(rv.status_code, 200)
554
- self.assertTrue(rv.is_json)
555
- run_id = rv.json.get("run_id")
592
+ run_id = rv.json().get("run_id")
556
593
  self.assertIsNotNone(run_id)
557
594
 
558
595
  # Check status
@@ -571,11 +608,11 @@ class ToilWESServerWorkflowTest(AbstractToilWESServerTest):
571
608
  "workflow_type_version": "v1.0",
572
609
  "workflow_params": "{}",
573
610
  },
611
+ files=TrueDict(),
574
612
  )
575
613
  self.assertEqual(rv.status_code, 400)
576
- self.assertTrue(rv.is_json)
577
614
  self.assertEqual(
578
- rv.json.get("msg"),
615
+ rv.json().get("msg"),
579
616
  "Relative 'workflow_url' but missing 'workflow_attachment'",
580
617
  )
581
618
 
@@ -589,20 +626,24 @@ class ToilWESServerWorkflowTest(AbstractToilWESServerTest):
589
626
  "workflow_type": "CWL",
590
627
  "workflow_type_version": "v1.0",
591
628
  "workflow_params": json.dumps({"message": "Hello, world!"}),
592
- "workflow_attachment": [
593
- (BytesIO(self.example_cwl.encode()), "example.cwl"),
594
- ],
629
+ },
630
+ files={
631
+ "workflow_attachment": (
632
+ "example.cwl",
633
+ BytesIO(self.example_cwl.encode()),
634
+ "application/octet-stream",
635
+ ),
595
636
  },
596
637
  )
597
638
  # workflow is submitted successfully
598
639
  self.assertEqual(rv.status_code, 200)
599
- self.assertTrue(rv.is_json)
600
- run_id = rv.json.get("run_id")
640
+ run_id = rv.json().get("run_id")
601
641
  self.assertIsNotNone(run_id)
602
642
 
603
643
  # Check status
604
644
  self._wait_for_success(client, run_id)
605
645
 
646
+ @integrative
606
647
  def test_run_workflow_https_url(self) -> None:
607
648
  """Test run example CWL workflow from the Internet."""
608
649
  with self.app.test_client() as client:
@@ -614,11 +655,11 @@ class ToilWESServerWorkflowTest(AbstractToilWESServerTest):
614
655
  "workflow_type_version": "v1.2",
615
656
  "workflow_params": json.dumps({"message": "Hello, world!"}),
616
657
  },
658
+ files=TrueDict(),
617
659
  )
618
660
  # workflow is submitted successfully
619
661
  self.assertEqual(rv.status_code, 200)
620
- self.assertTrue(rv.is_json)
621
- run_id = rv.json.get("run_id")
662
+ run_id = rv.json().get("run_id")
622
663
  self.assertIsNotNone(run_id)
623
664
 
624
665
  # Check status
@@ -730,6 +771,7 @@ class ToilWESServerWorkflowTest(AbstractToilWESServerTest):
730
771
 
731
772
 
732
773
  @needs_celery_broker
774
+ @integrative
733
775
  class ToilWESServerCeleryWorkflowTest(ToilWESServerWorkflowTest):
734
776
  """
735
777
  End-to-end workflow-running tests against Celery.
toil/test/sort/sort.py CHANGED
@@ -23,6 +23,7 @@ from configargparse import ArgumentParser
23
23
 
24
24
  from toil.common import Toil
25
25
  from toil.job import Job
26
+ from toil.lib.misc import StrPath
26
27
  from toil.realtimeLogger import RealtimeLogger
27
28
 
28
29
  defaultLines = 1000
@@ -207,7 +208,9 @@ def getMidPoint(file, fileStart, fileEnd):
207
208
  return len(line) + fileStart - 1
208
209
 
209
210
 
210
- def makeFileToSort(fileName, lines=defaultLines, lineLen=defaultLineLen):
211
+ def makeFileToSort(
212
+ fileName: StrPath, lines: int = defaultLines, lineLen: int = defaultLineLen
213
+ ) -> None:
211
214
  with open(fileName, "w") as f:
212
215
  for _ in range(lines):
213
216
  line = (
toil/test/src/busTest.py CHANGED
@@ -14,7 +14,9 @@
14
14
 
15
15
  import logging
16
16
  import os
17
+ from pathlib import Path
17
18
  from threading import Thread, current_thread
19
+ from typing import NoReturn
18
20
 
19
21
  from toil.batchSystems.abstractBatchSystem import BatchJobExitReason
20
22
  from toil.bus import (
@@ -26,18 +28,17 @@ from toil.bus import (
26
28
  from toil.common import Toil
27
29
  from toil.exceptions import FailedJobsException
28
30
  from toil.job import Job
29
- from toil.test import ToilTest, get_temp_file
30
31
 
31
32
  logger = logging.getLogger(__name__)
32
33
 
33
34
 
34
- class MessageBusTest(ToilTest):
35
+ class TestMessageBus:
35
36
 
36
- def test_enum_ints_in_file(self) -> None:
37
+ def test_enum_ints_in_file(self, tmp_path: Path) -> None:
37
38
  """
38
39
  Make sure writing bus messages to files works with enums.
39
40
  """
40
- bus_file = get_temp_file()
41
+ bus_file = tmp_path / "bus"
41
42
 
42
43
  bus = MessageBus()
43
44
  # Connect the handler and hold the result to protect it from GC
@@ -73,7 +74,7 @@ class MessageBusTest(ToilTest):
73
74
  # Message should always arrive in the main thread.
74
75
  nonlocal message_count
75
76
  logger.debug("Got message: %s", received)
76
- self.assertEqual(current_thread(), main_thread)
77
+ assert current_thread() == main_thread
77
78
  message_count += 1
78
79
 
79
80
  bus.subscribe(JobIssuedMessage, handler)
@@ -101,28 +102,27 @@ class MessageBusTest(ToilTest):
101
102
  t.join()
102
103
 
103
104
  # We should ge tone message per thread, plus our own
104
- self.assertEqual(box.count(JobIssuedMessage), 11)
105
+ assert box.count(JobIssuedMessage) == 11
105
106
  # And having polled for those, our handler should have run
106
- self.assertEqual(message_count, 11)
107
+ assert message_count == 11
107
108
 
108
- def test_restart_without_bus_path(self) -> None:
109
+ def test_restart_without_bus_path(self, tmp_path: Path) -> None:
109
110
  """
110
111
  Test the ability to restart a workflow when the message bus path used
111
112
  by the previous attempt is gone.
112
113
  """
113
- temp_dir = self._createTempDir(purpose="tempDir")
114
- job_store = self._getTestJobStorePath()
114
+ temp_dir = tmp_path / "tempDir"
115
+ temp_dir.mkdir()
116
+ job_store = tmp_path / "jobstore"
115
117
 
116
- bus_holder_dir = os.path.join(temp_dir, "bus_holder")
117
- os.mkdir(bus_holder_dir)
118
+ bus_holder_dir = temp_dir / "bus_holder"
119
+ bus_holder_dir.mkdir()
118
120
 
119
121
  start_options = Job.Runner.getDefaultOptions(job_store)
120
122
  start_options.logLevel = "DEBUG"
121
123
  start_options.retryCount = 0
122
124
  start_options.clean = "never"
123
- start_options.write_messages = os.path.abspath(
124
- os.path.join(bus_holder_dir, "messagebus.txt")
125
- )
125
+ start_options.write_messages = str(bus_holder_dir / "messagebus.txt")
126
126
 
127
127
  root = Job.wrapJobFn(failing_job_fn)
128
128
 
@@ -137,7 +137,7 @@ class MessageBusTest(ToilTest):
137
137
 
138
138
  # Get rid of the bus
139
139
  os.unlink(start_options.write_messages)
140
- os.rmdir(bus_holder_dir)
140
+ bus_holder_dir.rmdir()
141
141
 
142
142
  logger.info("Making second attempt")
143
143
 
@@ -158,7 +158,7 @@ class MessageBusTest(ToilTest):
158
158
  logger.info("Second attempt successfully failed")
159
159
 
160
160
 
161
- def failing_job_fn(job: Job) -> None:
161
+ def failing_job_fn(job: Job) -> NoReturn:
162
162
  """
163
163
  This function is guaranteed to fail.
164
164
  """