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.
Files changed (193) hide show
  1. toil/__init__.py +122 -315
  2. toil/batchSystems/__init__.py +1 -0
  3. toil/batchSystems/abstractBatchSystem.py +173 -89
  4. toil/batchSystems/abstractGridEngineBatchSystem.py +272 -148
  5. toil/batchSystems/awsBatch.py +244 -135
  6. toil/batchSystems/cleanup_support.py +26 -16
  7. toil/batchSystems/contained_executor.py +31 -28
  8. toil/batchSystems/gridengine.py +86 -50
  9. toil/batchSystems/htcondor.py +166 -89
  10. toil/batchSystems/kubernetes.py +632 -382
  11. toil/batchSystems/local_support.py +20 -15
  12. toil/batchSystems/lsf.py +134 -81
  13. toil/batchSystems/lsfHelper.py +13 -11
  14. toil/batchSystems/mesos/__init__.py +41 -29
  15. toil/batchSystems/mesos/batchSystem.py +290 -151
  16. toil/batchSystems/mesos/executor.py +79 -50
  17. toil/batchSystems/mesos/test/__init__.py +31 -23
  18. toil/batchSystems/options.py +46 -28
  19. toil/batchSystems/registry.py +53 -19
  20. toil/batchSystems/singleMachine.py +296 -125
  21. toil/batchSystems/slurm.py +603 -138
  22. toil/batchSystems/torque.py +47 -33
  23. toil/bus.py +186 -76
  24. toil/common.py +664 -368
  25. toil/cwl/__init__.py +1 -1
  26. toil/cwl/cwltoil.py +1136 -483
  27. toil/cwl/utils.py +17 -22
  28. toil/deferred.py +63 -42
  29. toil/exceptions.py +5 -3
  30. toil/fileStores/__init__.py +5 -5
  31. toil/fileStores/abstractFileStore.py +140 -60
  32. toil/fileStores/cachingFileStore.py +717 -269
  33. toil/fileStores/nonCachingFileStore.py +116 -87
  34. toil/job.py +1225 -368
  35. toil/jobStores/abstractJobStore.py +416 -266
  36. toil/jobStores/aws/jobStore.py +863 -477
  37. toil/jobStores/aws/utils.py +201 -120
  38. toil/jobStores/conftest.py +3 -2
  39. toil/jobStores/fileJobStore.py +292 -154
  40. toil/jobStores/googleJobStore.py +140 -74
  41. toil/jobStores/utils.py +36 -15
  42. toil/leader.py +668 -272
  43. toil/lib/accelerators.py +115 -18
  44. toil/lib/aws/__init__.py +74 -31
  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 +214 -39
  49. toil/lib/aws/utils.py +287 -231
  50. toil/lib/bioio.py +13 -5
  51. toil/lib/compatibility.py +11 -6
  52. toil/lib/conversions.py +104 -47
  53. toil/lib/docker.py +131 -103
  54. toil/lib/ec2.py +361 -199
  55. toil/lib/ec2nodes.py +174 -106
  56. toil/lib/encryption/_dummy.py +5 -3
  57. toil/lib/encryption/_nacl.py +10 -6
  58. toil/lib/encryption/conftest.py +1 -0
  59. toil/lib/exceptions.py +26 -7
  60. toil/lib/expando.py +5 -3
  61. toil/lib/ftp_utils.py +217 -0
  62. toil/lib/generatedEC2Lists.py +127 -19
  63. toil/lib/humanize.py +6 -2
  64. toil/lib/integration.py +341 -0
  65. toil/lib/io.py +141 -15
  66. toil/lib/iterables.py +4 -2
  67. toil/lib/memoize.py +12 -8
  68. toil/lib/misc.py +66 -21
  69. toil/lib/objects.py +2 -2
  70. toil/lib/resources.py +68 -15
  71. toil/lib/retry.py +126 -81
  72. toil/lib/threading.py +299 -82
  73. toil/lib/throttle.py +16 -15
  74. toil/options/common.py +843 -409
  75. toil/options/cwl.py +175 -90
  76. toil/options/runner.py +50 -0
  77. toil/options/wdl.py +73 -17
  78. toil/provisioners/__init__.py +117 -46
  79. toil/provisioners/abstractProvisioner.py +332 -157
  80. toil/provisioners/aws/__init__.py +70 -33
  81. toil/provisioners/aws/awsProvisioner.py +1145 -715
  82. toil/provisioners/clusterScaler.py +541 -279
  83. toil/provisioners/gceProvisioner.py +282 -179
  84. toil/provisioners/node.py +155 -79
  85. toil/realtimeLogger.py +34 -22
  86. toil/resource.py +137 -75
  87. toil/server/app.py +128 -62
  88. toil/server/celery_app.py +3 -1
  89. toil/server/cli/wes_cwl_runner.py +82 -53
  90. toil/server/utils.py +54 -28
  91. toil/server/wes/abstract_backend.py +64 -26
  92. toil/server/wes/amazon_wes_utils.py +21 -15
  93. toil/server/wes/tasks.py +121 -63
  94. toil/server/wes/toil_backend.py +142 -107
  95. toil/server/wsgi_app.py +4 -3
  96. toil/serviceManager.py +58 -22
  97. toil/statsAndLogging.py +224 -70
  98. toil/test/__init__.py +282 -183
  99. toil/test/batchSystems/batchSystemTest.py +460 -210
  100. toil/test/batchSystems/batch_system_plugin_test.py +90 -0
  101. toil/test/batchSystems/test_gridengine.py +173 -0
  102. toil/test/batchSystems/test_lsf_helper.py +67 -58
  103. toil/test/batchSystems/test_slurm.py +110 -49
  104. toil/test/cactus/__init__.py +0 -0
  105. toil/test/cactus/test_cactus_integration.py +56 -0
  106. toil/test/cwl/cwlTest.py +496 -287
  107. toil/test/cwl/measure_default_memory.cwl +12 -0
  108. toil/test/cwl/not_run_required_input.cwl +29 -0
  109. toil/test/cwl/scatter_duplicate_outputs.cwl +40 -0
  110. toil/test/cwl/seqtk_seq.cwl +1 -1
  111. toil/test/docs/scriptsTest.py +69 -46
  112. toil/test/jobStores/jobStoreTest.py +427 -264
  113. toil/test/lib/aws/test_iam.py +118 -50
  114. toil/test/lib/aws/test_s3.py +16 -9
  115. toil/test/lib/aws/test_utils.py +5 -6
  116. toil/test/lib/dockerTest.py +118 -141
  117. toil/test/lib/test_conversions.py +113 -115
  118. toil/test/lib/test_ec2.py +58 -50
  119. toil/test/lib/test_integration.py +104 -0
  120. toil/test/lib/test_misc.py +12 -5
  121. toil/test/mesos/MesosDataStructuresTest.py +23 -10
  122. toil/test/mesos/helloWorld.py +7 -6
  123. toil/test/mesos/stress.py +25 -20
  124. toil/test/options/__init__.py +13 -0
  125. toil/test/options/options.py +42 -0
  126. toil/test/provisioners/aws/awsProvisionerTest.py +320 -150
  127. toil/test/provisioners/clusterScalerTest.py +440 -250
  128. toil/test/provisioners/clusterTest.py +166 -44
  129. toil/test/provisioners/gceProvisionerTest.py +174 -100
  130. toil/test/provisioners/provisionerTest.py +25 -13
  131. toil/test/provisioners/restartScript.py +5 -4
  132. toil/test/server/serverTest.py +188 -141
  133. toil/test/sort/restart_sort.py +137 -68
  134. toil/test/sort/sort.py +134 -66
  135. toil/test/sort/sortTest.py +91 -49
  136. toil/test/src/autoDeploymentTest.py +141 -101
  137. toil/test/src/busTest.py +20 -18
  138. toil/test/src/checkpointTest.py +8 -2
  139. toil/test/src/deferredFunctionTest.py +49 -35
  140. toil/test/src/dockerCheckTest.py +32 -24
  141. toil/test/src/environmentTest.py +135 -0
  142. toil/test/src/fileStoreTest.py +539 -272
  143. toil/test/src/helloWorldTest.py +7 -4
  144. toil/test/src/importExportFileTest.py +61 -31
  145. toil/test/src/jobDescriptionTest.py +46 -21
  146. toil/test/src/jobEncapsulationTest.py +2 -0
  147. toil/test/src/jobFileStoreTest.py +74 -50
  148. toil/test/src/jobServiceTest.py +187 -73
  149. toil/test/src/jobTest.py +121 -71
  150. toil/test/src/miscTests.py +19 -18
  151. toil/test/src/promisedRequirementTest.py +82 -36
  152. toil/test/src/promisesTest.py +7 -6
  153. toil/test/src/realtimeLoggerTest.py +10 -6
  154. toil/test/src/regularLogTest.py +71 -37
  155. toil/test/src/resourceTest.py +80 -49
  156. toil/test/src/restartDAGTest.py +36 -22
  157. toil/test/src/resumabilityTest.py +9 -2
  158. toil/test/src/retainTempDirTest.py +45 -14
  159. toil/test/src/systemTest.py +12 -8
  160. toil/test/src/threadingTest.py +44 -25
  161. toil/test/src/toilContextManagerTest.py +10 -7
  162. toil/test/src/userDefinedJobArgTypeTest.py +8 -5
  163. toil/test/src/workerTest.py +73 -23
  164. toil/test/utils/toilDebugTest.py +103 -33
  165. toil/test/utils/toilKillTest.py +4 -5
  166. toil/test/utils/utilsTest.py +245 -106
  167. toil/test/wdl/wdltoil_test.py +818 -149
  168. toil/test/wdl/wdltoil_test_kubernetes.py +91 -0
  169. toil/toilState.py +120 -35
  170. toil/utils/toilConfig.py +13 -4
  171. toil/utils/toilDebugFile.py +44 -27
  172. toil/utils/toilDebugJob.py +214 -27
  173. toil/utils/toilDestroyCluster.py +11 -6
  174. toil/utils/toilKill.py +8 -3
  175. toil/utils/toilLaunchCluster.py +256 -140
  176. toil/utils/toilMain.py +37 -16
  177. toil/utils/toilRsyncCluster.py +32 -14
  178. toil/utils/toilSshCluster.py +49 -22
  179. toil/utils/toilStats.py +356 -273
  180. toil/utils/toilStatus.py +292 -139
  181. toil/utils/toilUpdateEC2Instances.py +3 -1
  182. toil/version.py +12 -12
  183. toil/wdl/utils.py +5 -5
  184. toil/wdl/wdltoil.py +3913 -1033
  185. toil/worker.py +367 -184
  186. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/LICENSE +25 -0
  187. toil-8.0.0.dist-info/METADATA +173 -0
  188. toil-8.0.0.dist-info/RECORD +253 -0
  189. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/WHEEL +1 -1
  190. toil-6.1.0a1.dist-info/METADATA +0 -125
  191. toil-6.1.0a1.dist-info/RECORD +0 -237
  192. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/entry_points.txt +0 -0
  193. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/top_level.txt +0 -0
