comparison env/lib/python3.7/site-packages/boto/exception.py @ 5:9b1c78e6ba9c draft default tip

"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author shellac
date Mon, 01 Jun 2020 08:59:25 -0400
parents 79f47841a781
children
comparison
equal deleted inserted replaced
4:79f47841a781 5:9b1c78e6ba9c
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
24 """
25 Exception classes - Subclassing allows you to check for specific errors
26 """
27 import base64
28 import xml.sax
29
30 import boto
31
32 from boto import handler
33 from boto.compat import json, StandardError
34 from boto.resultset import ResultSet
35
36
37 class BotoClientError(StandardError):
38 """
39 General Boto Client error (error accessing AWS)
40 """
41 def __init__(self, reason, *args):
42 super(BotoClientError, self).__init__(reason, *args)
43 self.reason = reason
44
45 def __repr__(self):
46 return 'BotoClientError: %s' % self.reason
47
48 def __str__(self):
49 return 'BotoClientError: %s' % self.reason
50
51
52 class SDBPersistenceError(StandardError):
53 pass
54
55
56 class StoragePermissionsError(BotoClientError):
57 """
58 Permissions error when accessing a bucket or key on a storage service.
59 """
60 pass
61
62
63 class S3PermissionsError(StoragePermissionsError):
64 """
65 Permissions error when accessing a bucket or key on S3.
66 """
67 pass
68
69
70 class GSPermissionsError(StoragePermissionsError):
71 """
72 Permissions error when accessing a bucket or key on GS.
73 """
74 pass
75
76
77 class BotoServerError(StandardError):
78 def __init__(self, status, reason, body=None, *args):
79 super(BotoServerError, self).__init__(status, reason, body, *args)
80 self.status = status
81 self.reason = reason
82 self.body = body or ''
83 self.request_id = None
84 self.error_code = None
85 self._error_message = None
86 self.message = ''
87 self.box_usage = None
88
89 if isinstance(self.body, bytes):
90 try:
91 self.body = self.body.decode('utf-8')
92 except UnicodeDecodeError:
93 boto.log.debug('Unable to decode body from bytes!')
94
95 # Attempt to parse the error response. If body isn't present,
96 # then just ignore the error response.
97 if self.body:
98 # Check if it looks like a ``dict``.
99 if hasattr(self.body, 'items'):
100 # It's not a string, so trying to parse it will fail.
101 # But since it's data, we can work with that.
102 self.request_id = self.body.get('RequestId', None)
103
104 if 'Error' in self.body:
105 # XML-style
106 error = self.body.get('Error', {})
107 self.error_code = error.get('Code', None)
108 self.message = error.get('Message', None)
109 else:
110 # JSON-style.
111 self.message = self.body.get('message', None)
112 else:
113 try:
114 h = handler.XmlHandlerWrapper(self, self)
115 h.parseString(self.body)
116 except (TypeError, xml.sax.SAXParseException):
117 # What if it's JSON? Let's try that.
118 try:
119 parsed = json.loads(self.body)
120
121 if 'RequestId' in parsed:
122 self.request_id = parsed['RequestId']
123 if 'Error' in parsed:
124 if 'Code' in parsed['Error']:
125 self.error_code = parsed['Error']['Code']
126 if 'Message' in parsed['Error']:
127 self.message = parsed['Error']['Message']
128
129 except (TypeError, ValueError):
130 # Remove unparsable message body so we don't include garbage
131 # in exception. But first, save self.body in self.error_message
132 # because occasionally we get error messages from Eucalyptus
133 # that are just text strings that we want to preserve.
134 self.message = self.body
135 self.body = None
136
137 def __getattr__(self, name):
138 if name == 'error_message':
139 return self.message
140 if name == 'code':
141 return self.error_code
142 raise AttributeError
143
144 def __setattr__(self, name, value):
145 if name == 'error_message':
146 self.message = value
147 else:
148 super(BotoServerError, self).__setattr__(name, value)
149
150 def __repr__(self):
151 return '%s: %s %s\n%s' % (self.__class__.__name__,
152 self.status, self.reason, self.body)
153
154 def __str__(self):
155 return '%s: %s %s\n%s' % (self.__class__.__name__,
156 self.status, self.reason, self.body)
157
158 def startElement(self, name, attrs, connection):
159 pass
160
161 def endElement(self, name, value, connection):
162 if name in ('RequestId', 'RequestID'):
163 self.request_id = value
164 elif name == 'Code':
165 self.error_code = value
166 elif name == 'Message':
167 self.message = value
168 elif name == 'BoxUsage':
169 self.box_usage = value
170 return None
171
172 def _cleanupParsedProperties(self):
173 self.request_id = None
174 self.error_code = None
175 self.message = None
176 self.box_usage = None
177
178
179 class ConsoleOutput(object):
180 def __init__(self, parent=None):
181 self.parent = parent
182 self.instance_id = None
183 self.timestamp = None
184 self.comment = None
185 self.output = None
186
187 def startElement(self, name, attrs, connection):
188 return None
189
190 def endElement(self, name, value, connection):
191 if name == 'instanceId':
192 self.instance_id = value
193 elif name == 'output':
194 self.output = base64.b64decode(value)
195 else:
196 setattr(self, name, value)
197
198
199 class StorageCreateError(BotoServerError):
200 """
201 Error creating a bucket or key on a storage service.
202 """
203 def __init__(self, status, reason, body=None):
204 self.bucket = None
205 super(StorageCreateError, self).__init__(status, reason, body)
206
207 def endElement(self, name, value, connection):
208 if name == 'BucketName':
209 self.bucket = value
210 else:
211 return super(StorageCreateError, self).endElement(name, value, connection)
212
213
214 class S3CreateError(StorageCreateError):
215 """
216 Error creating a bucket or key on S3.
217 """
218 pass
219
220
221 class GSCreateError(StorageCreateError):
222 """
223 Error creating a bucket or key on GS.
224 """
225 pass
226
227
228 class StorageCopyError(BotoServerError):
229 """
230 Error copying a key on a storage service.
231 """
232 pass
233
234
235 class S3CopyError(StorageCopyError):
236 """
237 Error copying a key on S3.
238 """
239 pass
240
241
242 class GSCopyError(StorageCopyError):
243 """
244 Error copying a key on GS.
245 """
246 pass
247
248
249 class SQSError(BotoServerError):
250 """
251 General Error on Simple Queue Service.
252 """
253 def __init__(self, status, reason, body=None):
254 self.detail = None
255 self.type = None
256 super(SQSError, self).__init__(status, reason, body)
257
258 def startElement(self, name, attrs, connection):
259 return super(SQSError, self).startElement(name, attrs, connection)
260
261 def endElement(self, name, value, connection):
262 if name == 'Detail':
263 self.detail = value
264 elif name == 'Type':
265 self.type = value
266 else:
267 return super(SQSError, self).endElement(name, value, connection)
268
269 def _cleanupParsedProperties(self):
270 super(SQSError, self)._cleanupParsedProperties()
271 for p in ('detail', 'type'):
272 setattr(self, p, None)
273
274
275 class SQSDecodeError(BotoClientError):
276 """
277 Error when decoding an SQS message.
278 """
279 def __init__(self, reason, message):
280 super(SQSDecodeError, self).__init__(reason, message)
281 self.message = message
282
283 def __repr__(self):
284 return 'SQSDecodeError: %s' % self.reason
285
286 def __str__(self):
287 return 'SQSDecodeError: %s' % self.reason
288
289
290 class StorageResponseError(BotoServerError):
291 """
292 Error in response from a storage service.
293 """
294 def __init__(self, status, reason, body=None):
295 self.resource = None
296 super(StorageResponseError, self).__init__(status, reason, body)
297
298 def startElement(self, name, attrs, connection):
299 return super(StorageResponseError, self).startElement(
300 name, attrs, connection)
301
302 def endElement(self, name, value, connection):
303 if name == 'Resource':
304 self.resource = value
305 else:
306 return super(StorageResponseError, self).endElement(
307 name, value, connection)
308
309 def _cleanupParsedProperties(self):
310 super(StorageResponseError, self)._cleanupParsedProperties()
311 for p in ('resource'):
312 setattr(self, p, None)
313
314
315 class S3ResponseError(StorageResponseError):
316 """
317 Error in response from S3.
318 """
319 pass
320
321
322 class GSResponseError(StorageResponseError):
323 """
324 Error in response from GS.
325 """
326 pass
327
328
329 class EC2ResponseError(BotoServerError):
330 """
331 Error in response from EC2.
332 """
333 def __init__(self, status, reason, body=None):
334 self.errors = None
335 self._errorResultSet = []
336 super(EC2ResponseError, self).__init__(status, reason, body)
337 self.errors = [
338 (e.error_code, e.error_message) for e in self._errorResultSet]
339 if len(self.errors):
340 self.error_code, self.error_message = self.errors[0]
341
342 def startElement(self, name, attrs, connection):
343 if name == 'Errors':
344 self._errorResultSet = ResultSet([('Error', _EC2Error)])
345 return self._errorResultSet
346 else:
347 return None
348
349 def endElement(self, name, value, connection):
350 if name == 'RequestID':
351 self.request_id = value
352 else:
353 return None # don't call subclass here
354
355 def _cleanupParsedProperties(self):
356 super(EC2ResponseError, self)._cleanupParsedProperties()
357 self._errorResultSet = []
358 for p in ('errors'):
359 setattr(self, p, None)
360
361
362 class JSONResponseError(BotoServerError):
363 """
364 This exception expects the fully parsed and decoded JSON response
365 body to be passed as the body parameter.
366
367 :ivar status: The HTTP status code.
368 :ivar reason: The HTTP reason message.
369 :ivar body: The Python dict that represents the decoded JSON
370 response body.
371 :ivar error_message: The full description of the AWS error encountered.
372 :ivar error_code: A short string that identifies the AWS error
373 (e.g. ConditionalCheckFailedException)
374 """
375 def __init__(self, status, reason, body=None, *args):
376 self.status = status
377 self.reason = reason
378 self.body = body
379 if self.body:
380 self.error_message = self.body.get('message', None)
381 self.error_code = self.body.get('__type', None)
382 if self.error_code:
383 self.error_code = self.error_code.split('#')[-1]
384
385
386 class DynamoDBResponseError(JSONResponseError):
387 pass
388
389
390 class SWFResponseError(JSONResponseError):
391 pass
392
393
394 class EmrResponseError(BotoServerError):
395 """
396 Error in response from EMR
397 """
398 pass
399
400
401 class _EC2Error(object):
402 def __init__(self, connection=None):
403 self.connection = connection
404 self.error_code = None
405 self.error_message = None
406
407 def startElement(self, name, attrs, connection):
408 return None
409
410 def endElement(self, name, value, connection):
411 if name == 'Code':
412 self.error_code = value
413 elif name == 'Message':
414 self.error_message = value
415 else:
416 return None
417
418
419 class SDBResponseError(BotoServerError):
420 """
421 Error in responses from SDB.
422 """
423 pass
424
425
426 class AWSConnectionError(BotoClientError):
427 """
428 General error connecting to Amazon Web Services.
429 """
430 pass
431
432
433 class StorageDataError(BotoClientError):
434 """
435 Error receiving data from a storage service.
436 """
437 pass
438
439
440 class S3DataError(StorageDataError):
441 """
442 Error receiving data from S3.
443 """
444 pass
445
446
447 class GSDataError(StorageDataError):
448 """
449 Error receiving data from GS.
450 """
451 pass
452
453
454 class InvalidUriError(Exception):
455 """Exception raised when URI is invalid."""
456
457 def __init__(self, message):
458 super(InvalidUriError, self).__init__(message)
459 self.message = message
460
461
462 class InvalidAclError(Exception):
463 """Exception raised when ACL XML is invalid."""
464
465 def __init__(self, message):
466 super(InvalidAclError, self).__init__(message)
467 self.message = message
468
469
470 class InvalidCorsError(Exception):
471 """Exception raised when CORS XML is invalid."""
472
473 def __init__(self, message):
474 super(InvalidCorsError, self).__init__(message)
475 self.message = message
476
477
478 class InvalidEncryptionConfigError(Exception):
479 """Exception raised when GCS encryption configuration XML is invalid."""
480
481 def __init__(self, message):
482 super(InvalidEncryptionConfigError, self).__init__(message)
483 self.message = message
484
485
486 class InvalidLifecycleConfigError(Exception):
487 """Exception raised when GCS lifecycle configuration XML is invalid."""
488
489 def __init__(self, message):
490 super(InvalidLifecycleConfigError, self).__init__(message)
491 self.message = message
492
493
494 class NoAuthHandlerFound(Exception):
495 """Is raised when no auth handlers were found ready to authenticate."""
496 pass
497
498
499 # Enum class for resumable upload failure disposition.
500 class ResumableTransferDisposition(object):
501 # START_OVER means an attempt to resume an existing transfer failed,
502 # and a new resumable upload should be attempted (without delay).
503 START_OVER = 'START_OVER'
504
505 # WAIT_BEFORE_RETRY means the resumable transfer failed but that it can
506 # be retried after a time delay within the current process.
507 WAIT_BEFORE_RETRY = 'WAIT_BEFORE_RETRY'
508
509 # ABORT_CUR_PROCESS means the resumable transfer failed and that
510 # delaying/retrying within the current process will not help. If
511 # resumable transfer included a state tracker file the upload can be
512 # retried again later, in another process (e.g., a later run of gsutil).
513 ABORT_CUR_PROCESS = 'ABORT_CUR_PROCESS'
514
515 # ABORT means the resumable transfer failed in a way that it does not
516 # make sense to continue in the current process, and further that the
517 # current tracker ID should not be preserved (in a tracker file if one
518 # was specified at resumable upload start time). If the user tries again
519 # later (e.g., a separate run of gsutil) it will get a new resumable
520 # upload ID.
521 ABORT = 'ABORT'
522
523
524 class ResumableUploadException(Exception):
525 """
526 Exception raised for various resumable upload problems.
527
528 self.disposition is of type ResumableTransferDisposition.
529 """
530
531 def __init__(self, message, disposition):
532 super(ResumableUploadException, self).__init__(message, disposition)
533 self.message = message
534 self.disposition = disposition
535
536 def __repr__(self):
537 return 'ResumableUploadException("%s", %s)' % (
538 self.message, self.disposition)
539
540
541 class ResumableDownloadException(Exception):
542 """
543 Exception raised for various resumable download problems.
544
545 self.disposition is of type ResumableTransferDisposition.
546 """
547
548 def __init__(self, message, disposition):
549 super(ResumableDownloadException, self).__init__(message, disposition)
550 self.message = message
551 self.disposition = disposition
552
553 def __repr__(self):
554 return 'ResumableDownloadException("%s", %s)' % (
555 self.message, self.disposition)
556
557
558 class TooManyRecordsException(Exception):
559 """
560 Exception raised when a search of Route53 records returns more
561 records than requested.
562 """
563
564 def __init__(self, message):
565 super(TooManyRecordsException, self).__init__(message)
566 self.message = message
567
568
569 class PleaseRetryException(Exception):
570 """
571 Indicates a request should be retried.
572 """
573 def __init__(self, message, response=None):
574 self.message = message
575 self.response = response
576
577 def __repr__(self):
578 return 'PleaseRetryException("%s", %s)' % (
579 self.message,
580 self.response
581 )
582
583
584 class InvalidInstanceMetadataError(Exception):
585 MSG = (
586 "You can set the 'metadata_service_num_attempts' "
587 "in your boto config file to increase the number "
588 "of times boto will attempt to retrieve "
589 "credentials from the instance metadata service."
590 )
591 def __init__(self, msg):
592 final_msg = msg + '\n' + self.MSG
593 super(InvalidInstanceMetadataError, self).__init__(final_msg)