toil 6.1.0a1__py3-none-any.whl → 8.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 +122 -315
- toil/batchSystems/__init__.py +1 -0
- toil/batchSystems/abstractBatchSystem.py +173 -89
- toil/batchSystems/abstractGridEngineBatchSystem.py +272 -148
- toil/batchSystems/awsBatch.py +244 -135
- toil/batchSystems/cleanup_support.py +26 -16
- toil/batchSystems/contained_executor.py +31 -28
- toil/batchSystems/gridengine.py +86 -50
- toil/batchSystems/htcondor.py +166 -89
- toil/batchSystems/kubernetes.py +632 -382
- toil/batchSystems/local_support.py +20 -15
- toil/batchSystems/lsf.py +134 -81
- toil/batchSystems/lsfHelper.py +13 -11
- toil/batchSystems/mesos/__init__.py +41 -29
- toil/batchSystems/mesos/batchSystem.py +290 -151
- toil/batchSystems/mesos/executor.py +79 -50
- toil/batchSystems/mesos/test/__init__.py +31 -23
- toil/batchSystems/options.py +46 -28
- toil/batchSystems/registry.py +53 -19
- toil/batchSystems/singleMachine.py +296 -125
- toil/batchSystems/slurm.py +603 -138
- toil/batchSystems/torque.py +47 -33
- toil/bus.py +186 -76
- toil/common.py +664 -368
- toil/cwl/__init__.py +1 -1
- toil/cwl/cwltoil.py +1136 -483
- toil/cwl/utils.py +17 -22
- toil/deferred.py +63 -42
- toil/exceptions.py +5 -3
- toil/fileStores/__init__.py +5 -5
- toil/fileStores/abstractFileStore.py +140 -60
- toil/fileStores/cachingFileStore.py +717 -269
- toil/fileStores/nonCachingFileStore.py +116 -87
- toil/job.py +1225 -368
- toil/jobStores/abstractJobStore.py +416 -266
- toil/jobStores/aws/jobStore.py +863 -477
- toil/jobStores/aws/utils.py +201 -120
- toil/jobStores/conftest.py +3 -2
- toil/jobStores/fileJobStore.py +292 -154
- toil/jobStores/googleJobStore.py +140 -74
- toil/jobStores/utils.py +36 -15
- toil/leader.py +668 -272
- toil/lib/accelerators.py +115 -18
- toil/lib/aws/__init__.py +74 -31
- toil/lib/aws/ami.py +122 -87
- toil/lib/aws/iam.py +284 -108
- toil/lib/aws/s3.py +31 -0
- toil/lib/aws/session.py +214 -39
- toil/lib/aws/utils.py +287 -231
- toil/lib/bioio.py +13 -5
- toil/lib/compatibility.py +11 -6
- toil/lib/conversions.py +104 -47
- toil/lib/docker.py +131 -103
- toil/lib/ec2.py +361 -199
- toil/lib/ec2nodes.py +174 -106
- toil/lib/encryption/_dummy.py +5 -3
- toil/lib/encryption/_nacl.py +10 -6
- toil/lib/encryption/conftest.py +1 -0
- toil/lib/exceptions.py +26 -7
- toil/lib/expando.py +5 -3
- toil/lib/ftp_utils.py +217 -0
- toil/lib/generatedEC2Lists.py +127 -19
- toil/lib/humanize.py +6 -2
- toil/lib/integration.py +341 -0
- toil/lib/io.py +141 -15
- toil/lib/iterables.py +4 -2
- toil/lib/memoize.py +12 -8
- toil/lib/misc.py +66 -21
- toil/lib/objects.py +2 -2
- toil/lib/resources.py +68 -15
- toil/lib/retry.py +126 -81
- toil/lib/threading.py +299 -82
- toil/lib/throttle.py +16 -15
- toil/options/common.py +843 -409
- toil/options/cwl.py +175 -90
- toil/options/runner.py +50 -0
- toil/options/wdl.py +73 -17
- toil/provisioners/__init__.py +117 -46
- toil/provisioners/abstractProvisioner.py +332 -157
- toil/provisioners/aws/__init__.py +70 -33
- toil/provisioners/aws/awsProvisioner.py +1145 -715
- toil/provisioners/clusterScaler.py +541 -279
- toil/provisioners/gceProvisioner.py +282 -179
- toil/provisioners/node.py +155 -79
- toil/realtimeLogger.py +34 -22
- toil/resource.py +137 -75
- toil/server/app.py +128 -62
- toil/server/celery_app.py +3 -1
- toil/server/cli/wes_cwl_runner.py +82 -53
- toil/server/utils.py +54 -28
- toil/server/wes/abstract_backend.py +64 -26
- toil/server/wes/amazon_wes_utils.py +21 -15
- toil/server/wes/tasks.py +121 -63
- toil/server/wes/toil_backend.py +142 -107
- toil/server/wsgi_app.py +4 -3
- toil/serviceManager.py +58 -22
- toil/statsAndLogging.py +224 -70
- toil/test/__init__.py +282 -183
- toil/test/batchSystems/batchSystemTest.py +460 -210
- toil/test/batchSystems/batch_system_plugin_test.py +90 -0
- toil/test/batchSystems/test_gridengine.py +173 -0
- toil/test/batchSystems/test_lsf_helper.py +67 -58
- toil/test/batchSystems/test_slurm.py +110 -49
- toil/test/cactus/__init__.py +0 -0
- toil/test/cactus/test_cactus_integration.py +56 -0
- toil/test/cwl/cwlTest.py +496 -287
- toil/test/cwl/measure_default_memory.cwl +12 -0
- toil/test/cwl/not_run_required_input.cwl +29 -0
- toil/test/cwl/scatter_duplicate_outputs.cwl +40 -0
- toil/test/cwl/seqtk_seq.cwl +1 -1
- toil/test/docs/scriptsTest.py +69 -46
- toil/test/jobStores/jobStoreTest.py +427 -264
- toil/test/lib/aws/test_iam.py +118 -50
- toil/test/lib/aws/test_s3.py +16 -9
- toil/test/lib/aws/test_utils.py +5 -6
- toil/test/lib/dockerTest.py +118 -141
- toil/test/lib/test_conversions.py +113 -115
- toil/test/lib/test_ec2.py +58 -50
- toil/test/lib/test_integration.py +104 -0
- toil/test/lib/test_misc.py +12 -5
- toil/test/mesos/MesosDataStructuresTest.py +23 -10
- toil/test/mesos/helloWorld.py +7 -6
- toil/test/mesos/stress.py +25 -20
- toil/test/options/__init__.py +13 -0
- toil/test/options/options.py +42 -0
- toil/test/provisioners/aws/awsProvisionerTest.py +320 -150
- toil/test/provisioners/clusterScalerTest.py +440 -250
- toil/test/provisioners/clusterTest.py +166 -44
- toil/test/provisioners/gceProvisionerTest.py +174 -100
- toil/test/provisioners/provisionerTest.py +25 -13
- toil/test/provisioners/restartScript.py +5 -4
- toil/test/server/serverTest.py +188 -141
- toil/test/sort/restart_sort.py +137 -68
- toil/test/sort/sort.py +134 -66
- toil/test/sort/sortTest.py +91 -49
- toil/test/src/autoDeploymentTest.py +141 -101
- toil/test/src/busTest.py +20 -18
- toil/test/src/checkpointTest.py +8 -2
- toil/test/src/deferredFunctionTest.py +49 -35
- toil/test/src/dockerCheckTest.py +32 -24
- toil/test/src/environmentTest.py +135 -0
- toil/test/src/fileStoreTest.py +539 -272
- toil/test/src/helloWorldTest.py +7 -4
- toil/test/src/importExportFileTest.py +61 -31
- toil/test/src/jobDescriptionTest.py +46 -21
- toil/test/src/jobEncapsulationTest.py +2 -0
- toil/test/src/jobFileStoreTest.py +74 -50
- toil/test/src/jobServiceTest.py +187 -73
- toil/test/src/jobTest.py +121 -71
- toil/test/src/miscTests.py +19 -18
- toil/test/src/promisedRequirementTest.py +82 -36
- toil/test/src/promisesTest.py +7 -6
- toil/test/src/realtimeLoggerTest.py +10 -6
- toil/test/src/regularLogTest.py +71 -37
- toil/test/src/resourceTest.py +80 -49
- toil/test/src/restartDAGTest.py +36 -22
- toil/test/src/resumabilityTest.py +9 -2
- toil/test/src/retainTempDirTest.py +45 -14
- toil/test/src/systemTest.py +12 -8
- toil/test/src/threadingTest.py +44 -25
- toil/test/src/toilContextManagerTest.py +10 -7
- toil/test/src/userDefinedJobArgTypeTest.py +8 -5
- toil/test/src/workerTest.py +73 -23
- toil/test/utils/toilDebugTest.py +103 -33
- toil/test/utils/toilKillTest.py +4 -5
- toil/test/utils/utilsTest.py +245 -106
- toil/test/wdl/wdltoil_test.py +818 -149
- toil/test/wdl/wdltoil_test_kubernetes.py +91 -0
- toil/toilState.py +120 -35
- toil/utils/toilConfig.py +13 -4
- toil/utils/toilDebugFile.py +44 -27
- toil/utils/toilDebugJob.py +214 -27
- toil/utils/toilDestroyCluster.py +11 -6
- toil/utils/toilKill.py +8 -3
- toil/utils/toilLaunchCluster.py +256 -140
- toil/utils/toilMain.py +37 -16
- toil/utils/toilRsyncCluster.py +32 -14
- toil/utils/toilSshCluster.py +49 -22
- toil/utils/toilStats.py +356 -273
- toil/utils/toilStatus.py +292 -139
- toil/utils/toilUpdateEC2Instances.py +3 -1
- toil/version.py +12 -12
- toil/wdl/utils.py +5 -5
- toil/wdl/wdltoil.py +3913 -1033
- toil/worker.py +367 -184
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/LICENSE +25 -0
- toil-8.0.0.dist-info/METADATA +173 -0
- toil-8.0.0.dist-info/RECORD +253 -0
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/WHEEL +1 -1
- toil-6.1.0a1.dist-info/METADATA +0 -125
- toil-6.1.0a1.dist-info/RECORD +0 -237
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/entry_points.txt +0 -0
- {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/top_level.txt +0 -0
|
@@ -32,46 +32,77 @@ class hidden:
|
|
|
32
32
|
http://stackoverflow.com/questions/1323455/python-unit-test-with-base-and-sub-class#answer-25695512
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
|
-
class AbstractPromisedRequirementsTest(
|
|
35
|
+
class AbstractPromisedRequirementsTest(
|
|
36
|
+
batchSystemTest.hidden.AbstractBatchSystemJobTest
|
|
37
|
+
):
|
|
36
38
|
"""An abstract base class for testing Toil workflows with promised requirements."""
|
|
39
|
+
|
|
37
40
|
@slow
|
|
38
41
|
def testConcurrencyDynamic(self):
|
|
39
42
|
"""
|
|
40
43
|
Asserts that promised core resources are allocated properly using a dynamic Toil workflow
|
|
41
44
|
"""
|
|
42
45
|
for coresPerJob in self.allocatedCores:
|
|
43
|
-
log.debug(
|
|
44
|
-
|
|
46
|
+
log.debug(
|
|
47
|
+
"Testing %d cores per job with CPU count %d",
|
|
48
|
+
coresPerJob,
|
|
49
|
+
self.cpuCount,
|
|
50
|
+
)
|
|
51
|
+
tempDir = self._createTempDir("testFiles")
|
|
45
52
|
counterPath = self.getCounterPath(tempDir)
|
|
46
53
|
|
|
47
|
-
root = Job.wrapJobFn(
|
|
48
|
-
|
|
54
|
+
root = Job.wrapJobFn(
|
|
55
|
+
maxConcurrency,
|
|
56
|
+
self.cpuCount,
|
|
57
|
+
counterPath,
|
|
58
|
+
coresPerJob,
|
|
59
|
+
cores=1,
|
|
60
|
+
memory="1M",
|
|
61
|
+
disk="1M",
|
|
62
|
+
)
|
|
49
63
|
values = Job.Runner.startToil(root, self.getOptions(tempDir))
|
|
50
64
|
maxValue = max(values)
|
|
51
65
|
self.assertLessEqual(maxValue, self.cpuCount // coresPerJob)
|
|
52
66
|
|
|
53
67
|
@slow
|
|
54
|
-
@retry_flaky_test(
|
|
55
|
-
|
|
68
|
+
@retry_flaky_test(
|
|
69
|
+
prepare=[
|
|
70
|
+
batchSystemTest.hidden.AbstractBatchSystemJobTest.tearDown,
|
|
71
|
+
batchSystemTest.hidden.AbstractBatchSystemJobTest.setUp,
|
|
72
|
+
]
|
|
73
|
+
)
|
|
56
74
|
def testConcurrencyStatic(self):
|
|
57
75
|
"""
|
|
58
76
|
Asserts that promised core resources are allocated properly using a static DAG
|
|
59
77
|
"""
|
|
60
78
|
for coresPerJob in self.allocatedCores:
|
|
61
|
-
log.debug(
|
|
62
|
-
|
|
79
|
+
log.debug(
|
|
80
|
+
"Testing %d cores per job with CPU count %d",
|
|
81
|
+
coresPerJob,
|
|
82
|
+
self.cpuCount,
|
|
83
|
+
)
|
|
84
|
+
tempDir = self._createTempDir("testFiles")
|
|
63
85
|
counterPath = self.getCounterPath(tempDir)
|
|
64
86
|
|
|
65
87
|
root = Job()
|
|
66
|
-
one = Job.wrapFn(getOne, cores=0.1, memory=
|
|
67
|
-
thirtyTwoMb = Job.wrapFn(
|
|
88
|
+
one = Job.wrapFn(getOne, cores=0.1, memory="32M", disk="1M")
|
|
89
|
+
thirtyTwoMb = Job.wrapFn(
|
|
90
|
+
getThirtyTwoMb, cores=0.1, memory="32M", disk="1M"
|
|
91
|
+
)
|
|
68
92
|
root.addChild(one)
|
|
69
93
|
root.addChild(thirtyTwoMb)
|
|
70
94
|
for _ in range(self.cpuCount):
|
|
71
|
-
root.addFollowOn(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
95
|
+
root.addFollowOn(
|
|
96
|
+
Job.wrapFn(
|
|
97
|
+
batchSystemTest.measureConcurrency,
|
|
98
|
+
counterPath,
|
|
99
|
+
cores=PromisedRequirement(
|
|
100
|
+
lambda x: x * coresPerJob, one.rv()
|
|
101
|
+
),
|
|
102
|
+
memory=PromisedRequirement(thirtyTwoMb.rv()),
|
|
103
|
+
disk="1M",
|
|
104
|
+
)
|
|
105
|
+
)
|
|
75
106
|
Job.Runner.startToil(root, self.getOptions(tempDir))
|
|
76
107
|
_, maxValue = batchSystemTest.getCounters(counterPath)
|
|
77
108
|
self.assertLessEqual(maxValue, self.cpuCount // coresPerJob)
|
|
@@ -90,7 +121,7 @@ class hidden:
|
|
|
90
121
|
:param str tempDir: path to test directory
|
|
91
122
|
:return: path to counter file
|
|
92
123
|
"""
|
|
93
|
-
counterPath = os.path.join(tempDir,
|
|
124
|
+
counterPath = os.path.join(tempDir, "counter")
|
|
94
125
|
batchSystemTest.resetCounters(counterPath)
|
|
95
126
|
minValue, maxValue = batchSystemTest.getCounters(counterPath)
|
|
96
127
|
assert (minValue, maxValue) == (0, 0)
|
|
@@ -108,13 +139,19 @@ class hidden:
|
|
|
108
139
|
file2 = 512
|
|
109
140
|
F1 = Job.wrapJobFn(_writer, file1)
|
|
110
141
|
F2 = Job.wrapJobFn(_writer, file2)
|
|
111
|
-
G = Job.wrapJobFn(
|
|
112
|
-
|
|
113
|
-
|
|
142
|
+
G = Job.wrapJobFn(
|
|
143
|
+
_follower,
|
|
144
|
+
file1 + file2,
|
|
145
|
+
disk=PromisedRequirement(
|
|
146
|
+
lambda x, y: x.size + y.size, F1.rv(), F2.rv()
|
|
147
|
+
),
|
|
148
|
+
)
|
|
114
149
|
F1.addChild(F2)
|
|
115
150
|
F2.addChild(G)
|
|
116
151
|
|
|
117
|
-
Job.Runner.startToil(
|
|
152
|
+
Job.Runner.startToil(
|
|
153
|
+
F1, self.getOptions(self._createTempDir("testFiles"), caching=caching)
|
|
154
|
+
)
|
|
118
155
|
|
|
119
156
|
def testPromisesWithNonCachingFileStore(self):
|
|
120
157
|
self.testPromisesWithJobStoreFileObjects(caching=False)
|
|
@@ -124,14 +161,18 @@ class hidden:
|
|
|
124
161
|
"""
|
|
125
162
|
Checks for a race condition when using promised requirements and child job functions.
|
|
126
163
|
"""
|
|
127
|
-
A = Job.wrapJobFn(
|
|
128
|
-
|
|
164
|
+
A = Job.wrapJobFn(
|
|
165
|
+
logDiskUsage, "A", sleep=5, disk=PromisedRequirement(1024)
|
|
166
|
+
)
|
|
167
|
+
B = Job.wrapJobFn(
|
|
168
|
+
logDiskUsage, "B", disk=PromisedRequirement(lambda x: x + 1024, A.rv())
|
|
169
|
+
)
|
|
129
170
|
A.addChild(B)
|
|
130
|
-
Job.Runner.startToil(A, self.getOptions(self._createTempDir(
|
|
171
|
+
Job.Runner.startToil(A, self.getOptions(self._createTempDir("testFiles")))
|
|
131
172
|
|
|
132
173
|
|
|
133
174
|
def _writer(job, fileSize):
|
|
134
|
-
|
|
175
|
+
"""
|
|
135
176
|
Write a local file and return the FileID obtained from running writeGlobalFile on
|
|
136
177
|
it.
|
|
137
178
|
|
|
@@ -139,8 +180,8 @@ def _writer(job, fileSize):
|
|
|
139
180
|
:param int fileSize: Size of the file in bytes
|
|
140
181
|
:returns: the result of writeGlobalFile on a locally created file
|
|
141
182
|
:rtype: job.FileID
|
|
142
|
-
|
|
143
|
-
with open(job.fileStore.getLocalTempFileName(),
|
|
183
|
+
"""
|
|
184
|
+
with open(job.fileStore.getLocalTempFileName(), "wb") as fH:
|
|
144
185
|
fH.write(os.urandom(fileSize))
|
|
145
186
|
return job.fileStore.writeGlobalFile(fH.name)
|
|
146
187
|
|
|
@@ -166,15 +207,18 @@ def maxConcurrency(job, cpuCount, filename, coresPerJob):
|
|
|
166
207
|
:param int coresPerJob: number of cores assigned to each job
|
|
167
208
|
:return int max concurrency value:
|
|
168
209
|
"""
|
|
169
|
-
one = job.addChildFn(getOne, cores=0.1, memory=
|
|
170
|
-
thirtyTwoMb = job.addChildFn(getThirtyTwoMb, cores=0.1, memory=
|
|
210
|
+
one = job.addChildFn(getOne, cores=0.1, memory="32M", disk="1M")
|
|
211
|
+
thirtyTwoMb = job.addChildFn(getThirtyTwoMb, cores=0.1, memory="32M", disk="1M")
|
|
171
212
|
|
|
172
213
|
values = []
|
|
173
214
|
for _ in range(cpuCount):
|
|
174
|
-
value = job.addFollowOnFn(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
215
|
+
value = job.addFollowOnFn(
|
|
216
|
+
batchSystemTest.measureConcurrency,
|
|
217
|
+
filename,
|
|
218
|
+
cores=PromisedRequirement(lambda x: x * coresPerJob, one.rv()),
|
|
219
|
+
memory=PromisedRequirement(thirtyTwoMb.rv()),
|
|
220
|
+
disk="1M",
|
|
221
|
+
).rv()
|
|
178
222
|
values.append(value)
|
|
179
223
|
return values
|
|
180
224
|
|
|
@@ -184,7 +228,7 @@ def getOne():
|
|
|
184
228
|
|
|
185
229
|
|
|
186
230
|
def getThirtyTwoMb():
|
|
187
|
-
return
|
|
231
|
+
return "32M"
|
|
188
232
|
|
|
189
233
|
|
|
190
234
|
def logDiskUsage(job, funcName, sleep=0):
|
|
@@ -194,7 +238,7 @@ def logDiskUsage(job, funcName, sleep=0):
|
|
|
194
238
|
:return: job function's disk usage
|
|
195
239
|
"""
|
|
196
240
|
diskUsage = job.disk
|
|
197
|
-
job.fileStore.log_to_leader(f
|
|
241
|
+
job.fileStore.log_to_leader(f"{funcName}: {diskUsage}")
|
|
198
242
|
time.sleep(sleep)
|
|
199
243
|
return diskUsage
|
|
200
244
|
|
|
@@ -212,14 +256,16 @@ class SingleMachinePromisedRequirementsTest(hidden.AbstractPromisedRequirementsT
|
|
|
212
256
|
|
|
213
257
|
|
|
214
258
|
@needs_mesos
|
|
215
|
-
class MesosPromisedRequirementsTest(
|
|
259
|
+
class MesosPromisedRequirementsTest(
|
|
260
|
+
hidden.AbstractPromisedRequirementsTest, MesosTestSupport
|
|
261
|
+
):
|
|
216
262
|
"""
|
|
217
263
|
Tests against the Mesos batch system
|
|
218
264
|
"""
|
|
219
265
|
|
|
220
266
|
def getOptions(self, tempDir, caching=True):
|
|
221
267
|
options = super().getOptions(tempDir, caching=caching)
|
|
222
|
-
options.mesos_endpoint =
|
|
268
|
+
options.mesos_endpoint = "localhost:5050"
|
|
223
269
|
return options
|
|
224
270
|
|
|
225
271
|
def getBatchSystemName(self):
|
toil/test/src/promisesTest.py
CHANGED
|
@@ -23,7 +23,7 @@ class CachedUnpicklingJobStoreTest(ToilTest):
|
|
|
23
23
|
"""
|
|
24
24
|
for _ in range(2):
|
|
25
25
|
options = Job.Runner.getDefaultOptions(self._getTestJobStorePath())
|
|
26
|
-
options.logLevel =
|
|
26
|
+
options.logLevel = "INFO"
|
|
27
27
|
root = Job.wrapJobFn(parent)
|
|
28
28
|
Job.Runner.startToil(root, options)
|
|
29
29
|
|
|
@@ -40,7 +40,7 @@ class ChainedIndexedPromisesTest(ToilTest):
|
|
|
40
40
|
# https://github.com/BD2KGenomics/toil/issues/1021
|
|
41
41
|
def test(self):
|
|
42
42
|
options = Job.Runner.getDefaultOptions(self._getTestJobStorePath())
|
|
43
|
-
options.logLevel =
|
|
43
|
+
options.logLevel = "INFO"
|
|
44
44
|
root = Job.wrapJobFn(a)
|
|
45
45
|
self.assertEqual(Job.Runner.startToil(root, options), 42)
|
|
46
46
|
|
|
@@ -62,17 +62,18 @@ class PathIndexingPromiseTest(ToilTest):
|
|
|
62
62
|
Test support for indexing promises of arbitrarily nested data structures of lists, dicts and
|
|
63
63
|
tuples, or any other object supporting the __getitem__() protocol.
|
|
64
64
|
"""
|
|
65
|
+
|
|
65
66
|
def test(self):
|
|
66
67
|
options = Job.Runner.getDefaultOptions(self._getTestJobStorePath())
|
|
67
|
-
options.logLevel =
|
|
68
|
+
options.logLevel = "INFO"
|
|
68
69
|
root = Job.wrapJobFn(d)
|
|
69
|
-
self.assertEqual(Job.Runner.startToil(root, options), (
|
|
70
|
+
self.assertEqual(Job.Runner.startToil(root, options), ("b", 43, 3))
|
|
70
71
|
|
|
71
72
|
|
|
72
73
|
def d(job):
|
|
73
74
|
child = job.addChild(job.wrapFn(e))
|
|
74
|
-
return child.rv(
|
|
75
|
+
return child.rv("a"), child.rv(42), child.rv("c", 2)
|
|
75
76
|
|
|
76
77
|
|
|
77
78
|
def e():
|
|
78
|
-
return {
|
|
79
|
+
return {"a": "b", 42: 43, "c": [1, 2, 3]}
|
|
@@ -23,13 +23,16 @@ class RealtimeLoggerTest(ToilTest):
|
|
|
23
23
|
def testRealtimeLogger(self):
|
|
24
24
|
options = Job.Runner.getDefaultOptions(self._getTestJobStorePath())
|
|
25
25
|
options.realTimeLogging = True
|
|
26
|
-
options.logLevel =
|
|
26
|
+
options.logLevel = "INFO"
|
|
27
27
|
|
|
28
28
|
detector = MessageDetector()
|
|
29
29
|
|
|
30
30
|
# Set up a log message detector to the root logger
|
|
31
31
|
logging.getLogger().addHandler(detector)
|
|
32
32
|
|
|
33
|
+
# I believe coloredlogs replaces handlers with its own when doing handler formatting, preserving only filters
|
|
34
|
+
# https://github.com/xolox/python-coloredlogs/blob/65bdfe976ac0bf81e8c0bd9a98242b9d666b2859/coloredlogs/__init__.py#L453-L459
|
|
35
|
+
options.colored_logs = False
|
|
33
36
|
Job.Runner.startToil(LogTest(), options)
|
|
34
37
|
|
|
35
38
|
# We need the message we're supposed to see
|
|
@@ -46,19 +49,20 @@ class MessageDetector(logging.StreamHandler):
|
|
|
46
49
|
def __init__(self):
|
|
47
50
|
self.detected = False # Have we seen the message we want?
|
|
48
51
|
self.overLogged = False # Have we seen the message we don't want?
|
|
52
|
+
|
|
49
53
|
super().__init__()
|
|
50
54
|
|
|
51
55
|
def emit(self, record):
|
|
52
|
-
if record.msg ==
|
|
56
|
+
if record.msg == "This should be logged at info level":
|
|
53
57
|
self.detected = True
|
|
54
|
-
if record.msg ==
|
|
58
|
+
if record.msg == "This should be logged at debug level":
|
|
55
59
|
self.overLogged = True
|
|
56
60
|
|
|
57
61
|
|
|
58
62
|
class LogTest(Job):
|
|
59
63
|
def __init__(self):
|
|
60
|
-
Job.__init__(self, memory=100000, cores=1, disk=
|
|
64
|
+
Job.__init__(self, memory=100000, cores=1, disk="3G")
|
|
61
65
|
|
|
62
66
|
def run(self, fileStore):
|
|
63
|
-
RealtimeLogger.info(
|
|
64
|
-
RealtimeLogger.debug(
|
|
67
|
+
RealtimeLogger.info("This should be logged at info level")
|
|
68
|
+
RealtimeLogger.debug("This should be logged at debug level")
|
toil/test/src/regularLogTest.py
CHANGED
|
@@ -28,10 +28,14 @@ class RegularLogTest(ToilTest):
|
|
|
28
28
|
|
|
29
29
|
def setUp(self) -> None:
|
|
30
30
|
super().setUp()
|
|
31
|
-
self.tempDir = self._createTempDir(purpose=
|
|
31
|
+
self.tempDir = self._createTempDir(purpose="tempDir")
|
|
32
32
|
|
|
33
33
|
def _getFiles(self, dir):
|
|
34
|
-
return [
|
|
34
|
+
return [
|
|
35
|
+
os.path.join(dir, f)
|
|
36
|
+
for f in os.listdir(dir)
|
|
37
|
+
if os.path.isfile(os.path.join(dir, f))
|
|
38
|
+
]
|
|
35
39
|
|
|
36
40
|
def _assertFileTypeExists(self, dir, extension, encoding=None):
|
|
37
41
|
# an encoding of None implies no compression
|
|
@@ -45,56 +49,86 @@ class RegularLogTest(ToilTest):
|
|
|
45
49
|
if encoding is not None:
|
|
46
50
|
for log in onlyLogs:
|
|
47
51
|
with open(log, "rb") as f:
|
|
48
|
-
logger.info(
|
|
52
|
+
logger.info(
|
|
53
|
+
"Checking for encoding %s on file %s", str(encoding), log
|
|
54
|
+
)
|
|
49
55
|
if encoding == "gzip":
|
|
50
56
|
# Check for gzip magic header '\x1f\x8b'
|
|
51
|
-
assert f.read().startswith(b
|
|
57
|
+
assert f.read().startswith(b"\x1f\x8b")
|
|
52
58
|
else:
|
|
53
59
|
mime = mimetypes.guess_type(log)
|
|
54
60
|
self.assertEqual(mime[1], encoding)
|
|
55
61
|
|
|
56
62
|
@slow
|
|
57
63
|
def testLogToMaster(self):
|
|
58
|
-
toilOutput = subprocess.check_output(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
toilOutput = subprocess.check_output(
|
|
65
|
+
[
|
|
66
|
+
sys.executable,
|
|
67
|
+
"-m",
|
|
68
|
+
helloWorld.__name__,
|
|
69
|
+
"./toilTest",
|
|
70
|
+
"--clean=always",
|
|
71
|
+
"--logLevel=info",
|
|
72
|
+
],
|
|
73
|
+
stderr=subprocess.STDOUT,
|
|
74
|
+
)
|
|
75
|
+
assert helloWorld.childMessage in toilOutput.decode("utf-8")
|
|
64
76
|
|
|
65
77
|
def testWriteLogs(self):
|
|
66
|
-
subprocess.check_call(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
78
|
+
subprocess.check_call(
|
|
79
|
+
[
|
|
80
|
+
sys.executable,
|
|
81
|
+
"-m",
|
|
82
|
+
helloWorld.__name__,
|
|
83
|
+
"./toilTest",
|
|
84
|
+
"--clean=always",
|
|
85
|
+
"--logLevel=debug",
|
|
86
|
+
"--writeLogs=%s" % self.tempDir,
|
|
87
|
+
]
|
|
88
|
+
)
|
|
89
|
+
self._assertFileTypeExists(self.tempDir, ".log")
|
|
73
90
|
|
|
74
91
|
@slow
|
|
75
92
|
def testWriteGzipLogs(self):
|
|
76
|
-
subprocess.check_call(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
93
|
+
subprocess.check_call(
|
|
94
|
+
[
|
|
95
|
+
sys.executable,
|
|
96
|
+
"-m",
|
|
97
|
+
helloWorld.__name__,
|
|
98
|
+
"./toilTest",
|
|
99
|
+
"--clean=always",
|
|
100
|
+
"--logLevel=debug",
|
|
101
|
+
"--writeLogsGzip=%s" % self.tempDir,
|
|
102
|
+
]
|
|
103
|
+
)
|
|
104
|
+
self._assertFileTypeExists(self.tempDir, ".log.gz", "gzip")
|
|
83
105
|
|
|
84
106
|
@slow
|
|
85
107
|
def testMultipleLogToMaster(self):
|
|
86
|
-
toilOutput = subprocess.check_output(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
108
|
+
toilOutput = subprocess.check_output(
|
|
109
|
+
[
|
|
110
|
+
sys.executable,
|
|
111
|
+
"-m",
|
|
112
|
+
helloWorld.__name__,
|
|
113
|
+
"./toilTest",
|
|
114
|
+
"--clean=always",
|
|
115
|
+
"--logLevel=info",
|
|
116
|
+
],
|
|
117
|
+
stderr=subprocess.STDOUT,
|
|
118
|
+
)
|
|
119
|
+
assert helloWorld.parentMessage in toilOutput.decode("utf-8")
|
|
92
120
|
|
|
93
121
|
def testRegularLog(self):
|
|
94
|
-
toilOutput = subprocess.check_output(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
122
|
+
toilOutput = subprocess.check_output(
|
|
123
|
+
[
|
|
124
|
+
sys.executable,
|
|
125
|
+
"-m",
|
|
126
|
+
helloWorld.__name__,
|
|
127
|
+
"./toilTest",
|
|
128
|
+
"--clean=always",
|
|
129
|
+
"--batchSystem=single_machine",
|
|
130
|
+
"--logLevel=debug",
|
|
131
|
+
],
|
|
132
|
+
stderr=subprocess.STDOUT,
|
|
133
|
+
)
|
|
134
|
+
assert "single machine batch system" in toilOutput.decode("utf-8")
|