toil/lib/aws/session.py CHANGED
@@ -15,17 +15,24 @@ import collections
15
15
  import logging
16
16
  import os
17
17
  import threading
18
- from typing import Dict, Optional, Tuple, cast
18
+ from typing import TYPE_CHECKING, Literal, Optional, cast, overload
19
19
 
20
20
  import boto3
21
21
  import boto3.resources.base
22
- import boto.connection
23
22
  import botocore
24
23
  from boto3 import Session
25
24
  from botocore.client import Config
26
25
  from botocore.session import get_session
27
26
  from botocore.utils import JSONFileCache
28
27
 
28
+ if TYPE_CHECKING:
29
+ from mypy_boto3_autoscaling import AutoScalingClient
30
+ from mypy_boto3_ec2 import EC2Client, EC2ServiceResource
31
+ from mypy_boto3_iam import IAMClient, IAMServiceResource
32
+ from mypy_boto3_s3 import S3Client, S3ServiceResource
33
+ from mypy_boto3_sdb import SimpleDBClient
34
+ from mypy_boto3_sts import STSClient
35
+
29
36
  logger = logging.getLogger(__name__)
30
37
 
31
38
  # A note on thread safety:
@@ -44,6 +51,7 @@ logger = logging.getLogger(__name__)
44
51
  # initializing Boto3 (or Boto2) things at a time.
