toil 7.0.0__py3-none-any.whl → 8.1.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. toil/__init__.py +124 -86
  2. toil/batchSystems/__init__.py +1 -0
  3. toil/batchSystems/abstractBatchSystem.py +137 -77
  4. toil/batchSystems/abstractGridEngineBatchSystem.py +211 -101
  5. toil/batchSystems/awsBatch.py +237 -128
  6. toil/batchSystems/cleanup_support.py +22 -16
  7. toil/batchSystems/contained_executor.py +30 -26
  8. toil/batchSystems/gridengine.py +85 -49
  9. toil/batchSystems/htcondor.py +164 -87
  10. toil/batchSystems/kubernetes.py +622 -386
  11. toil/batchSystems/local_support.py +17 -12
  12. toil/batchSystems/lsf.py +132 -79
  13. toil/batchSystems/lsfHelper.py +13 -11
  14. toil/batchSystems/mesos/__init__.py +41 -29
  15. toil/batchSystems/mesos/batchSystem.py +288 -149
  16. toil/batchSystems/mesos/executor.py +77 -49
  17. toil/batchSystems/mesos/test/__init__.py +31 -23
  18. toil/batchSystems/options.py +39 -29
  19. toil/batchSystems/registry.py +53 -19
  20. toil/batchSystems/singleMachine.py +293 -123
  21. toil/batchSystems/slurm.py +651 -155
  22. toil/batchSystems/torque.py +46 -32
  23. toil/bus.py +141 -73
  24. toil/common.py +784 -397
  25. toil/cwl/__init__.py +1 -1
  26. toil/cwl/cwltoil.py +1137 -534
  27. toil/cwl/utils.py +17 -22
  28. toil/deferred.py +62 -41
  29. toil/exceptions.py +5 -3
  30. toil/fileStores/__init__.py +5 -5
  31. toil/fileStores/abstractFileStore.py +88 -57
  32. toil/fileStores/cachingFileStore.py +711 -247
  33. toil/fileStores/nonCachingFileStore.py +113 -75
  34. toil/job.py +1031 -349
  35. toil/jobStores/abstractJobStore.py +387 -243
  36. toil/jobStores/aws/jobStore.py +772 -412
  37. toil/jobStores/aws/utils.py +161 -109
  38. toil/jobStores/conftest.py +1 -0
  39. toil/jobStores/fileJobStore.py +289 -151
  40. toil/jobStores/googleJobStore.py +137 -70
  41. toil/jobStores/utils.py +36 -15
  42. toil/leader.py +614 -269
  43. toil/lib/accelerators.py +115 -18
  44. toil/lib/aws/__init__.py +55 -28
  45. toil/lib/aws/ami.py +122 -87
  46. toil/lib/aws/iam.py +284 -108
  47. toil/lib/aws/s3.py +31 -0
  48. toil/lib/aws/session.py +204 -58
  49. toil/lib/aws/utils.py +290 -213
  50. toil/lib/bioio.py +13 -5
  51. toil/lib/compatibility.py +11 -6
  52. toil/lib/conversions.py +83 -49
  53. toil/lib/docker.py +131 -103
  54. toil/lib/dockstore.py +379 -0
  55. toil/lib/ec2.py +322 -209
  56. toil/lib/ec2nodes.py +174 -105
  57. toil/lib/encryption/_dummy.py +5 -3
  58. toil/lib/encryption/_nacl.py +10 -6
  59. toil/lib/encryption/conftest.py +1 -0
  60. toil/lib/exceptions.py +26 -7
  61. toil/lib/expando.py +4 -2
  62. toil/lib/ftp_utils.py +217 -0
  63. toil/lib/generatedEC2Lists.py +127 -19
  64. toil/lib/history.py +1271 -0
  65. toil/lib/history_submission.py +681 -0
  66. toil/lib/humanize.py +6 -2
  67. toil/lib/io.py +121 -12
  68. toil/lib/iterables.py +4 -2
  69. toil/lib/memoize.py +12 -8
  70. toil/lib/misc.py +83 -18
  71. toil/lib/objects.py +2 -2
  72. toil/lib/resources.py +19 -7
  73. toil/lib/retry.py +125 -87
  74. toil/lib/threading.py +282 -80
  75. toil/lib/throttle.py +15 -14
  76. toil/lib/trs.py +390 -0
  77. toil/lib/web.py +38 -0
  78. toil/options/common.py +850 -402
  79. toil/options/cwl.py +185 -90
  80. toil/options/runner.py +50 -0
  81. toil/options/wdl.py +70 -19
  82. toil/provisioners/__init__.py +111 -46
  83. toil/provisioners/abstractProvisioner.py +322 -157
  84. toil/provisioners/aws/__init__.py +62 -30
  85. toil/provisioners/aws/awsProvisioner.py +980 -627
  86. toil/provisioners/clusterScaler.py +541 -279
  87. toil/provisioners/gceProvisioner.py +283 -180
  88. toil/provisioners/node.py +147 -79
  89. toil/realtimeLogger.py +34 -22
  90. toil/resource.py +137 -75
  91. toil/server/app.py +127 -61
  92. toil/server/celery_app.py +3 -1
  93. toil/server/cli/wes_cwl_runner.py +84 -55
  94. toil/server/utils.py +56 -31
  95. toil/server/wes/abstract_backend.py +64 -26
  96. toil/server/wes/amazon_wes_utils.py +21 -15
  97. toil/server/wes/tasks.py +121 -63
  98. toil/server/wes/toil_backend.py +142 -107
  99. toil/server/wsgi_app.py +4 -3
  100. toil/serviceManager.py +58 -22
  101. toil/statsAndLogging.py +183 -65
  102. toil/test/__init__.py +263 -179
  103. toil/test/batchSystems/batchSystemTest.py +438 -195
  104. toil/test/batchSystems/batch_system_plugin_test.py +18 -7
  105. toil/test/batchSystems/test_gridengine.py +173 -0
  106. toil/test/batchSystems/test_lsf_helper.py +67 -58
  107. toil/test/batchSystems/test_slurm.py +265 -49
  108. toil/test/cactus/test_cactus_integration.py +20 -22
  109. toil/test/cwl/conftest.py +39 -0
  110. toil/test/cwl/cwlTest.py +375 -72
  111. toil/test/cwl/measure_default_memory.cwl +12 -0
  112. toil/test/cwl/not_run_required_input.cwl +29 -0
  113. toil/test/cwl/optional-file.cwl +18 -0
  114. toil/test/cwl/scatter_duplicate_outputs.cwl +40 -0
  115. toil/test/docs/scriptsTest.py +60 -34
  116. toil/test/jobStores/jobStoreTest.py +412 -235
  117. toil/test/lib/aws/test_iam.py +116 -48
  118. toil/test/lib/aws/test_s3.py +16 -9
  119. toil/test/lib/aws/test_utils.py +5 -6
  120. toil/test/lib/dockerTest.py +118 -141
  121. toil/test/lib/test_conversions.py +113 -115
  122. toil/test/lib/test_ec2.py +57 -49
  123. toil/test/lib/test_history.py +212 -0
  124. toil/test/lib/test_misc.py +12 -5
  125. toil/test/lib/test_trs.py +161 -0
  126. toil/test/mesos/MesosDataStructuresTest.py +23 -10
  127. toil/test/mesos/helloWorld.py +7 -6
  128. toil/test/mesos/stress.py +25 -20
  129. toil/test/options/options.py +7 -2
  130. toil/test/provisioners/aws/awsProvisionerTest.py +293 -140
  131. toil/test/provisioners/clusterScalerTest.py +440 -250
  132. toil/test/provisioners/clusterTest.py +81 -42
  133. toil/test/provisioners/gceProvisionerTest.py +174 -100
  134. toil/test/provisioners/provisionerTest.py +25 -13
  135. toil/test/provisioners/restartScript.py +5 -4
  136. toil/test/server/serverTest.py +188 -141
  137. toil/test/sort/restart_sort.py +137 -68
  138. toil/test/sort/sort.py +134 -66
  139. toil/test/sort/sortTest.py +91 -49
  140. toil/test/src/autoDeploymentTest.py +140 -100
  141. toil/test/src/busTest.py +20 -18
  142. toil/test/src/checkpointTest.py +8 -2
  143. toil/test/src/deferredFunctionTest.py +49 -35
  144. toil/test/src/dockerCheckTest.py +33 -26
  145. toil/test/src/environmentTest.py +20 -10
  146. toil/test/src/fileStoreTest.py +538 -271
  147. toil/test/src/helloWorldTest.py +7 -4
  148. toil/test/src/importExportFileTest.py +61 -31
  149. toil/test/src/jobDescriptionTest.py +32 -17
  150. toil/test/src/jobEncapsulationTest.py +2 -0
  151. toil/test/src/jobFileStoreTest.py +74 -50
  152. toil/test/src/jobServiceTest.py +187 -73
  153. toil/test/src/jobTest.py +120 -70
  154. toil/test/src/miscTests.py +19 -18
  155. toil/test/src/promisedRequirementTest.py +82 -36
  156. toil/test/src/promisesTest.py +7 -6
  157. toil/test/src/realtimeLoggerTest.py +6 -6
  158. toil/test/src/regularLogTest.py +71 -37
  159. toil/test/src/resourceTest.py +80 -49
  160. toil/test/src/restartDAGTest.py +36 -22
  161. toil/test/src/resumabilityTest.py +9 -2
  162. toil/test/src/retainTempDirTest.py +45 -14
  163. toil/test/src/systemTest.py +12 -8
  164. toil/test/src/threadingTest.py +44 -25
  165. toil/test/src/toilContextManagerTest.py +10 -7
  166. toil/test/src/userDefinedJobArgTypeTest.py +8 -5
  167. toil/test/src/workerTest.py +33 -16
  168. toil/test/utils/toilDebugTest.py +70 -58
  169. toil/test/utils/toilKillTest.py +4 -5
  170. toil/test/utils/utilsTest.py +239 -102
  171. toil/test/wdl/wdltoil_test.py +789 -148
  172. toil/test/wdl/wdltoil_test_kubernetes.py +37 -23
  173. toil/toilState.py +52 -26
  174. toil/utils/toilConfig.py +13 -4
  175. toil/utils/toilDebugFile.py +44 -27
  176. toil/utils/toilDebugJob.py +85 -25
  177. toil/utils/toilDestroyCluster.py +11 -6
  178. toil/utils/toilKill.py +8 -3
  179. toil/utils/toilLaunchCluster.py +251 -145
  180. toil/utils/toilMain.py +37 -16
  181. toil/utils/toilRsyncCluster.py +27 -14
  182. toil/utils/toilSshCluster.py +45 -22
  183. toil/utils/toilStats.py +75 -36
  184. toil/utils/toilStatus.py +226 -119
  185. toil/utils/toilUpdateEC2Instances.py +3 -1
  186. toil/version.py +6 -6
  187. toil/wdl/utils.py +5 -5
  188. toil/wdl/wdltoil.py +3528 -1053
  189. toil/worker.py +370 -149
  190. toil-8.1.0b1.dist-info/METADATA +178 -0
  191. toil-8.1.0b1.dist-info/RECORD +259 -0
  192. {toil-7.0.0.dist-info → toil-8.1.0b1.dist-info}/WHEEL +1 -1
  193. toil-7.0.0.dist-info/METADATA +0 -158
  194. toil-7.0.0.dist-info/RECORD +0 -244
  195. {toil-7.0.0.dist-info → toil-8.1.0b1.dist-info}/LICENSE +0 -0
  196. {toil-7.0.0.dist-info → toil-8.1.0b1.dist-info}/entry_points.txt +0 -0
  197. {toil-7.0.0.dist-info → toil-8.1.0b1.dist-info}/top_level.txt +0 -0
