Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/boto/regioninfo.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
| author | shellac |
|---|---|
| date | Sat, 02 May 2020 07:14:21 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:26e78fe6e8c4 |
|---|---|
| 1 # Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ | |
| 2 # Copyright (c) 2010, Eucalyptus Systems, Inc. | |
| 3 # All rights reserved. | |
| 4 # | |
| 5 # Permission is hereby granted, free of charge, to any person obtaining a | |
| 6 # copy of this software and associated documentation files (the | |
| 7 # "Software"), to deal in the Software without restriction, including | |
| 8 # without limitation the rights to use, copy, modify, merge, publish, dis- | |
| 9 # tribute, sublicense, and/or sell copies of the Software, and to permit | |
| 10 # persons to whom the Software is furnished to do so, subject to the fol- | |
| 11 # lowing conditions: | |
| 12 # | |
| 13 # The above copyright notice and this permission notice shall be included | |
| 14 # in all copies or substantial portions of the Software. | |
| 15 # | |
| 16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 17 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | |
| 18 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | |
| 19 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 20 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| 22 # IN THE SOFTWARE. | |
| 23 import os | |
| 24 | |
| 25 import boto | |
| 26 from boto.compat import json | |
| 27 from boto.exception import BotoClientError | |
| 28 from boto.endpoints import BotoEndpointResolver | |
| 29 from boto.endpoints import StaticEndpointBuilder | |
| 30 | |
| 31 | |
| 32 _endpoints_cache = {} | |
| 33 | |
| 34 | |
| 35 def load_endpoint_json(path): | |
| 36 """ | |
| 37 Loads a given JSON file & returns it. | |
| 38 | |
| 39 :param path: The path to the JSON file | |
| 40 :type path: string | |
| 41 | |
| 42 :returns: The loaded data | |
| 43 """ | |
| 44 return _load_json_file(path) | |
| 45 | |
| 46 | |
| 47 def _load_json_file(path): | |
| 48 """ | |
| 49 Loads a given JSON file & returns it. | |
| 50 | |
| 51 :param path: The path to the JSON file | |
| 52 :type path: string | |
| 53 | |
| 54 :returns: The loaded data | |
| 55 """ | |
| 56 with open(path, 'r') as endpoints_file: | |
| 57 return json.load(endpoints_file) | |
| 58 | |
| 59 | |
| 60 def merge_endpoints(defaults, additions): | |
| 61 """ | |
| 62 Given an existing set of endpoint data, this will deep-update it with | |
| 63 any similarly structured data in the additions. | |
| 64 | |
| 65 :param defaults: The existing endpoints data | |
| 66 :type defaults: dict | |
| 67 | |
| 68 :param defaults: The additional endpoints data | |
| 69 :type defaults: dict | |
| 70 | |
| 71 :returns: The modified endpoints data | |
| 72 :rtype: dict | |
| 73 """ | |
| 74 # We can't just do an ``defaults.update(...)`` here, as that could | |
| 75 # *overwrite* regions if present in both. | |
| 76 # We'll iterate instead, essentially doing a deeper merge. | |
| 77 for service, region_info in additions.items(): | |
| 78 # Set the default, if not present, to an empty dict. | |
| 79 defaults.setdefault(service, {}) | |
| 80 defaults[service].update(region_info) | |
| 81 | |
| 82 return defaults | |
| 83 | |
| 84 | |
| 85 def load_regions(): | |
| 86 """ | |
| 87 Actually load the region/endpoint information from the JSON files. | |
| 88 | |
| 89 By default, this loads from the default included ``boto/endpoints.json`` | |
| 90 file. | |
| 91 | |
| 92 Users can override/extend this by supplying either a ``BOTO_ENDPOINTS`` | |
| 93 environment variable or a ``endpoints_path`` config variable, either of | |
| 94 which should be an absolute path to the user's JSON file. | |
| 95 | |
| 96 :returns: The endpoints data | |
| 97 :rtype: dict | |
| 98 """ | |
| 99 # Load the defaults first. | |
| 100 endpoints = _load_builtin_endpoints() | |
| 101 additional_path = None | |
| 102 | |
| 103 # Try the ENV var. If not, check the config file. | |
| 104 if os.environ.get('BOTO_ENDPOINTS'): | |
| 105 additional_path = os.environ['BOTO_ENDPOINTS'] | |
| 106 elif boto.config.get('Boto', 'endpoints_path'): | |
| 107 additional_path = boto.config.get('Boto', 'endpoints_path') | |
| 108 | |
| 109 # If there's a file provided, we'll load it & additively merge it into | |
| 110 # the endpoints. | |
| 111 if additional_path: | |
| 112 additional = load_endpoint_json(additional_path) | |
| 113 endpoints = merge_endpoints(endpoints, additional) | |
| 114 | |
| 115 return endpoints | |
| 116 | |
| 117 | |
| 118 def _load_builtin_endpoints(_cache=_endpoints_cache): | |
| 119 """Loads the builtin endpoints in the legacy format.""" | |
| 120 # If there's a cached response, return it | |
| 121 if _cache: | |
| 122 return _cache | |
| 123 | |
| 124 # Load the endpoints file | |
| 125 endpoints = _load_json_file(boto.ENDPOINTS_PATH) | |
| 126 | |
| 127 # Build the endpoints into the legacy format | |
| 128 resolver = BotoEndpointResolver(endpoints) | |
| 129 builder = StaticEndpointBuilder(resolver) | |
| 130 endpoints = builder.build_static_endpoints() | |
| 131 | |
| 132 # Cache the endpoints and then return them | |
| 133 _cache.update(endpoints) | |
| 134 return _cache | |
| 135 | |
| 136 | |
| 137 def get_regions(service_name, region_cls=None, connection_cls=None): | |
| 138 """ | |
| 139 Given a service name (like ``ec2``), returns a list of ``RegionInfo`` | |
| 140 objects for that service. | |
| 141 | |
| 142 This leverages the ``endpoints.json`` file (+ optional user overrides) to | |
| 143 configure/construct all the objects. | |
| 144 | |
| 145 :param service_name: The name of the service to construct the ``RegionInfo`` | |
| 146 objects for. Ex: ``ec2``, ``s3``, ``sns``, etc. | |
| 147 :type service_name: string | |
| 148 | |
| 149 :param region_cls: (Optional) The class to use when constructing. By | |
| 150 default, this is ``RegionInfo``. | |
| 151 :type region_cls: class | |
| 152 | |
| 153 :param connection_cls: (Optional) The connection class for the | |
| 154 ``RegionInfo`` object. Providing this allows the ``connect`` method on | |
| 155 the ``RegionInfo`` to work. Default is ``None`` (no connection). | |
| 156 :type connection_cls: class | |
| 157 | |
| 158 :returns: A list of configured ``RegionInfo`` objects | |
| 159 :rtype: list | |
| 160 """ | |
| 161 endpoints = load_regions() | |
| 162 | |
| 163 if service_name not in endpoints: | |
| 164 raise BotoClientError( | |
| 165 "Service '%s' not found in endpoints." % service_name | |
| 166 ) | |
| 167 | |
| 168 if region_cls is None: | |
| 169 region_cls = RegionInfo | |
| 170 | |
| 171 region_objs = [] | |
| 172 | |
| 173 for region_name, endpoint in endpoints.get(service_name, {}).items(): | |
| 174 region_objs.append( | |
| 175 region_cls( | |
| 176 name=region_name, | |
| 177 endpoint=endpoint, | |
| 178 connection_cls=connection_cls | |
| 179 ) | |
| 180 ) | |
| 181 | |
| 182 return region_objs | |
| 183 | |
| 184 | |
| 185 def connect(service_name, region_name, region_cls=None, | |
| 186 connection_cls=None, **kw_params): | |
| 187 """Create a connection class for a given service in a given region. | |
| 188 | |
| 189 :param service_name: The name of the service to construct the | |
| 190 ``RegionInfo`` object for, e.g. ``ec2``, ``s3``, etc. | |
| 191 :type service_name: str | |
| 192 | |
| 193 :param region_name: The name of the region to connect to, e.g. | |
| 194 ``us-west-2``, ``eu-central-1``, etc. | |
| 195 :type region_name: str | |
| 196 | |
| 197 :param region_cls: (Optional) The class to use when constructing. By | |
| 198 default, this is ``RegionInfo``. | |
| 199 :type region_cls: class | |
| 200 | |
| 201 :param connection_cls: (Optional) The connection class for the | |
| 202 ``RegionInfo`` object. Providing this allows the ``connect`` method on | |
| 203 the ``RegionInfo`` to work. Default is ``None`` (no connection). | |
| 204 :type connection_cls: class | |
| 205 | |
| 206 :returns: A configured connection class. | |
| 207 """ | |
| 208 if region_cls is None: | |
| 209 region_cls = RegionInfo | |
| 210 region = _get_region(service_name, region_name, region_cls, connection_cls) | |
| 211 | |
| 212 if region is None and _use_endpoint_heuristics(): | |
| 213 region = _get_region_with_heuristics( | |
| 214 service_name, region_name, region_cls, connection_cls | |
| 215 ) | |
| 216 | |
| 217 if region is None: | |
| 218 return None | |
| 219 | |
| 220 return region.connect(**kw_params) | |
| 221 | |
| 222 | |
| 223 def _get_region(service_name, region_name, region_cls=None, | |
| 224 connection_cls=None): | |
| 225 """Finds the region by searching through the known regions.""" | |
| 226 for region in get_regions(service_name, region_cls, connection_cls): | |
| 227 if region.name == region_name: | |
| 228 return region | |
| 229 return None | |
| 230 | |
| 231 | |
| 232 def _get_region_with_heuristics(service_name, region_name, region_cls=None, | |
| 233 connection_cls=None): | |
| 234 """Finds the region using known regions and heuristics.""" | |
| 235 endpoints = load_endpoint_json(boto.ENDPOINTS_PATH) | |
| 236 resolver = BotoEndpointResolver(endpoints) | |
| 237 hostname = resolver.resolve_hostname(service_name, region_name) | |
| 238 | |
| 239 return region_cls( | |
| 240 name=region_name, | |
| 241 endpoint=hostname, | |
| 242 connection_cls=connection_cls | |
| 243 ) | |
| 244 | |
| 245 | |
| 246 def _use_endpoint_heuristics(): | |
| 247 env_var = os.environ.get('BOTO_USE_ENDPOINT_HEURISTICS', 'false').lower() | |
| 248 config_var = boto.config.getbool('Boto', 'use_endpoint_heuristics', False) | |
| 249 return env_var == 'true' or config_var | |
| 250 | |
| 251 | |
| 252 class RegionInfo(object): | |
| 253 """ | |
| 254 Represents an AWS Region | |
| 255 """ | |
| 256 | |
| 257 def __init__(self, connection=None, name=None, endpoint=None, | |
| 258 connection_cls=None): | |
| 259 self.connection = connection | |
| 260 self.name = name | |
| 261 self.endpoint = endpoint | |
| 262 self.connection_cls = connection_cls | |
| 263 | |
| 264 def __repr__(self): | |
| 265 return 'RegionInfo:%s' % self.name | |
| 266 | |
| 267 def startElement(self, name, attrs, connection): | |
| 268 return None | |
| 269 | |
| 270 def endElement(self, name, value, connection): | |
| 271 if name == 'regionName': | |
| 272 self.name = value | |
| 273 elif name == 'regionEndpoint': | |
| 274 self.endpoint = value | |
| 275 else: | |
| 276 setattr(self, name, value) | |
| 277 | |
| 278 def connect(self, **kw_params): | |
| 279 """ | |
| 280 Connect to this Region's endpoint. Returns an connection | |
| 281 object pointing to the endpoint associated with this region. | |
| 282 You may pass any of the arguments accepted by the connection | |
| 283 class's constructor as keyword arguments and they will be | |
| 284 passed along to the connection object. | |
| 285 | |
| 286 :rtype: Connection object | |
| 287 :return: The connection to this regions endpoint | |
| 288 """ | |
| 289 if self.connection_cls: | |
| 290 return self.connection_cls(region=self, **kw_params) |