45
52
  _init_lock = threading.RLock()
46
53
 
54
+
47
55
  def _new_boto3_session(region_name: Optional[str] = None) -> Session:
48
56
  """
49
57
  This is the One True Place where new Boto3 sessions should be made, and
@@ -59,10 +67,16 @@ def _new_boto3_session(region_name: Optional[str] = None) -> Session:
59
67
 
60
68
  with _init_lock:
61
69
  botocore_session = get_session()
62
- botocore_session.get_component('credential_provider').get_provider(
63
- 'assume-role').cache = JSONFileCache()
70
+ botocore_session.get_component("credential_provider").get_provider(
71
+ "assume-role"
72
+ ).cache = JSONFileCache()
73
+
74
+ return Session(
75
+ botocore_session=botocore_session,
76
+ region_name=region_name,
77
+ profile_name=os.environ.get("TOIL_AWS_PROFILE", None),
78
+ )
64
79
 
65
- return Session(botocore_session=botocore_session, region_name=region_name, profile_name=os.environ.get("TOIL_AWS_PROFILE", None))
66
80
 
67
81
  class AWSConnectionManager:
68
82
  """
@@ -98,29 +112,64 @@ class AWSConnectionManager:
98
112
  """
99
113
  # This stores Boto3 sessions in .item of a thread-local storage, by
100
114
  # region.
101
- self.sessions_by_region: Dict[Optional[str], threading.local] = collections.defaultdict(threading.local)
115
+ self.sessions_by_region: dict[Optional[str], threading.local] = (
116
+ collections.defaultdict(threading.local)
117
+ )
102
118
  # This stores Boto3 resources in .item of a thread-local storage, by
103
119
  # (region, service name, endpoint URL) tuples
104
- self.resource_cache: Dict[Tuple[Optional[str], str, Optional[str]], threading.local] = collections.defaultdict(threading.local)
120
+ self.resource_cache: dict[
121
+ tuple[Optional[str], str, Optional[str]], threading.local
122
+ ] = collections.defaultdict(threading.local)
105
123
  # This stores Boto3 clients in .item of a thread-local storage, by
106
124
  # (region, service name, endpoint URL) tuples
107
- self.client_cache: Dict[Tuple[Optional[str], str, Optional[str]], threading.local] = collections.defaultdict(threading.local)
125
+ self.client_cache: dict[
126
+ tuple[Optional[str], str, Optional[str]], threading.local
127
+ ] = collections.defaultdict(threading.local)
108
128
  # This stores Boto 2 connections in .item of a thread-local storage, by
109
129
  # (region, service name) tuples.
110
- self.boto2_cache: Dict[Tuple[Optional[str], str], threading.local] = collections.defaultdict(threading.local)
130
+ self.boto2_cache: dict[tuple[Optional[str], str], threading.local] = (
131
+ collections.defaultdict(threading.local)
132
+ )
111
133
 
112
134
  def session(self, region: Optional[str]) -> boto3.session.Session:
113
135
  """
