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.
- toil/__init__.py +0 -35
- toil/batchSystems/abstractBatchSystem.py +1 -1
- toil/batchSystems/abstractGridEngineBatchSystem.py +1 -1
- toil/batchSystems/awsBatch.py +1 -1
- toil/batchSystems/cleanup_support.py +1 -1
- toil/batchSystems/kubernetes.py +53 -7
- toil/batchSystems/local_support.py +1 -1
- toil/batchSystems/mesos/batchSystem.py +13 -8
- toil/batchSystems/mesos/test/__init__.py +3 -2
- toil/batchSystems/registry.py +15 -118
- toil/batchSystems/singleMachine.py +1 -1
- toil/batchSystems/slurm.py +27 -26
- toil/bus.py +5 -3
- toil/common.py +59 -12
- toil/cwl/cwltoil.py +81 -38
- toil/cwl/utils.py +103 -3
- toil/job.py +64 -49
- toil/jobStores/abstractJobStore.py +35 -239
- toil/jobStores/aws/jobStore.py +2 -1
- toil/jobStores/fileJobStore.py +27 -2
- toil/jobStores/googleJobStore.py +110 -33
- toil/leader.py +9 -0
- toil/lib/accelerators.py +4 -2
- toil/lib/aws/utils.py.orig +504 -0
- toil/lib/bioio.py +1 -1
- toil/lib/docker.py +252 -91
- toil/lib/dockstore.py +11 -3
- toil/lib/exceptions.py +5 -3
- toil/lib/generatedEC2Lists.py +81 -19
- toil/lib/history.py +87 -13
- toil/lib/history_submission.py +23 -9
- toil/lib/io.py +34 -22
- toil/lib/misc.py +8 -2
- toil/lib/plugins.py +106 -0
- toil/lib/resources.py +2 -1
- toil/lib/threading.py +11 -10
- toil/lib/url.py +320 -0
- toil/options/common.py +8 -0
- toil/options/cwl.py +13 -1
- toil/options/runner.py +17 -10
- toil/options/wdl.py +22 -0
- toil/provisioners/aws/awsProvisioner.py +25 -2
- toil/server/api_spec/LICENSE +201 -0
- toil/server/api_spec/README.rst +5 -0
- toil/server/app.py +12 -6
- toil/server/cli/wes_cwl_runner.py +3 -2
- toil/server/wes/abstract_backend.py +21 -43
- toil/server/wes/toil_backend.py +2 -2
- toil/test/__init__.py +275 -115
- toil/test/batchSystems/batchSystemTest.py +228 -213
- toil/test/batchSystems/batch_system_plugin_test.py +7 -0
- toil/test/batchSystems/test_slurm.py +27 -0
- toil/test/cactus/pestis.tar.gz +0 -0
- toil/test/conftest.py +7 -0
- toil/test/cwl/2.fasta +11 -0
- toil/test/cwl/2.fastq +12 -0
- toil/test/cwl/conftest.py +1 -1
- toil/test/cwl/cwlTest.py +1175 -870
- toil/test/cwl/directory/directory/file.txt +15 -0
- toil/test/cwl/download_directory_file.json +4 -0
- toil/test/cwl/download_directory_s3.json +4 -0
- toil/test/cwl/download_file.json +6 -0
- toil/test/cwl/download_http.json +6 -0
- toil/test/cwl/download_https.json +6 -0
- toil/test/cwl/download_s3.json +6 -0
- toil/test/cwl/download_subdirectory_file.json +5 -0
- toil/test/cwl/download_subdirectory_s3.json +5 -0
- toil/test/cwl/empty.json +1 -0
- toil/test/cwl/mock_mpi/fake_mpi.yml +8 -0
- toil/test/cwl/mock_mpi/fake_mpi_run.py +42 -0
- toil/test/cwl/optional-file-exists.json +6 -0
- toil/test/cwl/optional-file-missing.json +6 -0
- toil/test/cwl/preemptible_expression.json +1 -0
- toil/test/cwl/revsort-job-missing.json +6 -0
- toil/test/cwl/revsort-job.json +6 -0
- toil/test/cwl/s3_secondary_file.json +16 -0
- toil/test/cwl/seqtk_seq_job.json +6 -0
- toil/test/cwl/stream.json +6 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.dat +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f0 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f1 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f1i +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f2 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f2_TSM0 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f3 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f3_TSM0 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f4 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f4_TSM0 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.f5 +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.info +0 -0
- toil/test/cwl/test_filename_conflict_resolution.ms/table.lock +0 -0
- toil/test/cwl/whale.txt +16 -0
- toil/test/docs/scripts/example_alwaysfail.py +38 -0
- toil/test/docs/scripts/example_alwaysfail_with_files.wdl +33 -0
- toil/test/docs/scripts/example_cachingbenchmark.py +117 -0
- toil/test/docs/scripts/stagingExampleFiles/in.txt +1 -0
- toil/test/docs/scripts/stagingExampleFiles/out.txt +2 -0
- toil/test/docs/scripts/tutorial_arguments.py +23 -0
- toil/test/docs/scripts/tutorial_debugging.patch +12 -0
- toil/test/docs/scripts/tutorial_debugging_hangs.wdl +126 -0
- toil/test/docs/scripts/tutorial_debugging_works.wdl +129 -0
- toil/test/docs/scripts/tutorial_docker.py +20 -0
- toil/test/docs/scripts/tutorial_dynamic.py +24 -0
- toil/test/docs/scripts/tutorial_encapsulation.py +28 -0
- toil/test/docs/scripts/tutorial_encapsulation2.py +29 -0
- toil/test/docs/scripts/tutorial_helloworld.py +15 -0
- toil/test/docs/scripts/tutorial_invokeworkflow.py +27 -0
- toil/test/docs/scripts/tutorial_invokeworkflow2.py +30 -0
- toil/test/docs/scripts/tutorial_jobfunctions.py +22 -0
- toil/test/docs/scripts/tutorial_managing.py +29 -0
- toil/test/docs/scripts/tutorial_managing2.py +56 -0
- toil/test/docs/scripts/tutorial_multiplejobs.py +25 -0
- toil/test/docs/scripts/tutorial_multiplejobs2.py +21 -0
- toil/test/docs/scripts/tutorial_multiplejobs3.py +22 -0
- toil/test/docs/scripts/tutorial_promises.py +25 -0
- toil/test/docs/scripts/tutorial_promises2.py +30 -0
- toil/test/docs/scripts/tutorial_quickstart.py +22 -0
- toil/test/docs/scripts/tutorial_requirements.py +44 -0
- toil/test/docs/scripts/tutorial_services.py +45 -0
- toil/test/docs/scripts/tutorial_staging.py +45 -0
- toil/test/docs/scripts/tutorial_stats.py +64 -0
- toil/test/docs/scriptsTest.py +2 -1
- toil/test/lib/aws/test_iam.py +3 -1
- toil/test/lib/dockerTest.py +205 -122
- toil/test/lib/test_history.py +101 -77
- toil/test/lib/test_url.py +69 -0
- toil/test/lib/url_plugin_test.py +105 -0
- toil/test/provisioners/aws/awsProvisionerTest.py +13 -10
- toil/test/provisioners/clusterTest.py +17 -4
- toil/test/provisioners/gceProvisionerTest.py +17 -15
- toil/test/server/serverTest.py +78 -36
- toil/test/sort/sort.py +4 -1
- toil/test/src/busTest.py +17 -17
- toil/test/src/deferredFunctionTest.py +145 -132
- toil/test/src/importExportFileTest.py +71 -63
- toil/test/src/jobEncapsulationTest.py +27 -28
- toil/test/src/jobServiceTest.py +149 -133
- toil/test/src/jobTest.py +219 -211
- toil/test/src/miscTests.py +66 -60
- toil/test/src/promisedRequirementTest.py +163 -169
- toil/test/src/regularLogTest.py +24 -24
- toil/test/src/resourceTest.py +82 -76
- toil/test/src/restartDAGTest.py +51 -47
- toil/test/src/resumabilityTest.py +24 -19
- toil/test/src/retainTempDirTest.py +60 -57
- toil/test/src/systemTest.py +17 -13
- toil/test/src/threadingTest.py +29 -32
- toil/test/utils/ABCWorkflowDebug/B_file.txt +1 -0
- toil/test/utils/ABCWorkflowDebug/debugWorkflow.py +204 -0
- toil/test/utils/ABCWorkflowDebug/mkFile.py +16 -0
- toil/test/utils/ABCWorkflowDebug/sleep.cwl +12 -0
- toil/test/utils/ABCWorkflowDebug/sleep.yaml +1 -0
- toil/test/utils/toilDebugTest.py +117 -102
- toil/test/utils/toilKillTest.py +54 -53
- toil/test/utils/utilsTest.py +303 -229
- toil/test/wdl/lint_error.wdl +9 -0
- toil/test/wdl/md5sum/empty_file.json +1 -0
- toil/test/wdl/md5sum/md5sum-gs.json +1 -0
- toil/test/wdl/md5sum/md5sum.1.0.wdl +32 -0
- toil/test/wdl/md5sum/md5sum.input +1 -0
- toil/test/wdl/md5sum/md5sum.json +1 -0
- toil/test/wdl/md5sum/md5sum.wdl +25 -0
- toil/test/wdl/miniwdl_self_test/inputs-namespaced.json +1 -0
- toil/test/wdl/miniwdl_self_test/inputs.json +1 -0
- toil/test/wdl/miniwdl_self_test/self_test.wdl +40 -0
- toil/test/wdl/standard_library/as_map.json +16 -0
- toil/test/wdl/standard_library/as_map_as_input.wdl +23 -0
- toil/test/wdl/standard_library/as_pairs.json +7 -0
- toil/test/wdl/standard_library/as_pairs_as_input.wdl +23 -0
- toil/test/wdl/standard_library/ceil.json +3 -0
- toil/test/wdl/standard_library/ceil_as_command.wdl +16 -0
- toil/test/wdl/standard_library/ceil_as_input.wdl +16 -0
- toil/test/wdl/standard_library/collect_by_key.json +1 -0
- toil/test/wdl/standard_library/collect_by_key_as_input.wdl +23 -0
- toil/test/wdl/standard_library/cross.json +11 -0
- toil/test/wdl/standard_library/cross_as_input.wdl +19 -0
- toil/test/wdl/standard_library/flatten.json +7 -0
- toil/test/wdl/standard_library/flatten_as_input.wdl +18 -0
- toil/test/wdl/standard_library/floor.json +3 -0
- toil/test/wdl/standard_library/floor_as_command.wdl +16 -0
- toil/test/wdl/standard_library/floor_as_input.wdl +16 -0
- toil/test/wdl/standard_library/keys.json +8 -0
- toil/test/wdl/standard_library/keys_as_input.wdl +24 -0
- toil/test/wdl/standard_library/length.json +7 -0
- toil/test/wdl/standard_library/length_as_input.wdl +16 -0
- toil/test/wdl/standard_library/length_as_input_with_map.json +7 -0
- toil/test/wdl/standard_library/length_as_input_with_map.wdl +17 -0
- toil/test/wdl/standard_library/length_invalid.json +3 -0
- toil/test/wdl/standard_library/range.json +3 -0
- toil/test/wdl/standard_library/range_0.json +3 -0
- toil/test/wdl/standard_library/range_as_input.wdl +17 -0
- toil/test/wdl/standard_library/range_invalid.json +3 -0
- toil/test/wdl/standard_library/read_boolean.json +3 -0
- toil/test/wdl/standard_library/read_boolean_as_command.wdl +17 -0
- toil/test/wdl/standard_library/read_float.json +3 -0
- toil/test/wdl/standard_library/read_float_as_command.wdl +17 -0
- toil/test/wdl/standard_library/read_int.json +3 -0
- toil/test/wdl/standard_library/read_int_as_command.wdl +17 -0
- toil/test/wdl/standard_library/read_json.json +3 -0
- toil/test/wdl/standard_library/read_json_as_output.wdl +31 -0
- toil/test/wdl/standard_library/read_lines.json +3 -0
- toil/test/wdl/standard_library/read_lines_as_output.wdl +31 -0
- toil/test/wdl/standard_library/read_map.json +3 -0
- toil/test/wdl/standard_library/read_map_as_output.wdl +31 -0
- toil/test/wdl/standard_library/read_string.json +3 -0
- toil/test/wdl/standard_library/read_string_as_command.wdl +17 -0
- toil/test/wdl/standard_library/read_tsv.json +3 -0
- toil/test/wdl/standard_library/read_tsv_as_output.wdl +31 -0
- toil/test/wdl/standard_library/round.json +3 -0
- toil/test/wdl/standard_library/round_as_command.wdl +16 -0
- toil/test/wdl/standard_library/round_as_input.wdl +16 -0
- toil/test/wdl/standard_library/size.json +3 -0
- toil/test/wdl/standard_library/size_as_command.wdl +17 -0
- toil/test/wdl/standard_library/size_as_output.wdl +36 -0
- toil/test/wdl/standard_library/stderr.json +3 -0
- toil/test/wdl/standard_library/stderr_as_output.wdl +30 -0
- toil/test/wdl/standard_library/stdout.json +3 -0
- toil/test/wdl/standard_library/stdout_as_output.wdl +30 -0
- toil/test/wdl/standard_library/sub.json +3 -0
- toil/test/wdl/standard_library/sub_as_input.wdl +17 -0
- toil/test/wdl/standard_library/sub_as_input_with_file.wdl +17 -0
- toil/test/wdl/standard_library/transpose.json +6 -0
- toil/test/wdl/standard_library/transpose_as_input.wdl +18 -0
- toil/test/wdl/standard_library/write_json.json +6 -0
- toil/test/wdl/standard_library/write_json_as_command.wdl +17 -0
- toil/test/wdl/standard_library/write_lines.json +7 -0
- toil/test/wdl/standard_library/write_lines_as_command.wdl +17 -0
- toil/test/wdl/standard_library/write_map.json +6 -0
- toil/test/wdl/standard_library/write_map_as_command.wdl +17 -0
- toil/test/wdl/standard_library/write_tsv.json +6 -0
- toil/test/wdl/standard_library/write_tsv_as_command.wdl +17 -0
- toil/test/wdl/standard_library/zip.json +12 -0
- toil/test/wdl/standard_library/zip_as_input.wdl +19 -0
- toil/test/wdl/test.csv +3 -0
- toil/test/wdl/test.tsv +3 -0
- toil/test/wdl/testfiles/croo.wdl +38 -0
- toil/test/wdl/testfiles/drop_files.wdl +62 -0
- toil/test/wdl/testfiles/drop_files_subworkflow.wdl +13 -0
- toil/test/wdl/testfiles/empty.txt +0 -0
- toil/test/wdl/testfiles/not_enough_outputs.wdl +33 -0
- toil/test/wdl/testfiles/random.wdl +66 -0
- toil/test/wdl/testfiles/read_file.wdl +18 -0
- toil/test/wdl/testfiles/string_file_coercion.json +1 -0
- toil/test/wdl/testfiles/string_file_coercion.wdl +35 -0
- toil/test/wdl/testfiles/test.json +4 -0
- toil/test/wdl/testfiles/test_boolean.txt +1 -0
- toil/test/wdl/testfiles/test_float.txt +1 -0
- toil/test/wdl/testfiles/test_int.txt +1 -0
- toil/test/wdl/testfiles/test_lines.txt +5 -0
- toil/test/wdl/testfiles/test_map.txt +2 -0
- toil/test/wdl/testfiles/test_string.txt +1 -0
- toil/test/wdl/testfiles/url_to_file.wdl +13 -0
- toil/test/wdl/testfiles/url_to_optional_file.wdl +14 -0
- toil/test/wdl/testfiles/vocab.json +1 -0
- toil/test/wdl/testfiles/vocab.wdl +66 -0
- toil/test/wdl/testfiles/wait.wdl +34 -0
- toil/test/wdl/wdl_specification/type_pair.json +23 -0
- toil/test/wdl/wdl_specification/type_pair_basic.wdl +36 -0
- toil/test/wdl/wdl_specification/type_pair_with_files.wdl +36 -0
- toil/test/wdl/wdl_specification/v1_spec.json +1 -0
- toil/test/wdl/wdl_specification/v1_spec_declaration.wdl +39 -0
- toil/test/wdl/wdltoil_test.py +751 -529
- toil/test/wdl/wdltoil_test_kubernetes.py +2 -2
- toil/utils/toilSshCluster.py +23 -0
- toil/utils/toilUpdateEC2Instances.py +1 -0
- toil/version.py +5 -5
- toil/wdl/wdltoil.py +518 -437
- toil/worker.py +11 -6
- {toil-8.1.0b1.dist-info → toil-9.0.0.dist-info}/METADATA +25 -24
- toil-9.0.0.dist-info/RECORD +444 -0
- {toil-8.1.0b1.dist-info → toil-9.0.0.dist-info}/WHEEL +1 -1
- toil-8.1.0b1.dist-info/RECORD +0 -259
- {toil-8.1.0b1.dist-info → toil-9.0.0.dist-info}/entry_points.txt +0 -0
- {toil-8.1.0b1.dist-info → toil-9.0.0.dist-info/licenses}/LICENSE +0 -0
- {toil-8.1.0b1.dist-info → toil-9.0.0.dist-info}/top_level.txt +0 -0
toil/test/server/serverTest.py
CHANGED
|
@@ -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
|
-
|
|
329
|
+
self.app = create_app(args)
|
|
300
330
|
|
|
301
|
-
#
|
|
302
|
-
|
|
303
|
-
|
|
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 =
|
|
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(
|
|
365
|
-
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.
|
|
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
|
-
|
|
412
|
-
|
|
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
|
-
|
|
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
|
-
|
|
432
|
-
self.assertIn("run_id",
|
|
433
|
-
self.assertEqual(
|
|
434
|
-
self.assertIn("state",
|
|
435
|
-
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
593
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
105
|
+
assert box.count(JobIssuedMessage) == 11
|
|
105
106
|
# And having polled for those, our handler should have run
|
|
106
|
-
|
|
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 =
|
|
114
|
-
|
|
114
|
+
temp_dir = tmp_path / "tempDir"
|
|
115
|
+
temp_dir.mkdir()
|
|
116
|
+
job_store = tmp_path / "jobstore"
|
|
115
117
|
|
|
116
|
-
bus_holder_dir =
|
|
117
|
-
|
|
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 =
|
|
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
|
-
|
|
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) ->
|
|
161
|
+
def failing_job_fn(job: Job) -> NoReturn:
|
|
162
162
|
"""
|
|
163
163
|
This function is guaranteed to fail.
|
|
164
164
|
"""
|