toil 5.12.0__py3-none-any.whl → 6.1.0a1__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 +18 -13
- toil/batchSystems/abstractBatchSystem.py +21 -10
- toil/batchSystems/abstractGridEngineBatchSystem.py +2 -2
- toil/batchSystems/awsBatch.py +14 -14
- toil/batchSystems/contained_executor.py +3 -3
- toil/batchSystems/htcondor.py +0 -1
- toil/batchSystems/kubernetes.py +34 -31
- toil/batchSystems/local_support.py +3 -1
- toil/batchSystems/mesos/batchSystem.py +7 -7
- toil/batchSystems/options.py +32 -83
- toil/batchSystems/registry.py +104 -23
- toil/batchSystems/singleMachine.py +16 -13
- toil/batchSystems/slurm.py +3 -3
- toil/batchSystems/torque.py +0 -1
- toil/bus.py +6 -8
- toil/common.py +532 -743
- toil/cwl/__init__.py +28 -32
- toil/cwl/cwltoil.py +523 -520
- toil/cwl/utils.py +55 -10
- toil/fileStores/__init__.py +2 -2
- toil/fileStores/abstractFileStore.py +36 -11
- toil/fileStores/cachingFileStore.py +607 -530
- toil/fileStores/nonCachingFileStore.py +43 -10
- toil/job.py +140 -75
- toil/jobStores/abstractJobStore.py +147 -79
- toil/jobStores/aws/jobStore.py +23 -9
- toil/jobStores/aws/utils.py +1 -2
- toil/jobStores/fileJobStore.py +117 -19
- toil/jobStores/googleJobStore.py +16 -7
- toil/jobStores/utils.py +5 -6
- toil/leader.py +71 -43
- toil/lib/accelerators.py +10 -5
- toil/lib/aws/__init__.py +3 -14
- toil/lib/aws/ami.py +22 -9
- toil/lib/aws/iam.py +21 -13
- toil/lib/aws/session.py +2 -16
- toil/lib/aws/utils.py +4 -5
- toil/lib/compatibility.py +1 -1
- toil/lib/conversions.py +7 -3
- toil/lib/docker.py +22 -23
- toil/lib/ec2.py +10 -6
- toil/lib/ec2nodes.py +106 -100
- toil/lib/encryption/_nacl.py +2 -1
- toil/lib/generatedEC2Lists.py +325 -18
- toil/lib/io.py +21 -0
- toil/lib/misc.py +1 -1
- toil/lib/resources.py +1 -1
- toil/lib/threading.py +74 -26
- toil/options/common.py +738 -0
- toil/options/cwl.py +336 -0
- toil/options/wdl.py +32 -0
- toil/provisioners/abstractProvisioner.py +1 -4
- toil/provisioners/aws/__init__.py +3 -6
- toil/provisioners/aws/awsProvisioner.py +6 -0
- toil/provisioners/clusterScaler.py +3 -2
- toil/provisioners/gceProvisioner.py +2 -2
- toil/realtimeLogger.py +2 -1
- toil/resource.py +24 -18
- toil/server/app.py +2 -3
- toil/server/cli/wes_cwl_runner.py +4 -4
- toil/server/utils.py +1 -1
- toil/server/wes/abstract_backend.py +3 -2
- toil/server/wes/amazon_wes_utils.py +5 -4
- toil/server/wes/tasks.py +2 -3
- toil/server/wes/toil_backend.py +2 -10
- toil/server/wsgi_app.py +2 -0
- toil/serviceManager.py +12 -10
- toil/statsAndLogging.py +5 -1
- toil/test/__init__.py +29 -54
- toil/test/batchSystems/batchSystemTest.py +11 -111
- toil/test/batchSystems/test_slurm.py +3 -2
- toil/test/cwl/cwlTest.py +213 -90
- toil/test/cwl/glob_dir.cwl +15 -0
- toil/test/cwl/preemptible.cwl +21 -0
- toil/test/cwl/preemptible_expression.cwl +28 -0
- toil/test/cwl/revsort.cwl +1 -1
- toil/test/cwl/revsort2.cwl +1 -1
- toil/test/docs/scriptsTest.py +0 -1
- toil/test/jobStores/jobStoreTest.py +27 -16
- toil/test/lib/aws/test_iam.py +4 -14
- toil/test/lib/aws/test_utils.py +0 -3
- toil/test/lib/dockerTest.py +4 -4
- toil/test/lib/test_ec2.py +11 -16
- toil/test/mesos/helloWorld.py +4 -5
- toil/test/mesos/stress.py +1 -1
- toil/test/provisioners/aws/awsProvisionerTest.py +9 -5
- toil/test/provisioners/clusterScalerTest.py +6 -4
- toil/test/provisioners/clusterTest.py +14 -3
- toil/test/provisioners/gceProvisionerTest.py +0 -6
- toil/test/provisioners/restartScript.py +3 -2
- toil/test/server/serverTest.py +1 -1
- toil/test/sort/restart_sort.py +2 -1
- toil/test/sort/sort.py +2 -1
- toil/test/sort/sortTest.py +2 -13
- toil/test/src/autoDeploymentTest.py +45 -45
- toil/test/src/busTest.py +5 -5
- toil/test/src/checkpointTest.py +2 -2
- toil/test/src/deferredFunctionTest.py +1 -1
- toil/test/src/fileStoreTest.py +32 -16
- toil/test/src/helloWorldTest.py +1 -1
- toil/test/src/importExportFileTest.py +1 -1
- toil/test/src/jobDescriptionTest.py +2 -1
- toil/test/src/jobServiceTest.py +1 -1
- toil/test/src/jobTest.py +18 -18
- toil/test/src/miscTests.py +5 -3
- toil/test/src/promisedRequirementTest.py +3 -3
- toil/test/src/realtimeLoggerTest.py +1 -1
- toil/test/src/resourceTest.py +2 -2
- toil/test/src/restartDAGTest.py +1 -1
- toil/test/src/resumabilityTest.py +36 -2
- toil/test/src/retainTempDirTest.py +1 -1
- toil/test/src/systemTest.py +2 -2
- toil/test/src/toilContextManagerTest.py +2 -2
- toil/test/src/userDefinedJobArgTypeTest.py +1 -1
- toil/test/utils/toilDebugTest.py +98 -32
- toil/test/utils/toilKillTest.py +2 -2
- toil/test/utils/utilsTest.py +20 -0
- toil/test/wdl/wdltoil_test.py +148 -45
- toil/toilState.py +7 -6
- toil/utils/toilClean.py +1 -1
- toil/utils/toilConfig.py +36 -0
- toil/utils/toilDebugFile.py +60 -33
- toil/utils/toilDebugJob.py +39 -12
- toil/utils/toilDestroyCluster.py +1 -1
- toil/utils/toilKill.py +1 -1
- toil/utils/toilLaunchCluster.py +13 -2
- toil/utils/toilMain.py +3 -2
- toil/utils/toilRsyncCluster.py +1 -1
- toil/utils/toilSshCluster.py +1 -1
- toil/utils/toilStats.py +240 -143
- toil/utils/toilStatus.py +1 -4
- toil/version.py +11 -11
- toil/wdl/utils.py +2 -122
- toil/wdl/wdltoil.py +999 -386
- toil/worker.py +25 -31
- {toil-5.12.0.dist-info → toil-6.1.0a1.dist-info}/METADATA +60 -53
- toil-6.1.0a1.dist-info/RECORD +237 -0
- {toil-5.12.0.dist-info → toil-6.1.0a1.dist-info}/WHEEL +1 -1
- {toil-5.12.0.dist-info → toil-6.1.0a1.dist-info}/entry_points.txt +0 -1
- toil/batchSystems/parasol.py +0 -379
- toil/batchSystems/tes.py +0 -459
- toil/test/batchSystems/parasolTestSupport.py +0 -117
- toil/test/wdl/builtinTest.py +0 -506
- toil/test/wdl/conftest.py +0 -23
- toil/test/wdl/toilwdlTest.py +0 -522
- toil/wdl/toilwdl.py +0 -141
- toil/wdl/versions/dev.py +0 -107
- toil/wdl/versions/draft2.py +0 -980
- toil/wdl/versions/v1.py +0 -794
- toil/wdl/wdl_analysis.py +0 -116
- toil/wdl/wdl_functions.py +0 -997
- toil/wdl/wdl_synthesis.py +0 -1011
- toil/wdl/wdl_types.py +0 -243
- toil-5.12.0.dist-info/RECORD +0 -244
- /toil/{wdl/versions → options}/__init__.py +0 -0
- {toil-5.12.0.dist-info → toil-6.1.0a1.dist-info}/LICENSE +0 -0
- {toil-5.12.0.dist-info → toil-6.1.0a1.dist-info}/top_level.txt +0 -0
toil/batchSystems/options.py
CHANGED
|
@@ -12,19 +12,18 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
|
|
14
14
|
import logging
|
|
15
|
-
import os
|
|
16
15
|
import sys
|
|
17
16
|
from argparse import ArgumentParser, _ArgumentGroup
|
|
18
|
-
from typing import Any, Callable, List, Optional, TypeVar, Union
|
|
17
|
+
from typing import Any, Callable, List, Optional, TypeVar, Union
|
|
19
18
|
|
|
20
19
|
if sys.version_info >= (3, 8):
|
|
21
20
|
from typing import Protocol
|
|
22
21
|
else:
|
|
23
22
|
from typing_extensions import Protocol
|
|
24
23
|
|
|
25
|
-
from toil.batchSystems.registry import (
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
from toil.batchSystems.registry import (DEFAULT_BATCH_SYSTEM,
|
|
25
|
+
get_batch_system,
|
|
26
|
+
get_batch_systems)
|
|
28
27
|
from toil.lib.threading import cpu_count
|
|
29
28
|
|
|
30
29
|
logger = logging.getLogger(__name__)
|
|
@@ -56,60 +55,62 @@ def set_batchsystem_options(batch_system: Optional[str], set_option: OptionSette
|
|
|
56
55
|
"""
|
|
57
56
|
if batch_system is not None:
|
|
58
57
|
# Use this batch system
|
|
59
|
-
batch_system_type =
|
|
58
|
+
batch_system_type = get_batch_system(batch_system)
|
|
60
59
|
batch_system_type.setOptions(set_option)
|
|
61
60
|
else:
|
|
62
|
-
for
|
|
61
|
+
for name in get_batch_systems():
|
|
63
62
|
# All the batch systems are responsible for setting their own options
|
|
64
63
|
# with their setOptions() class methods.
|
|
65
64
|
try:
|
|
66
|
-
batch_system_type =
|
|
65
|
+
batch_system_type = get_batch_system(name)
|
|
67
66
|
except ImportError:
|
|
68
67
|
# Skip anything we can't import
|
|
69
68
|
continue
|
|
70
69
|
# Ask the batch system to tell us all its options.
|
|
71
70
|
batch_system_type.setOptions(set_option)
|
|
72
71
|
# Options shared between multiple batch systems
|
|
73
|
-
set_option("disableAutoDeployment"
|
|
72
|
+
set_option("disableAutoDeployment")
|
|
74
73
|
# Make limits maximum if set to 0
|
|
75
|
-
set_option("max_jobs"
|
|
76
|
-
set_option("max_local_jobs"
|
|
74
|
+
set_option("max_jobs")
|
|
75
|
+
set_option("max_local_jobs")
|
|
77
76
|
set_option("manualMemArgs")
|
|
78
|
-
set_option("run_local_jobs_on_workers"
|
|
77
|
+
set_option("run_local_jobs_on_workers")
|
|
79
78
|
set_option("statePollingWait")
|
|
80
|
-
set_option("batch_logs_dir"
|
|
79
|
+
set_option("batch_logs_dir")
|
|
81
80
|
|
|
82
81
|
|
|
83
82
|
def add_all_batchsystem_options(parser: Union[ArgumentParser, _ArgumentGroup]) -> None:
|
|
83
|
+
from toil.options.common import SYS_MAX_SIZE
|
|
84
|
+
|
|
84
85
|
# Do the global cross-batch-system arguments
|
|
85
86
|
parser.add_argument(
|
|
86
87
|
"--batchSystem",
|
|
87
88
|
dest="batchSystem",
|
|
88
89
|
default=DEFAULT_BATCH_SYSTEM,
|
|
89
|
-
choices=
|
|
90
|
+
choices=get_batch_systems(),
|
|
90
91
|
help=f"The type of batch system to run the job(s) with, currently can be one "
|
|
91
|
-
f"of {', '.join(
|
|
92
|
+
f"of {', '.join(get_batch_systems())}. Default = {DEFAULT_BATCH_SYSTEM}",
|
|
92
93
|
)
|
|
93
94
|
parser.add_argument(
|
|
94
95
|
"--disableHotDeployment",
|
|
95
96
|
dest="disableAutoDeployment",
|
|
97
|
+
default=False,
|
|
96
98
|
action="store_true",
|
|
97
|
-
default=None,
|
|
98
99
|
help="Hot-deployment was renamed to auto-deployment. Option now redirects to "
|
|
99
|
-
"--disableAutoDeployment.
|
|
100
|
+
"--disableAutoDeployment. Left in for backwards compatibility.",
|
|
100
101
|
)
|
|
101
102
|
parser.add_argument(
|
|
102
103
|
"--disableAutoDeployment",
|
|
103
104
|
dest="disableAutoDeployment",
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"script/package should be present at the same location on all workers. Default = False.",
|
|
105
|
+
default=False,
|
|
106
|
+
help="Should auto-deployment of Toil Python workflows be deactivated? If True, the workflow's "
|
|
107
|
+
"Python code should be present at the same location on all workers. Default = False.",
|
|
108
108
|
)
|
|
109
109
|
parser.add_argument(
|
|
110
110
|
"--maxJobs",
|
|
111
111
|
dest="max_jobs",
|
|
112
|
-
default=
|
|
112
|
+
default=SYS_MAX_SIZE, # This is *basically* unlimited and saves a lot of Optional[]
|
|
113
|
+
type=lambda x: int(x) or SYS_MAX_SIZE,
|
|
113
114
|
help="Specifies the maximum number of jobs to submit to the "
|
|
114
115
|
"backing scheduler at once. Not supported on Mesos or "
|
|
115
116
|
"AWS Batch. Use 0 for unlimited. Defaults to unlimited.",
|
|
@@ -117,7 +118,8 @@ def add_all_batchsystem_options(parser: Union[ArgumentParser, _ArgumentGroup]) -
|
|
|
117
118
|
parser.add_argument(
|
|
118
119
|
"--maxLocalJobs",
|
|
119
120
|
dest="max_local_jobs",
|
|
120
|
-
default=
|
|
121
|
+
default=None,
|
|
122
|
+
type=lambda x: int(x) or 0,
|
|
121
123
|
help=f"Specifies the maximum number of housekeeping jobs to "
|
|
122
124
|
f"run sumultaneously on the local system. Use 0 for "
|
|
123
125
|
f"unlimited. Defaults to the number of local cores ({cpu_count()}).",
|
|
@@ -125,18 +127,18 @@ def add_all_batchsystem_options(parser: Union[ArgumentParser, _ArgumentGroup]) -
|
|
|
125
127
|
parser.add_argument(
|
|
126
128
|
"--manualMemArgs",
|
|
127
129
|
default=False,
|
|
128
|
-
action="store_true",
|
|
129
130
|
dest="manualMemArgs",
|
|
131
|
+
action="store_true",
|
|
130
132
|
help="Do not add the default arguments: 'hv=MEMORY' & 'h_vmem=MEMORY' to the qsub "
|
|
131
133
|
"call, and instead rely on TOIL_GRIDGENGINE_ARGS to supply alternative arguments. "
|
|
132
134
|
"Requires that TOIL_GRIDGENGINE_ARGS be set.",
|
|
133
135
|
)
|
|
134
136
|
parser.add_argument(
|
|
135
|
-
"--runLocalJobsOnWorkers"
|
|
137
|
+
"--runLocalJobsOnWorkers",
|
|
136
138
|
"--runCwlInternalJobsOnWorkers",
|
|
137
139
|
dest="run_local_jobs_on_workers",
|
|
140
|
+
default=False,
|
|
138
141
|
action="store_true",
|
|
139
|
-
default=None,
|
|
140
142
|
help="Whether to run jobs marked as local (e.g. CWLScatter) on the worker nodes "
|
|
141
143
|
"instead of the leader node. If false (default), then all such jobs are run on "
|
|
142
144
|
"the leader node. Setting this to true can speed up CWL pipelines for very large "
|
|
@@ -166,6 +168,7 @@ def add_all_batchsystem_options(parser: Union[ArgumentParser, _ArgumentGroup]) -
|
|
|
166
168
|
"--batchLogsDir",
|
|
167
169
|
dest="batch_logs_dir",
|
|
168
170
|
default=None,
|
|
171
|
+
env_var="TOIL_BATCH_LOGS_DIR",
|
|
169
172
|
help="Directory to tell the backing batch system to log into. Should be available "
|
|
170
173
|
"on both the leader and the workers, if the backing batch system writes logs "
|
|
171
174
|
"to the worker machines' filesystems, as many HPC schedulers do. If unset, "
|
|
@@ -173,68 +176,14 @@ def add_all_batchsystem_options(parser: Union[ArgumentParser, _ArgumentGroup]) -
|
|
|
173
176
|
"systems such as gridengine, htcondor, torque, slurm, and lsf."
|
|
174
177
|
)
|
|
175
178
|
|
|
176
|
-
for
|
|
179
|
+
for name in get_batch_systems():
|
|
177
180
|
# All the batch systems are responsible for adding their own options
|
|
178
181
|
# with the add_options class method.
|
|
179
182
|
try:
|
|
180
|
-
batch_system_type =
|
|
183
|
+
batch_system_type = get_batch_system(name)
|
|
181
184
|
except ImportError:
|
|
182
185
|
# Skip anything we can't import
|
|
183
186
|
continue
|
|
184
187
|
# Ask the batch system to create its options in the parser
|
|
185
|
-
logger.debug('Add options for %s',
|
|
188
|
+
logger.debug('Add options for %s batch system', name)
|
|
186
189
|
batch_system_type.add_options(parser)
|
|
187
|
-
|
|
188
|
-
def set_batchsystem_config_defaults(config) -> None:
|
|
189
|
-
"""
|
|
190
|
-
Set default and environment-based options for builtin batch systems. This
|
|
191
|
-
is required if a Config object is not constructed from an Options object.
|
|
192
|
-
"""
|
|
193
|
-
|
|
194
|
-
# Do the global options across batch systems
|
|
195
|
-
config.batchSystem = "single_machine"
|
|
196
|
-
config.disableAutoDeployment = False
|
|
197
|
-
config.max_jobs = sys.maxsize
|
|
198
|
-
config.max_local_jobs = cpu_count()
|
|
199
|
-
config.manualMemArgs = False
|
|
200
|
-
config.statePollingWait: Optional[Union[float, int]] = None # Number of seconds to wait before querying job state
|
|
201
|
-
|
|
202
|
-
OptionType = TypeVar('OptionType')
|
|
203
|
-
def set_option(option_name: str,
|
|
204
|
-
parsing_function: Optional[Callable[[Any], OptionType]] = None,
|
|
205
|
-
check_function: Optional[Callable[[OptionType], None]] = None,
|
|
206
|
-
default: Optional[OptionType] = None,
|
|
207
|
-
env: Optional[List[str]] = None,
|
|
208
|
-
old_names: Optional[List[str]] = None) -> None:
|
|
209
|
-
"""
|
|
210
|
-
Function to set a batch-system-defined option to its default value, or
|
|
211
|
-
one from the environment.
|
|
212
|
-
"""
|
|
213
|
-
|
|
214
|
-
# TODO: deduplicate with Config
|
|
215
|
-
|
|
216
|
-
option_value = default
|
|
217
|
-
|
|
218
|
-
if env is not None:
|
|
219
|
-
for env_var in env:
|
|
220
|
-
# Try all the environment variables
|
|
221
|
-
if option_value != default:
|
|
222
|
-
break
|
|
223
|
-
option_value = os.environ.get(env_var, default)
|
|
224
|
-
|
|
225
|
-
if option_value is not None or not hasattr(config, option_name):
|
|
226
|
-
if parsing_function is not None:
|
|
227
|
-
# Parse whatever it is (string, argparse-made list, etc.)
|
|
228
|
-
option_value = parsing_function(option_value)
|
|
229
|
-
if check_function is not None:
|
|
230
|
-
try:
|
|
231
|
-
check_function(option_value)
|
|
232
|
-
except AssertionError:
|
|
233
|
-
raise RuntimeError(f"The {option_name} option has an invalid value: {option_value}")
|
|
234
|
-
setattr(config, option_name, option_value)
|
|
235
|
-
|
|
236
|
-
# Set up defaults from all the batch systems
|
|
237
|
-
set_batchsystem_options(None, cast(OptionSetter, set_option))
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
toil/batchSystems/registry.py
CHANGED
|
@@ -12,14 +12,58 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import importlib
|
|
15
16
|
import logging
|
|
16
|
-
|
|
17
|
+
import pkgutil
|
|
18
|
+
import warnings
|
|
19
|
+
from typing import TYPE_CHECKING, Callable, Dict, List, Sequence, Tuple, Type
|
|
20
|
+
|
|
21
|
+
from toil.lib.compatibility import deprecated
|
|
22
|
+
from toil.lib.memoize import memoize
|
|
17
23
|
|
|
18
24
|
if TYPE_CHECKING:
|
|
19
25
|
from toil.batchSystems.abstractBatchSystem import AbstractBatchSystem
|
|
20
26
|
|
|
21
27
|
logger = logging.getLogger(__name__)
|
|
22
28
|
|
|
29
|
+
#####
|
|
30
|
+
# Plugin system/API
|
|
31
|
+
#####
|
|
32
|
+
|
|
33
|
+
def add_batch_system_factory(key: str, class_factory: Callable[[], Type['AbstractBatchSystem']]):
|
|
34
|
+
"""
|
|
35
|
+
Adds a batch system to the registry for workflow or plugin-supplied batch systems.
|
|
36
|
+
|
|
37
|
+
:param class_factory: A function that returns a batch system class (NOT an instance), which implements :class:`toil.batchSystems.abstractBatchSystem.AbstractBatchSystem`.
|
|
38
|
+
"""
|
|
39
|
+
_registry_keys.append(key)
|
|
40
|
+
_registry[key] = class_factory
|
|
41
|
+
|
|
42
|
+
def get_batch_systems() -> Sequence[str]:
|
|
43
|
+
"""
|
|
44
|
+
Get the names of all the availsble batch systems.
|
|
45
|
+
"""
|
|
46
|
+
_load_all_plugins()
|
|
47
|
+
|
|
48
|
+
return _registry_keys
|
|
49
|
+
|
|
50
|
+
def get_batch_system(key: str) -> Type['AbstractBatchSystem']:
|
|
51
|
+
"""
|
|
52
|
+
Get a batch system class by name.
|
|
53
|
+
|
|
54
|
+
:raises: KeyError if the key is not the name of a batch system, and
|
|
55
|
+
ImportError if the batch system's class cannot be loaded.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
return _registry[key]()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
DEFAULT_BATCH_SYSTEM = 'single_machine'
|
|
62
|
+
|
|
63
|
+
#####
|
|
64
|
+
# Built-in batch systems
|
|
65
|
+
#####
|
|
66
|
+
|
|
23
67
|
def aws_batch_batch_system_factory():
|
|
24
68
|
from toil.batchSystems.awsBatch import AWSBatchBatchSystem
|
|
25
69
|
return AWSBatchBatchSystem
|
|
@@ -29,11 +73,6 @@ def gridengine_batch_system_factory():
|
|
|
29
73
|
return GridEngineBatchSystem
|
|
30
74
|
|
|
31
75
|
|
|
32
|
-
def parasol_batch_system_factory():
|
|
33
|
-
from toil.batchSystems.parasol import ParasolBatchSystem
|
|
34
|
-
return ParasolBatchSystem
|
|
35
|
-
|
|
36
|
-
|
|
37
76
|
def lsf_batch_system_factory():
|
|
38
77
|
from toil.batchSystems.lsf import LSFBatchSystem
|
|
39
78
|
return LSFBatchSystem
|
|
@@ -53,10 +92,6 @@ def slurm_batch_system_factory():
|
|
|
53
92
|
from toil.batchSystems.slurm import SlurmBatchSystem
|
|
54
93
|
return SlurmBatchSystem
|
|
55
94
|
|
|
56
|
-
def tes_batch_system_factory():
|
|
57
|
-
from toil.batchSystems.tes import TESBatchSystem
|
|
58
|
-
return TESBatchSystem
|
|
59
|
-
|
|
60
95
|
def torque_batch_system_factory():
|
|
61
96
|
from toil.batchSystems.torque import TorqueBatchSystem
|
|
62
97
|
return TorqueBatchSystem
|
|
@@ -71,29 +106,75 @@ def kubernetes_batch_system_factory():
|
|
|
71
106
|
from toil.batchSystems.kubernetes import KubernetesBatchSystem
|
|
72
107
|
return KubernetesBatchSystem
|
|
73
108
|
|
|
109
|
+
#####
|
|
110
|
+
# Registry implementation
|
|
111
|
+
#####
|
|
74
112
|
|
|
75
|
-
|
|
113
|
+
_registry: Dict[str, Callable[[], Type["AbstractBatchSystem"]]] = {
|
|
76
114
|
'aws_batch' : aws_batch_batch_system_factory,
|
|
77
|
-
'parasol' : parasol_batch_system_factory,
|
|
78
115
|
'single_machine' : single_machine_batch_system_factory,
|
|
79
116
|
'grid_engine' : gridengine_batch_system_factory,
|
|
80
117
|
'lsf' : lsf_batch_system_factory,
|
|
81
118
|
'mesos' : mesos_batch_system_factory,
|
|
82
119
|
'slurm' : slurm_batch_system_factory,
|
|
83
|
-
'tes' : tes_batch_system_factory,
|
|
84
120
|
'torque' : torque_batch_system_factory,
|
|
85
121
|
'htcondor' : htcondor_batch_system_factory,
|
|
86
122
|
'kubernetes' : kubernetes_batch_system_factory
|
|
87
123
|
}
|
|
88
|
-
|
|
89
|
-
|
|
124
|
+
_registry_keys = list(_registry.keys())
|
|
125
|
+
|
|
126
|
+
# We will load any packages starting with this prefix and let them call
|
|
127
|
+
# add_batch_system_factory()
|
|
128
|
+
_PLUGIN_NAME_PREFIX = "toil_batch_system_"
|
|
129
|
+
|
|
130
|
+
@memoize
|
|
131
|
+
def _load_all_plugins() -> None:
|
|
132
|
+
"""
|
|
133
|
+
Load all the batch system plugins that are installed.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
for finder, name, is_pkg in pkgutil.iter_modules():
|
|
137
|
+
# For all installed packages
|
|
138
|
+
if name.startswith(_PLUGIN_NAME_PREFIX):
|
|
139
|
+
# If it is a Toil batch system plugin, import it
|
|
140
|
+
importlib.import_module(name)
|
|
141
|
+
|
|
142
|
+
#####
|
|
143
|
+
# Deprecated API
|
|
144
|
+
#####
|
|
90
145
|
|
|
146
|
+
# We used to directly access these constants, but now the Right Way to use this
|
|
147
|
+
# module is add_batch_system_factory() to register and get_batch_systems() to
|
|
148
|
+
# get the list/get_batch_system() to get a class by name.
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def __getattr__(name):
|
|
152
|
+
"""
|
|
153
|
+
Implement a fallback attribute getter to handle deprecated constants.
|
|
154
|
+
|
|
155
|
+
See <https://stackoverflow.com/a/48242860>.
|
|
156
|
+
"""
|
|
157
|
+
if name == "BATCH_SYSTEM_FACTORY_REGISTRY":
|
|
158
|
+
warnings.warn("BATCH_SYSTEM_FACTORY_REGISTRY is deprecated; use get_batch_system() or add_batch_system_factory()", DeprecationWarning)
|
|
159
|
+
return _registry
|
|
160
|
+
elif name == "BATCH_SYSTEMS":
|
|
161
|
+
warnings.warn("BATCH_SYSTEMS is deprecated; use get_batch_systems()", DeprecationWarning)
|
|
162
|
+
return _registry_keys
|
|
163
|
+
else:
|
|
164
|
+
raise AttributeError(f"Module {__name__} ahs no attribute {name}")
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@deprecated(new_function_name="add_batch_system_factory")
|
|
91
168
|
def addBatchSystemFactory(key: str, batchSystemFactory: Callable[[], Type['AbstractBatchSystem']]):
|
|
92
169
|
"""
|
|
93
|
-
|
|
170
|
+
Deprecated method to add a batch system.
|
|
94
171
|
"""
|
|
95
|
-
|
|
96
|
-
|
|
172
|
+
return add_batch_system_factory(key, batchSystemFactory)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
#####
|
|
176
|
+
# Testing utilities
|
|
177
|
+
#####
|
|
97
178
|
|
|
98
179
|
# We need a snapshot save/restore system for testing. We can't just tamper with
|
|
99
180
|
# the globals because module-level globals are their own references, so we
|
|
@@ -106,7 +187,7 @@ def save_batch_system_plugin_state() -> Tuple[List[str], Dict[str, Callable[[],
|
|
|
106
187
|
tests.
|
|
107
188
|
"""
|
|
108
189
|
|
|
109
|
-
snapshot = (list(
|
|
190
|
+
snapshot = (list(_registry_keys), dict(_registry))
|
|
110
191
|
return snapshot
|
|
111
192
|
|
|
112
193
|
def restore_batch_system_plugin_state(snapshot: Tuple[List[str], Dict[str, Callable[[], Type['AbstractBatchSystem']]]]):
|
|
@@ -118,7 +199,7 @@ def restore_batch_system_plugin_state(snapshot: Tuple[List[str], Dict[str, Calla
|
|
|
118
199
|
# We need to apply the snapshot without rebinding the names, because that
|
|
119
200
|
# won't affect modules that imported the names.
|
|
120
201
|
wanted_batch_systems, wanted_registry = snapshot
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
202
|
+
_registry_keys.clear()
|
|
203
|
+
_registry_keys.extend(wanted_batch_systems)
|
|
204
|
+
_registry.clear()
|
|
205
|
+
_registry.update(wanted_registry)
|
|
@@ -22,23 +22,26 @@ import traceback
|
|
|
22
22
|
from argparse import ArgumentParser, _ArgumentGroup
|
|
23
23
|
from queue import Empty, Queue
|
|
24
24
|
from threading import Event, Lock, Thread
|
|
25
|
-
from typing import Dict, List, Optional,
|
|
25
|
+
from typing import Dict, List, Optional, Sequence, Set, Tuple, Union
|
|
26
26
|
|
|
27
27
|
import toil
|
|
28
28
|
from toil import worker as toil_worker
|
|
29
29
|
from toil.batchSystems.abstractBatchSystem import (EXIT_STATUS_UNAVAILABLE_VALUE,
|
|
30
30
|
BatchSystemSupport,
|
|
31
|
+
InsufficientSystemResources,
|
|
31
32
|
ResourcePool,
|
|
32
33
|
ResourceSet,
|
|
33
|
-
UpdatedBatchJobInfo
|
|
34
|
-
InsufficientSystemResources)
|
|
35
|
-
|
|
36
|
-
from toil.bus import ExternalBatchIdMessage
|
|
34
|
+
UpdatedBatchJobInfo)
|
|
37
35
|
from toil.batchSystems.options import OptionSetter
|
|
38
|
-
|
|
39
|
-
from toil.common import
|
|
40
|
-
from toil.
|
|
41
|
-
from toil.
|
|
36
|
+
from toil.bus import ExternalBatchIdMessage
|
|
37
|
+
from toil.common import Config, Toil
|
|
38
|
+
from toil.options.common import SYS_MAX_SIZE, make_open_interval_action
|
|
39
|
+
from toil.job import (AcceleratorRequirement,
|
|
40
|
+
JobDescription,
|
|
41
|
+
Requirer,
|
|
42
|
+
accelerator_satisfies)
|
|
43
|
+
from toil.lib.accelerators import (get_individual_local_accelerators,
|
|
44
|
+
get_restrictive_environment_for_local_accelerators)
|
|
42
45
|
from toil.lib.threading import cpu_count
|
|
43
46
|
|
|
44
47
|
logger = logging.getLogger(__name__)
|
|
@@ -104,7 +107,7 @@ class SingleMachineBatchSystem(BatchSystemSupport):
|
|
|
104
107
|
logger.warning('Not enough cores! User limited to %i but we only have %i.', maxCores, self.numCores)
|
|
105
108
|
maxCores = self.numCores
|
|
106
109
|
if maxMemory > self.physicalMemory:
|
|
107
|
-
if maxMemory
|
|
110
|
+
if maxMemory < SYS_MAX_SIZE: # todo: looks like humans2bytes converts SYS_MAX_SIZE to SYS_MAX_SIZE+1
|
|
108
111
|
# We have an actually specified limit and not the default
|
|
109
112
|
logger.warning('Not enough memory! User limited to %i bytes but we only have %i bytes.', maxMemory, self.physicalMemory)
|
|
110
113
|
maxMemory = self.physicalMemory
|
|
@@ -112,7 +115,7 @@ class SingleMachineBatchSystem(BatchSystemSupport):
|
|
|
112
115
|
workdir = Toil.getLocalWorkflowDir(config.workflowID, config.workDir) # config.workDir may be None; this sets a real directory
|
|
113
116
|
self.physicalDisk = toil.physicalDisk(workdir)
|
|
114
117
|
if maxDisk > self.physicalDisk:
|
|
115
|
-
if maxDisk
|
|
118
|
+
if maxDisk < SYS_MAX_SIZE: # same as maxMemory logger.warning
|
|
116
119
|
# We have an actually specified limit and not the default
|
|
117
120
|
logger.warning('Not enough disk space! User limited to %i bytes but we only have %i bytes.', maxDisk, self.physicalDisk)
|
|
118
121
|
maxDisk = self.physicalDisk
|
|
@@ -843,7 +846,7 @@ class SingleMachineBatchSystem(BatchSystemSupport):
|
|
|
843
846
|
|
|
844
847
|
@classmethod
|
|
845
848
|
def add_options(cls, parser: Union[ArgumentParser, _ArgumentGroup]) -> None:
|
|
846
|
-
parser.add_argument("--scale", dest="scale", default=1,
|
|
849
|
+
parser.add_argument("--scale", dest="scale", type=float, default=1, action=make_open_interval_action(0.0),
|
|
847
850
|
help="A scaling factor to change the value of all submitted tasks's submitted cores. "
|
|
848
851
|
"Used in the single_machine batch system. Useful for running workflows on "
|
|
849
852
|
"smaller machines than they were designed for, by setting a value less than 1. "
|
|
@@ -851,7 +854,7 @@ class SingleMachineBatchSystem(BatchSystemSupport):
|
|
|
851
854
|
|
|
852
855
|
@classmethod
|
|
853
856
|
def setOptions(cls, setOption: OptionSetter):
|
|
854
|
-
setOption("scale"
|
|
857
|
+
setOption("scale")
|
|
855
858
|
|
|
856
859
|
|
|
857
860
|
class Info:
|
toil/batchSystems/slurm.py
CHANGED
|
@@ -16,13 +16,13 @@ import math
|
|
|
16
16
|
import os
|
|
17
17
|
from argparse import ArgumentParser, _ArgumentGroup
|
|
18
18
|
from shlex import quote
|
|
19
|
-
from typing import
|
|
19
|
+
from typing import Dict, List, Optional, TypeVar, Union
|
|
20
20
|
|
|
21
21
|
from toil.batchSystems.abstractGridEngineBatchSystem import \
|
|
22
22
|
AbstractGridEngineBatchSystem
|
|
23
23
|
from toil.batchSystems.options import OptionSetter
|
|
24
|
-
from toil.lib.misc import CalledProcessErrorStderr, call_command
|
|
25
24
|
from toil.job import Requirer
|
|
25
|
+
from toil.lib.misc import CalledProcessErrorStderr, call_command
|
|
26
26
|
|
|
27
27
|
logger = logging.getLogger(__name__)
|
|
28
28
|
|
|
@@ -387,5 +387,5 @@ class SlurmBatchSystem(AbstractGridEngineBatchSystem):
|
|
|
387
387
|
OptionType = TypeVar('OptionType')
|
|
388
388
|
@classmethod
|
|
389
389
|
def setOptions(cls, setOption: OptionSetter) -> None:
|
|
390
|
-
setOption("allocate_mem"
|
|
390
|
+
setOption("allocate_mem")
|
|
391
391
|
|
toil/batchSystems/torque.py
CHANGED
toil/bus.py
CHANGED
|
@@ -61,15 +61,13 @@ MessageBus.connect_output_file() and MessageBus.scan_bus_messages().
|
|
|
61
61
|
"""
|
|
62
62
|
|
|
63
63
|
import collections
|
|
64
|
-
|
|
65
|
-
import inspect
|
|
64
|
+
import json
|
|
66
65
|
import logging
|
|
67
|
-
|
|
68
66
|
import os
|
|
69
67
|
import queue
|
|
70
|
-
import json
|
|
71
68
|
import tempfile
|
|
72
69
|
import threading
|
|
70
|
+
from dataclasses import dataclass
|
|
73
71
|
from typing import (IO,
|
|
74
72
|
Any,
|
|
75
73
|
Callable,
|
|
@@ -80,7 +78,6 @@ from typing import (IO,
|
|
|
80
78
|
Optional,
|
|
81
79
|
Type,
|
|
82
80
|
TypeVar,
|
|
83
|
-
Union,
|
|
84
81
|
cast)
|
|
85
82
|
|
|
86
83
|
from pubsub.core import Publisher
|
|
@@ -396,8 +393,8 @@ class MessageBus:
|
|
|
396
393
|
given topic.
|
|
397
394
|
"""
|
|
398
395
|
# There should always be a "message"
|
|
399
|
-
|
|
400
|
-
|
|
396
|
+
if len(message_data) != 1 or 'message' not in message_data:
|
|
397
|
+
raise RuntimeError("Cannot log the bus message. The message is either empty/malformed or there are too many messages provided.")
|
|
401
398
|
message = message_data['message']
|
|
402
399
|
topic = topic_object.getName()
|
|
403
400
|
stream.write(topic.encode('utf-8'))
|
|
@@ -572,7 +569,8 @@ class MessageInbox(MessageBusClient):
|
|
|
572
569
|
handled = False
|
|
573
570
|
try:
|
|
574
571
|
# Emit the message
|
|
575
|
-
|
|
572
|
+
if not isinstance(message, message_type):
|
|
573
|
+
raise RuntimeError(f"Unacceptable message type {type(message)} in list for type {message_type}")
|
|
576
574
|
yield message
|
|
577
575
|
# If we get here it was handled without error.
|
|
578
576
|
handled = True
|