114
136
  Get the Boto3 Session to use for the given region.
115
137
  """
116
138
  storage = self.sessions_by_region[region]
117
- if not hasattr(storage, 'item'):
139
+ if not hasattr(storage, "item"):
118
140
  # This is the first time this thread wants to talk to this region
119
141
  # through this manager
120
142
  storage.item = _new_boto3_session(region_name=region)
121
143
  return cast(boto3.session.Session, storage.item)
122
144
 
123
- def resource(self, region: Optional[str], service_name: str, endpoint_url: Optional[str] = None) -> boto3.resources.base.ServiceResource:
145
+ @overload
146
+ def resource(
147
+ self,
148
+ region: Optional[str],
149
+ service_name: Literal["s3"],
150
+ endpoint_url: Optional[str] = None,
151
+ ) -> "S3ServiceResource": ...
152
+ @overload
153
+ def resource(
154
+ self,
155
+ region: Optional[str],
156
+ service_name: Literal["iam"],
157
+ endpoint_url: Optional[str] = None,
158
+ ) -> "IAMServiceResource": ...
159
+ @overload
160
+ def resource(
161
+ self,
162
+ region: Optional[str],
163
+ service_name: Literal["ec2"],
164
+ endpoint_url: Optional[str] = None,
165
+ ) -> "EC2ServiceResource": ...
166
+
167
+ def resource(
168
+ self,
169
+ region: Optional[str],
170
+ service_name: str,
171
+ endpoint_url: Optional[str] = None,
172
+ ) -> boto3.resources.base.ServiceResource:
124
173
  """
