{"action":"created","issue":{"url":"https://api.github.com/repos/boto/botocore/issues/965","repository_url":"https://api.github.com/repos/boto/botocore","labels_url":"https://api.github.com/repos/boto/botocore/issues/965/labels{/name}","comments_url":"https://api.github.com/repos/boto/botocore/issues/965/comments","events_url":"https://api.github.com/repos/boto/botocore/issues/965/events","html_url":"https://github.com/boto/botocore/pull/965","id":161916231,"number":965,"title":"fixes #926 - expose retry information in exceptions","user":{"login":"jantman","id":273454,"avatar_url":"https://avatars.githubusercontent.com/u/273454?v=3","gravatar_id":"","url":"https://api.github.com/users/jantman","html_url":"https://github.com/jantman","followers_url":"https://api.github.com/users/jantman/followers","following_url":"https://api.github.com/users/jantman/following{/other_user}","gists_url":"https://api.github.com/users/jantman/gists{/gist_id}","starred_url":"https://api.github.com/users/jantman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jantman/subscriptions","organizations_url":"https://api.github.com/users/jantman/orgs","repos_url":"https://api.github.com/users/jantman/repos","events_url":"https://api.github.com/users/jantman/events{/privacy}","received_events_url":"https://api.github.com/users/jantman/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/boto/botocore/labels/needs-discussion","name":"needs-discussion","color":"e99695"},{"url":"https://api.github.com/repos/boto/botocore/labels/needs-review","name":"needs-review","color":"5319e7"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":17,"created_at":"2016-06-23T12:56:48Z","updated_at":"2016-08-03T18:02:08Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/boto/botocore/pulls/965","html_url":"https://github.com/boto/botocore/pull/965","diff_url":"https://github.com/boto/botocore/pull/965.diff","patch_url":"https://github.com/boto/botocore/pull/965.patch"},"body":"This is my attempt at fixing #926 by providing information on retries in ``ResponseMetadata``, which is returned as part of the exceptions that are raised to the user.\r\n\r\n* in botocore.retryhandler.MaxAttemptsDecorator.__call__(), add a MaxAttemptsReached=True element to ResponseMetadata if the maximum number of attempts is reached\r\n* in botocore.endpoint.Endpoint._send_request(), add a NumAttempts element to ResponseMetadata, containing the attempt number\r\n\r\nAn example of this in action:\r\n\r\n```python\r\n#!/usr/bin/env python\r\n\r\nimport boto3\r\nfrom mock import patch, Mock\r\nfrom botocore.vendored.requests.models import Response\r\n\r\nec2 = boto3.resource('ec2')\r\ni = ec2.Instance('i-0')\r\n\r\ndef mock_get_response(self, request, operation_model, attempts):\r\n    headers = {\r\n        'transfer-encoding': 'chunked',\r\n        'date': 'Thu, 23 Jun 2016 11:32:42 GMT',\r\n        'connection': 'close',\r\n        'server': 'AmazonEC2'\r\n    }\r\n    mock_resp = Mock(spec_set=Response)\r\n    type(mock_resp).content = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<Response><Errors><Error><Type>Sender</Type><Code>Throttling</Code><Message>Rate exceeded</Message></Error></Errors><RequestID>44c0f570-e338-48dd-9953-6684fa586dcb</RequestID></Response>'\r\n    type(mock_resp).headers = headers\r\n    type(mock_resp).status_code = 400\r\n    parsed = {\r\n        'ResponseMetadata': {\r\n            'HTTPStatusCode': 400,\r\n            'RequestId': '44c0f570-e338-48dd-9953-6684fa586dcb',\r\n            'HTTPHeaders': headers\r\n        },\r\n        'Error': {\r\n            'Message': \"Rate exceeded\",\r\n            'Code': 'Throttling'\r\n        }\r\n    }\r\n    return (mock_resp, parsed), None\r\n\r\n\r\nwith patch('botocore.endpoint.Endpoint._get_response', side_effect=mock_get_response, autospec=True):\r\n    try:\r\n        x = i.hypervisor\r\n    except Exception as ex:\r\n        print(ex.response)\r\n```\r\n\r\n```console\r\n(botocore)jantman@phoenix:pts/14:~/GIT/botocore (issue926_retry_info %=)$ time python ~/tmp/test.py \r\n{'ResponseMetadata': {'NumAttempts': 5, 'HTTPStatusCode': 400, 'MaxAttemptsReached': True, 'RequestId': '44c0f570-e338-48dd-9953-6684fa586dcb', 'HTTPHeaders': {'transfer-encoding': 'chunked', 'date': 'Thu, 23 Jun 2016 11:32:42 GMT', 'connection': 'close', 'server': 'AmazonEC2'}}, 'Error': {'Message': 'Rate exceeded', 'Code': 'Throttling'}}\r\n\r\nreal    0m13.479s\r\nuser    0m0.340s\r\nsys     0m0.043s\r\n```"},"comment":{"url":"https://api.github.com/repos/boto/botocore/issues/comments/237317856","html_url":"https://github.com/boto/botocore/pull/965#issuecomment-237317856","issue_url":"https://api.github.com/repos/boto/botocore/issues/965","id":237317856,"user":{"login":"jantman","id":273454,"avatar_url":"https://avatars.githubusercontent.com/u/273454?v=3","gravatar_id":"","url":"https://api.github.com/users/jantman","html_url":"https://github.com/jantman","followers_url":"https://api.github.com/users/jantman/followers","following_url":"https://api.github.com/users/jantman/following{/other_user}","gists_url":"https://api.github.com/users/jantman/gists{/gist_id}","starred_url":"https://api.github.com/users/jantman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jantman/subscriptions","organizations_url":"https://api.github.com/users/jantman/orgs","repos_url":"https://api.github.com/users/jantman/repos","events_url":"https://api.github.com/users/jantman/events{/privacy}","received_events_url":"https://api.github.com/users/jantman/received_events","type":"User","site_admin":false},"created_at":"2016-08-03T18:02:08Z","updated_at":"2016-08-03T18:02:08Z","body":"@jamesls @JordonPhillips ping?"}}
{"actor":{"display_login":"jantman"}}