toil/lib/ftp_utils.py ADDED
@@ -0,0 +1,217 @@
1
+ # Copyright 2017 Oregon Health and Science University
2
+ #
3
+ # Copyright (C) 2015-2021 Regents of the University of California
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ import ftplib
19
+ import logging
20
+ import netrc
21
+ import os
22
+ from contextlib import closing
23
+ from typing import Optional, Any, cast, IO
24
+ from urllib.parse import urlparse
25
+ from urllib.request import urlopen
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+
30
+ class FtpFsAccess:
31
+ """
32
+ FTP access with upload.
33
+
34
+ Taken and modified from https://github.com/ohsu-comp-bio/cwl-tes/blob/03f0096f9fae8acd527687d3460a726e09190c3a/cwl_tes/ftp.py#L37-L251
35
+ """
36
+ # TODO: Properly support FTP over SSL
37
+
38
+ def __init__(
39
+ self, cache: Optional[dict[Any, ftplib.FTP]] = None
40
+ ):
41
+ """
42
+ FTP object to handle FTP connections. By default, connect over FTP with TLS.
43
+
44
+ :param cache: cache of generated FTP objects
45
+ """
46
+ self.cache = cache or {}
47
+ self.netrc = None
48
+ try:
49
+ if "HOME" in os.environ:
50
+ if os.path.exists(os.path.join(os.environ["HOME"], ".netrc")):
51
+ self.netrc = netrc.netrc(os.path.join(os.environ["HOME"], ".netrc"))
52
+ elif os.path.exists(os.path.join(os.curdir, ".netrc")):
53
+ self.netrc = netrc.netrc(os.path.join(os.curdir, ".netrc"))
54
+ except netrc.NetrcParseError as err:
55
+ logger.debug(err)
56
+
57
+ def exists(self, fn: str) -> bool:
58
+ """
59
+ Check if a file/directory exists over an FTP server
60
+ :param fn: FTP url
61
+ :return: True or false depending on whether the object exists on the server
62
+ """
63
+ return self.isfile(fn) or self.isdir(fn)
64
+
65
+ def isfile(self, fn: str) -> bool:
66
+ """
67
+ Check if the FTP url points to a file
68
+ :param fn: FTP url
69
+ :return: True if url is file, else false
70
+ """
71
+ ftp = self._connect(fn)
72
+ if ftp:
73
+ try:
74
+ if not self.size(fn) is None:
75
+ return True
76
+ else:
77
+ return False
78
+ except ftplib.all_errors:
79
+ return False
80
+ return False
81
+
82
+ def isdir(self, fn: str) -> bool:
83
+ """
84
+ Check if the FTP url points to a directory
85
+ :param fn: FTP url
86
+ :return: True if url is directory, else false
87
+ """
88
+ ftp = self._connect(fn)
89
+ if ftp:
90
+ try:
91
+ cwd = ftp.pwd()
92
+ ftp.cwd(urlparse(fn).path)
93
+ ftp.cwd(cwd)
94
+ return True
95
+ except ftplib.all_errors:
96
+ return False
97
+ return False
98
+
99
+ def open(self, fn: str, mode: str) -> IO[bytes]:
100
+ """
101
+ Open an FTP url.
102
+
103
+ Only supports reading, no write support.
104
+ :param fn: FTP url
105
+ :param mode: Mode to open FTP url in
106
+ :return:
107
+ """
108
+ if "r" in mode:
109
+ host, port, user, passwd, path = self._parse_url(fn)
110
+ handle = urlopen("ftp://{}:{}@{}:{}/{}".format(user, passwd, host, port, path))
111
+ return cast(IO[bytes], closing(handle))
112
+ # TODO: support write mode
113
+ raise Exception("Write mode FTP not implemented")
114
+
115
+ def _parse_url(
116
+ self, url: str
117
+ ) -> tuple[str, int, Optional[str], Optional[str], str]:
118
+ """
119
+ Parse an FTP url into hostname, username, password, and path
120
+ :param url:
121
+ :return: hostname, username, password, path
122
+ """
123
+ parse = urlparse(url)
124
+ user = parse.username
125
+ passwd = parse.password
126
+ host = parse.hostname
127
+ port = parse.port
128
+ path = parse.path
129
+ if host is None:
130
+ # The URL we connect to must have a host
131
+ raise RuntimeError(f"FTP URL does not contain a host: {url}")
132
+ # default port is 21
133
+ if port is None:
134
+ port = 21
135
+ if parse.scheme == "ftp":
136
+ if not user and self.netrc:
137
+ if host is not None:
138
+ creds = self.netrc.authenticators(host)
139
+ if creds:
140
+ user, _, passwd = creds
141
+ if not user:
142
+ if host is not None:
143
+ user, passwd = self._recall_credentials(host)
144
+ if passwd is None:
145
+ passwd = "anonymous@"
146
+ if user is None:
147
+ user = "anonymous"
148
+ return host, port, user, passwd, path
149
+
150
+ def _connect(self, url: str) -> Optional[ftplib.FTP]:
151
+ """
152
+ Connect to an FTP server. Handles authentication.
153
+ :param url: FTP url
154
+ :return: FTP object
155
+ """
156
+ parse = urlparse(url)
157
+ if parse.scheme == "ftp":
158
+ host, port, user, passwd, _ = self._parse_url(url)
159
+ if host is None:
160
+ # there has to be a host
161
+ return None
162
+ if (host, user, passwd) in self.cache:
163
+ if self.cache[(host, user, passwd)].pwd():
164
+ return self.cache[(host, user, passwd)]
165
+ ftp = ftplib.FTP_TLS()
166
+ # Note: the FTP lib logger handles logging itself and doesn't go through our logging implementation
167
+ ftp.set_debuglevel(1 if logger.isEnabledFor(logging.DEBUG) else 0)
168
+ ftp.connect(host, port)
169
+ env_user = os.getenv("TOIL_FTP_USER")
170
+ env_passwd = os.getenv("TOIL_FTP_PASSWORD")
171
+ if env_user:
172
+ user = env_user
173
+ if env_passwd:
174
+ passwd = env_passwd
175
+ ftp.login(user or "", passwd or "", secure=False)
176
+ self.cache[(host, user, passwd)] = ftp
177
+ return ftp
178
+ return None
179
+
180
+ def _recall_credentials(
181
+ self, desired_host: str
182
+ ) -> tuple[Optional[str], Optional[str]]:
183
+ """
184
+ Grab the cached credentials
185
+ :param desired_host: FTP hostname
186
+ :return: username, password
187
+ """
188
+ for host, user, passwd in self.cache:
189
+ if desired_host == host:
190
+ return user, passwd
191
+ return None, None
192
+
193
+ def size(self, fn: str) -> Optional[int]:
194
+ """
195
+ Get the size of an FTP object
196
+ :param fn: FTP url
197
+ :return: Size of object
198
+ """
199
+ ftp = self._connect(fn)
200
+ if ftp:
201
+ host, port, user, passwd, path = self._parse_url(fn)
202
+ try:
203
+ return ftp.size(path)
204
+ except ftplib.all_errors as e:
205
+ if str(e) == "550 SIZE not allowed in ASCII mode":
206
+ # some servers don't allow grabbing size in ascii mode
207
+ # https://stackoverflow.com/questions/22090001/get-folder-size-using-ftplib/22093848#22093848
208
+ ftp.voidcmd("TYPE I")
209
+ return ftp.size(path)
210
+ handle = urlopen("ftp://{}:{}@{}:{}/{}".format(user, passwd, host, port, path))
211
+ info = handle.info()
212
+ handle.close()
213
+ if "Content-length" in info:
214
+ return int(info["Content-length"])
215
+ return None
216
+
217
+ return None