125
174
  Get the Boto3 Resource to use with the given service (like 'ec2') in the given region.
126
175
 
@@ -129,7 +178,7 @@ class AWSConnectionManager:
129
178
  """
130
179
  key = (region, service_name, endpoint_url)
131
180
  storage = self.resource_cache[key]
132
- if not hasattr(storage, 'item'):
181
+ if not hasattr(storage, "item"):
133
182
  with _init_lock:
134
183
  # We lock inside the if check; we don't care if the memoization
135
184
  # sometimes results in multiple different copies leaking out.
@@ -139,14 +188,69 @@ class AWSConnectionManager:
139
188
  # The Boto3 stubs are missing an overload for `resource` that takes
140
189
  # a non-literal string. See
141
190
  # <https://github.com/vemel/mypy_boto3_builder/issues/121#issuecomment-1011322636>
142
- storage.item = self.session(region).resource(service_name, endpoint_url=endpoint_url) # type: ignore
191
+ storage.item = self.session(region).resource(service_name, endpoint_url=endpoint_url) # type: ignore
143
192
  else:
144
193
  # We might not be able to pass None to Boto3 and have it be the same as no argument.
145
- storage.item = self.session(region).resource(service_name) # type: ignore
194
+ storage.item = self.session(region).resource(service_name) # type: ignore
146
195
 
147
196
  return cast(boto3.resources.base.ServiceResource, storage.item)
148
197
 
149
- def client(self, region: Optional[str], service_name: str, endpoint_url: Optional[str] = None, config: Optional[Config] = None) -> botocore.client.BaseClient:
198
+ @overload
199
+ def client(
200
+ self,
201
+ region: Optional[str],
202
+ service_name: Literal["ec2"],
203
+ endpoint_url: Optional[str] = None,
204
+ config: Optional[Config] = None,
205
+ ) -> "EC2Client": ...
206
+ @overload
207
+ def client(
208
+ self,
209
+ region: Optional[str],
210
+ service_name: Literal["iam"],
211
+ endpoint_url: Optional[str] = None,
212
+ config: Optional[Config] = None,
213
+ ) -> "IAMClient": ...
214
+ @overload
215
+ def client(
216
+ self,
217
+ region: Optional[str],
218
+ service_name: Literal["s3"],
219
+ endpoint_url: Optional[str] = None,
220
+ config: Optional[Config] = None,
221
+ ) -> "S3Client": ...
222
+ @overload
223
+ def client(
224
+ self,
225
+ region: Optional[str],
226
+ service_name: Literal["sts"],
227
+ endpoint_url: Optional[str] = None,
228
+ config: Optional[Config] = None,
229
+ ) -> "STSClient": ...
230
+ @overload
231
+ def client(
232
+ self,
233
+ region: Optional[str],
234
+ service_name: Literal["sdb"],
235
+ endpoint_url: Optional[str] = None,
236
+ config: Optional[Config] = None,
237
+ ) -> "SimpleDBClient": ...
238
+ @overload
239
+ def client(
240
+ self,
241
+ region: Optional[str],
242
+ service_name: Literal["autoscaling"],
243
+ endpoint_url: Optional[str] = None,
244
+ config: Optional[Config] = None,
245
+ ) -> "AutoScalingClient": ...
246
+
247
+ def client(
248
+ self,
249
+ region: Optional[str],
250
+ service_name: Literal["ec2", "iam", "s3", "sts", "sdb", "autoscaling"],
251
+ endpoint_url: Optional[str] = None,
252
+ config: Optional[Config] = None,
253
+ ) -> botocore.client.BaseClient:
150
254
  """
