toil 8.1.0b1__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.
- 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/singleMachine.py +1 -1
- toil/batchSystems/slurm.py +27 -26
- toil/bus.py +5 -3
- toil/common.py +39 -11
- toil/cwl/cwltoil.py +1 -1
- toil/job.py +64 -49
- toil/jobStores/abstractJobStore.py +24 -3
- toil/jobStores/fileJobStore.py +25 -1
- toil/jobStores/googleJobStore.py +104 -30
- toil/leader.py +9 -0
- toil/lib/accelerators.py +3 -1
- 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/history.py +87 -13
- toil/lib/history_submission.py +23 -9
- toil/lib/io.py +34 -22
- toil/lib/misc.py +7 -1
- toil/lib/resources.py +2 -1
- toil/lib/threading.py +11 -10
- toil/options/common.py +8 -0
- toil/options/wdl.py +11 -0
- toil/server/api_spec/LICENSE +201 -0
- toil/server/api_spec/README.rst +5 -0
- toil/server/cli/wes_cwl_runner.py +2 -1
- toil/test/__init__.py +275 -115
- toil/test/batchSystems/batchSystemTest.py +227 -205
- 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 +999 -867
- 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/lib/aws/test_iam.py +3 -1
- toil/test/lib/dockerTest.py +205 -122
- toil/test/lib/test_history.py +101 -77
- toil/test/provisioners/aws/awsProvisionerTest.py +12 -9
- toil/test/provisioners/clusterTest.py +4 -4
- toil/test/provisioners/gceProvisionerTest.py +16 -14
- 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/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 +13 -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 +680 -407
- toil/test/wdl/wdltoil_test_kubernetes.py +2 -2
- toil/version.py +9 -9
- toil/wdl/wdltoil.py +336 -123
- {toil-8.1.0b1.dist-info → toil-8.2.0.dist-info}/METADATA +5 -4
- toil-8.2.0.dist-info/RECORD +439 -0
- {toil-8.1.0b1.dist-info → toil-8.2.0.dist-info}/WHEEL +1 -1
- toil-8.1.0b1.dist-info/RECORD +0 -259
- {toil-8.1.0b1.dist-info → toil-8.2.0.dist-info}/entry_points.txt +0 -0
- {toil-8.1.0b1.dist-info → toil-8.2.0.dist-info/licenses}/LICENSE +0 -0
- {toil-8.1.0b1.dist-info → toil-8.2.0.dist-info}/top_level.txt +0 -0
toil/test/cwl/empty.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import argparse
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
from configargparse import ArgumentParser
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def make_parser() -> ArgumentParser:
|
|
10
|
+
p = ArgumentParser()
|
|
11
|
+
p.add_argument(
|
|
12
|
+
"progargs", nargs=argparse.REMAINDER, help="The program and its arguments"
|
|
13
|
+
)
|
|
14
|
+
p.add_argument("--num", type=int, help="number of times to run the application")
|
|
15
|
+
p.add_argument(
|
|
16
|
+
"--no-fail", help="add this flag to actually work", action="store_true"
|
|
17
|
+
)
|
|
18
|
+
return p
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Runner:
|
|
22
|
+
def __init__(self) -> None:
|
|
23
|
+
if sys.stdin.isatty():
|
|
24
|
+
self.indata = None
|
|
25
|
+
else:
|
|
26
|
+
self.indata = sys.stdin.read().encode(sys.stdin.encoding)
|
|
27
|
+
|
|
28
|
+
def run_once(self, args: list[str]) -> None:
|
|
29
|
+
subprocess.run(
|
|
30
|
+
args, input=self.indata, stdout=sys.stdout, stderr=sys.stderr
|
|
31
|
+
).check_returncode()
|
|
32
|
+
|
|
33
|
+
def run_many(self, n: int, args: list[str]) -> None:
|
|
34
|
+
for i in range(n):
|
|
35
|
+
self.run_once(args)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
if __name__ == "__main__":
|
|
39
|
+
args = make_parser().parse_args()
|
|
40
|
+
assert args.no_fail is True, "Didn't set the --no-fail flag"
|
|
41
|
+
r = Runner()
|
|
42
|
+
r.run_many(args.num, args.progargs)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"preemptible": true}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ref": {
|
|
3
|
+
"class": "File",
|
|
4
|
+
"location": "whale.txt",
|
|
5
|
+
"size": 1111,
|
|
6
|
+
"checksum": "sha1$hash",
|
|
7
|
+
"secondaryFiles": [
|
|
8
|
+
{
|
|
9
|
+
"class": "File",
|
|
10
|
+
"location": "s3://toil-cwl-infra-test-bucket-dont-delete/whale.txt.changedOnPorpoise",
|
|
11
|
+
"size": 24,
|
|
12
|
+
"checksum": "sha1$hash"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
toil/test/cwl/whale.txt
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Call me Ishmael. Some years ago--never mind how long precisely--having
|
|
2
|
+
little or no money in my purse, and nothing particular to interest me on
|
|
3
|
+
shore, I thought I would sail about a little and see the watery part of
|
|
4
|
+
the world. It is a way I have of driving off the spleen and regulating
|
|
5
|
+
the circulation. Whenever I find myself growing grim about the mouth;
|
|
6
|
+
whenever it is a damp, drizzly November in my soul; whenever I find
|
|
7
|
+
myself involuntarily pausing before coffin warehouses, and bringing up
|
|
8
|
+
the rear of every funeral I meet; and especially whenever my hypos get
|
|
9
|
+
such an upper hand of me, that it requires a strong moral principle to
|
|
10
|
+
prevent me from deliberately stepping into the street, and methodically
|
|
11
|
+
knocking people's hats off--then, I account it high time to get to sea
|
|
12
|
+
as soon as I can. This is my substitute for pistol and ball. With a
|
|
13
|
+
philosophical flourish Cato throws himself upon his sword; I quietly
|
|
14
|
+
take to the ship. There is nothing surprising in this. If they but knew
|
|
15
|
+
it, almost all men in their degree, some time or other, cherish very
|
|
16
|
+
nearly the same feelings towards the ocean with me.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
from configargparse import ArgumentParser
|
|
4
|
+
|
|
5
|
+
from toil.common import Toil
|
|
6
|
+
from toil.job import Job
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main():
|
|
10
|
+
"""
|
|
11
|
+
This workflow always fails.
|
|
12
|
+
|
|
13
|
+
Invoke like:
|
|
14
|
+
|
|
15
|
+
python examples/example_alwaysfail.py ./jobstore
|
|
16
|
+
|
|
17
|
+
Then you can inspect the job store with tools like `toil status`:
|
|
18
|
+
|
|
19
|
+
toil status --logs ./jobstore
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
parser = ArgumentParser(description=main.__doc__)
|
|
23
|
+
Job.Runner.addToilOptions(parser)
|
|
24
|
+
options = parser.parse_args(sys.argv[1:])
|
|
25
|
+
|
|
26
|
+
hello_job = Job.wrapJobFn(explode)
|
|
27
|
+
|
|
28
|
+
with Toil(options) as toil:
|
|
29
|
+
toil.start(hello_job)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def explode(job):
|
|
33
|
+
sys.stderr.write("Something somewhere has gone terribly wrong\n")
|
|
34
|
+
raise RuntimeError("Boom!")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if __name__ == "__main__":
|
|
38
|
+
main()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
version 1.0
|
|
2
|
+
workflow test {
|
|
3
|
+
call make_file as f1
|
|
4
|
+
call make_file as f2
|
|
5
|
+
call hello {
|
|
6
|
+
input:
|
|
7
|
+
name_file=f1.out,
|
|
8
|
+
unused_file=f2.out
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
task make_file {
|
|
12
|
+
input {
|
|
13
|
+
}
|
|
14
|
+
command <<<
|
|
15
|
+
echo "These are the contents" >test.txt
|
|
16
|
+
>>>
|
|
17
|
+
output {
|
|
18
|
+
File out = "test.txt"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
task hello {
|
|
22
|
+
input {
|
|
23
|
+
File name_file
|
|
24
|
+
File? unused_file
|
|
25
|
+
}
|
|
26
|
+
command <<<
|
|
27
|
+
set -e
|
|
28
|
+
echoo "Hello" "$(cat ~{name_file})"
|
|
29
|
+
>>>
|
|
30
|
+
output {
|
|
31
|
+
File out = stdout()
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# example_cachingbenchmark.py: Empirically inspect Toil caching
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
This workflow collects statistics about caching.
|
|
6
|
+
|
|
7
|
+
Invoke like:
|
|
8
|
+
|
|
9
|
+
python examples/example_cachingbenchmark.py ./jobstore --realTimeLogging --logInfo
|
|
10
|
+
|
|
11
|
+
python examples/example_cachingbenchmark.py ./jobstore --realTimeLogging --logInfo --disableCaching
|
|
12
|
+
|
|
13
|
+
python examples/example_cachingbenchmark.py aws:us-west-2:cachingjobstore --realTimeLogging --logInfo
|
|
14
|
+
|
|
15
|
+
python examples/example_cachingbenchmark.py aws:us-west-2:cachingjobstore --realTimeLogging --logInfo --disableCaching
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import collections
|
|
21
|
+
import os
|
|
22
|
+
import random
|
|
23
|
+
import socket
|
|
24
|
+
import sys
|
|
25
|
+
import time
|
|
26
|
+
|
|
27
|
+
from configargparse import ArgumentParser
|
|
28
|
+
|
|
29
|
+
from toil.common import Toil
|
|
30
|
+
from toil.job import Job
|
|
31
|
+
from toil.realtimeLogger import RealtimeLogger
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def main():
|
|
35
|
+
parser = ArgumentParser(
|
|
36
|
+
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--minSleep", type=int, default=1, help="Minimum seconds to sleep"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
Job.Runner.addToilOptions(parser)
|
|
44
|
+
|
|
45
|
+
options = parser.parse_args(sys.argv[1:])
|
|
46
|
+
|
|
47
|
+
root_job = Job.wrapJobFn(root, options)
|
|
48
|
+
|
|
49
|
+
with Toil(options) as toil:
|
|
50
|
+
results = toil.start(root_job)
|
|
51
|
+
|
|
52
|
+
print("Caching results:")
|
|
53
|
+
print(results)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def root(job, options):
|
|
57
|
+
# Make a file
|
|
58
|
+
with job.fileStore.writeGlobalFileStream() as (stream, file_id):
|
|
59
|
+
stream.write(
|
|
60
|
+
b"This is a test of the Toil file caching system. "
|
|
61
|
+
b"Had this been an actual file, its contents would have been more interesting."
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
child_rvs = []
|
|
65
|
+
for i in range(100):
|
|
66
|
+
# Make lots of child jobs that read and report on the file
|
|
67
|
+
child_rvs.append(job.addChildJobFn(poll, options, file_id, i).rv())
|
|
68
|
+
|
|
69
|
+
# Collect all their views into a report
|
|
70
|
+
return job.addFollowOnJobFn(report, child_rvs).rv()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def poll(job, options, file_id, number, cores=0.1, disk="200M", memory="512M"):
|
|
74
|
+
|
|
75
|
+
# Wait a random amount of time before grabbing the file for others to cache it
|
|
76
|
+
time.sleep(random.randint(options.minSleep, options.minSleep + 10))
|
|
77
|
+
|
|
78
|
+
# Read the file. Don't accept a symlink because then we might just have the
|
|
79
|
+
# filestore's copy, even if caching is not happening.
|
|
80
|
+
local_file = job.fileStore.readGlobalFile(
|
|
81
|
+
file_id, cache=True, mutable=False, symlink=False
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Wait a random amount of after before grabbing the file for others to use it
|
|
85
|
+
time.sleep(random.randint(options.minSleep, options.minSleep + 10))
|
|
86
|
+
|
|
87
|
+
# Stat the file (reads through links)
|
|
88
|
+
stats = os.stat(local_file)
|
|
89
|
+
|
|
90
|
+
# Check what machine we are
|
|
91
|
+
hostname = socket.gethostname()
|
|
92
|
+
|
|
93
|
+
RealtimeLogger.info(
|
|
94
|
+
f"Job {number} on host {hostname} sees file at device {stats.st_dev} inode {stats.st_ino}"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Return a tuple representing our view of the file.
|
|
98
|
+
# Drop hostname since hostnames are unique per pod.
|
|
99
|
+
return stats.st_dev, stats.st_ino
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def report(job, views):
|
|
103
|
+
# Count the distinct views
|
|
104
|
+
counts = collections.Counter()
|
|
105
|
+
for v in views:
|
|
106
|
+
counts[v] += 1
|
|
107
|
+
|
|
108
|
+
report = [f"{len(counts)} distinct views, most frequent:"]
|
|
109
|
+
|
|
110
|
+
for view, count in counts.most_common(10):
|
|
111
|
+
report.append(f"{view}: {count}")
|
|
112
|
+
|
|
113
|
+
return "\n".join(report)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
if __name__ == "__main__":
|
|
117
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Hello,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from toil.common import Toil
|
|
2
|
+
from toil.job import Job
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class HelloWorld(Job):
|
|
6
|
+
def __init__(self, message):
|
|
7
|
+
Job.__init__(self)
|
|
8
|
+
self.message = message
|
|
9
|
+
|
|
10
|
+
def run(self, fileStore):
|
|
11
|
+
return "Hello, world!, here's a message: %s" % self.message
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
parser = Job.Runner.getDefaultArgumentParser()
|
|
16
|
+
options = parser.parse_args()
|
|
17
|
+
options.logLevel = "OFF"
|
|
18
|
+
options.clean = "always"
|
|
19
|
+
|
|
20
|
+
hello_job = HelloWorld("Woot")
|
|
21
|
+
|
|
22
|
+
with Toil(options) as toil:
|
|
23
|
+
print(toil.start(hello_job))
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
--- tutorial_debugging_works.wdl 2024-06-18 12:03:32
|
|
2
|
+
+++ tutorial_debugging_hangs.wdl 2024-06-18 12:03:53
|
|
3
|
+
@@ -112,9 +112,6 @@
|
|
4
|
+
# Also remember to encode the text as the zip file
|
|
5
|
+
# stream is in binary mode.
|
|
6
|
+
out_stream.write(f"{basename}: {line}".encode("utf-8"))
|
|
7
|
+
- # Even though we got distracted by zip file manipulation, remember
|
|
8
|
+
- # to pop off the file we just did.
|
|
9
|
+
- to_compress.pop()
|
|
10
|
+
EOF
|
|
11
|
+
python script.py ~{sep(" ", files)}
|
|
12
|
+
>>>
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
version 1.1
|
|
2
|
+
|
|
3
|
+
workflow TutorialDebugging {
|
|
4
|
+
|
|
5
|
+
input {
|
|
6
|
+
Array[String] messages = ["Uh-oh!", "Oh dear", "Oops"]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
scatter(message in messages) {
|
|
10
|
+
|
|
11
|
+
call WhaleSay {
|
|
12
|
+
input:
|
|
13
|
+
message = message
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
call CountLines {
|
|
17
|
+
input:
|
|
18
|
+
to_count = WhaleSay.result
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Array[File] to_compress = flatten([CountLines.result, WhaleSay.result])
|
|
23
|
+
|
|
24
|
+
call CompressFiles {
|
|
25
|
+
input:
|
|
26
|
+
files = to_compress
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
output {
|
|
30
|
+
File compressed = CompressFiles.result
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Draw ASCII art
|
|
36
|
+
task WhaleSay {
|
|
37
|
+
input {
|
|
38
|
+
String message
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
command <<<
|
|
42
|
+
cowsay "~{message}"
|
|
43
|
+
>>>
|
|
44
|
+
|
|
45
|
+
output {
|
|
46
|
+
File result = stdout()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
runtime {
|
|
50
|
+
container: "docker/whalesay"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Count the lines in a file
|
|
55
|
+
task CountLines {
|
|
56
|
+
input {
|
|
57
|
+
File to_count
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
command <<<
|
|
61
|
+
wc -l ~{to_count}
|
|
62
|
+
>>>
|
|
63
|
+
|
|
64
|
+
output {
|
|
65
|
+
File result = stdout()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
runtime {
|
|
69
|
+
container: ["ubuntu:latest", "https://gcr.io/standard-images/ubuntu:latest"]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# Compress files into a ZIP
|
|
74
|
+
task CompressFiles {
|
|
75
|
+
input {
|
|
76
|
+
Array[File] files
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
command <<<
|
|
80
|
+
set -e
|
|
81
|
+
cat >script.py <<'EOF'
|
|
82
|
+
import sys
|
|
83
|
+
from zipfile import ZipFile
|
|
84
|
+
import os
|
|
85
|
+
|
|
86
|
+
# Interpret command line arguments
|
|
87
|
+
to_compress = list(reversed(sys.argv[1:]))
|
|
88
|
+
|
|
89
|
+
with ZipFile("compressed.zip", "w") as z:
|
|
90
|
+
while to_compress != []:
|
|
91
|
+
# Grab the file to add off the end of the list
|
|
92
|
+
input_filename = to_compress[-1]
|
|
93
|
+
# Now we need to write this to the zip file.
|
|
94
|
+
# What internal filename should we use?
|
|
95
|
+
basename = os.path.basename(input_filename)
|
|
96
|
+
disambiguation_number = 0
|
|
97
|
+
while True:
|
|
98
|
+
target_filename = str(disambiguation_number) + basename
|
|
99
|
+
try:
|
|
100
|
+
z.getinfo(target_filename)
|
|
101
|
+
except KeyError:
|
|
102
|
+
# Filename is free
|
|
103
|
+
break
|
|
104
|
+
# Otherwise try another name
|
|
105
|
+
disambiguation_number += 1
|
|
106
|
+
# Now we can actually make the compressed file
|
|
107
|
+
with z.open(target_filename, 'w') as out_stream:
|
|
108
|
+
with open(input_filename) as in_stream:
|
|
109
|
+
for line in in_stream:
|
|
110
|
+
# Prefix each line of text with the original input file
|
|
111
|
+
# it came from.
|
|
112
|
+
# Also remember to encode the text as the zip file
|
|
113
|
+
# stream is in binary mode.
|
|
114
|
+
out_stream.write(f"{basename}: {line}".encode("utf-8"))
|
|
115
|
+
EOF
|
|
116
|
+
python script.py ~{sep(" ", files)}
|
|
117
|
+
>>>
|
|
118
|
+
|
|
119
|
+
output {
|
|
120
|
+
File result = "compressed.zip"
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
runtime {
|
|
124
|
+
container: "python:3.11"
|
|
125
|
+
}
|
|
126
|
+
}
|