151
255
  Get the Boto3 Client to use with the given service (like 'ec2') in the given region.
152
256
 
@@ -159,42 +263,34 @@ class AWSConnectionManager:
159
263
  # Don't try and memoize if a custom config is used
160
264
  with _init_lock:
161
265
  if endpoint_url is not None:
162
- return self.session(region).client(service_name, endpoint_url=endpoint_url, config=config) # type: ignore
266
+ return self.session(region).client(
267
+ service_name, endpoint_url=endpoint_url, config=config
268
+ )
163
269
  else:
164
- return self.session(region).client(service_name, config=config) # type: ignore
270
+ return self.session(region).client(service_name, config=config)
165
271
 
166
272
  key = (region, service_name, endpoint_url)
167
273
  storage = self.client_cache[key]
168
- if not hasattr(storage, 'item'):
274
+ if not hasattr(storage, "item"):
169
275
  with _init_lock:
170
276
  # We lock because we call .client()
171
277
 
172
278
  if endpoint_url is not None:
173
279
  # The Boto3 stubs are probably missing an overload here too. See:
174
280
  # <https://github.com/vemel/mypy_boto3_builder/issues/121#issuecomment-1011322636>
175
- storage.item = self.session(region).client(service_name, endpoint_url=endpoint_url) # type: ignore
281
+ storage.item = self.session(region).client(
282
+ service_name, endpoint_url=endpoint_url
283
+ )
176
284
  else:
177
285
  # We might not be able to pass None to Boto3 and have it be the same as no argument.
178
- storage.item = self.session(region).client(service_name) # type: ignore
179
- return cast(botocore.client.BaseClient , storage.item)
286
+ storage.item = self.session(region).client(service_name)
287
+ return cast(botocore.client.BaseClient, storage.item)
180
288
 
181
- def boto2(self, region: Optional[str], service_name: str) -> boto.connection.AWSAuthConnection:
182
- """
183
- Get the connected boto2 connection for the given region and service.
184
- """
185
- if service_name == 'iam':
186
- # IAM connections are regionless
187
- region = 'universal'
188
- key = (region, service_name)
189
- storage = self.boto2_cache[key]
190
- if not hasattr(storage, 'item'):
191
- with _init_lock:
192
- storage.item = getattr(boto, service_name).connect_to_region(region, profile_name=os.environ.get("TOIL_AWS_PROFILE", None))
193
- return cast(boto.connection.AWSAuthConnection, storage.item)
194
289
 
195
290
  # If you don't want your own AWSConnectionManager, we have a global one and some global functions
196
291
  _global_manager = AWSConnectionManager()
197
292
 
293
+
198
294
  def establish_boto3_session(region_name: Optional[str] = None) -> Session:
199
295
  """
200
296
  Get a Boto 3 session usable by the current thread.
@@ -205,7 +301,57 @@ def establish_boto3_session(region_name: Optional[str] = None) -> Session:
205
301
  # Just use a global version of the manager. Note that we change the argument order!
206
302
  return _global_manager.session(region_name)
207
303
 
208
- def client(service_name: str, region_name: Optional[str] = None, endpoint_url: Optional[str] = None, config: Optional[Config] = None) -> botocore.client.BaseClient:
304
+
305
+ @overload
306
+ def client(
307
+ service_name: Literal["ec2"],
308
+ region_name: Optional[str] = None,
309
+ endpoint_url: Optional[str] = None,
310
+ config: Optional[Config] = None,
311
+ ) -> "EC2Client": ...
312
+ @overload
313
+ def client(
314
+ service_name: Literal["iam"],
315
+ region_name: Optional[str] = None,
316
+ endpoint_url: Optional[str] = None,
317
+ config: Optional[Config] = None,
318
+ ) -> "IAMClient": ...
319
+ @overload
320
+ def client(
321
+ service_name: Literal["s3"],
322
+ region_name: Optional[str] = None,
323
+ endpoint_url: Optional[str] = None,
324
+ config: Optional[Config] = None,
325
+ ) -> "S3Client": ...
326
+ @overload
327
+ def client(
328
+ service_name: Literal["sts"],
329
+ region_name: Optional[str] = None,
330
+ endpoint_url: Optional[str] = None,
331
+ config: Optional[Config] = None,
332
+ ) -> "STSClient": ...
333
+ @overload
334
+ def client(
335
+ service_name: Literal["sdb"],
336
+ region_name: Optional[str] = None,
337
+ endpoint_url: Optional[str] = None,
338
+ config: Optional[Config] = None,
339
+ ) -> "SimpleDBClient": ...
340
+ @overload
341
+ def client(
342
+ service_name: Literal["autoscaling"],
343
+ region_name: Optional[str] = None,
344
+ endpoint_url: Optional[str] = None,
345
+ config: Optional[Config] = None,
346
+ ) -> "AutoScalingClient": ...
347
+
348
+
349
+ def client(
350
+ service_name: Literal["ec2", "iam", "s3", "sts", "sdb", "autoscaling"],
351
+ region_name: Optional[str] = None,
352
+ endpoint_url: Optional[str] = None,
353
+ config: Optional[Config] = None,
354
+ ) -> botocore.client.BaseClient:
209
355
  """
210
356
  Get a Boto 3 client for a particular AWS service, usable by the current thread.
211
357
 
@@ -213,9 +359,36 @@ def client(service_name: str, region_name: Optional[str] = None, endpoint_url: O
213
359
  """
214
360
 
215
361
  # Just use a global version of the manager. Note that we change the argument order!
216
- return _global_manager.client(region_name, service_name, endpoint_url=endpoint_url, config=config)
217
-
218
- def resource(service_name: str, region_name: Optional[str] = None, endpoint_url: Optional[str] = None) -> boto3.resources.base.ServiceResource:
362
+ return _global_manager.client(
363
+ region_name, service_name, endpoint_url=endpoint_url, config=config
364
+ )
365
+
366
+
367
+ @overload
368
+ def resource(
369
+ service_name: Literal["s3"],
370
+ region_name: Optional[str] = None,
371
+ endpoint_url: Optional[str] = None,
372
+ ) -> "S3ServiceResource": ...
373
+ @overload
374
+ def resource(
375
+ service_name: Literal["iam"],
376
+ region_name: Optional[str] = None,
377
+ endpoint_url: Optional[str] = None,
378
+ ) -> "IAMServiceResource": ...
379
+ @overload
380
+ def resource(
381
+ service_name: Literal["ec2"],
382
+ region_name: Optional[str] = None,
383
+ endpoint_url: Optional[str] = None,
384
+ ) -> "EC2ServiceResource": ...
385
+
386
+
387
+ def resource(
388
+ service_name: Literal["s3", "iam", "ec2"],
389
+ region_name: Optional[str] = None,
390
+ endpoint_url: Optional[str] = None,
391
+ ) -> boto3.resources.base.ServiceResource:
219
392
  """
220
393
  Get a Boto 3 resource for a particular AWS service, usable by the current thread.
221
394
 
@@ -223,4 +396,6 @@ def resource(service_name: str, region_name: Optional[str] = None, endpoint_url:
223
396
  """
224
397
 
225
398
  # Just use a global version of the manager. Note that we change the argument order!
226
- return _global_manager.resource(region_name, service_name, endpoint_url=endpoint_url)
399
+ return _global_manager.resource(
400
+ region_name, service_name, endpoint_url=endpoint_url
401
+ )