)]}'
{"swiftclient/client.py":[{"author":{"_account_id":860,"name":"Donagh McCabe","email":"donagh.mccabe@gmail.com","username":"donagh-mccabe"},"change_message_id":"149bea2004e3494d24617977f3ccc6fab4b5ce34","unresolved":false,"context_lines":[{"line_number":1346,"context_line":""},{"line_number":1347,"context_line":"        while True:"},{"line_number":1348,"context_line":"            connect_attempts +\u003d self.attempts"},{"line_number":1349,"context_line":"            for chunk in body:"},{"line_number":1350,"context_line":"                yield chunk"},{"line_number":1351,"context_line":"                bytes_read +\u003d len(chunk)"},{"line_number":1352,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"ba7be1f8_2bf45e86","line":1349,"updated":"2015-02-27 15:39:32.000000000","message":"I think you need to wrap this in try/except and catch ConnectionError and Timeout (see http://docs.python-requests.org/en/latest/user/quickstart/#errors-and-exceptions).\n\nAs-is, you only retry if the proxy-server does a clean close having not sent all data.\n\nTimeout is an interesting problem. One approach is to do nothing. However, I think the default is to wait forever -- which seems to negate the purpose of this patch since non-arrival of data is probably a common failure scenario.\n\nDeferring a discussion on an appropriate default value, there are two ways you could implement it: set it on requests.get() ... but that would apply to all API operations. Alternately, you wrap the body.next() in a \"with Timeout...\" --- though I\u0027ve no idea how big the chunk size is at this stage -- it\u0027s not Swift\u0027s 64k chunks.\n\nWrt a default value for timeout, one option is to punt to the caller and implement timeout if they specify it on a (new) parameter to Connect. Or you pick a large value (minutes/hours?). (this is not timeout on the *whole* body -- just timeout on chunks)","commit_id":"2684596c107eab903ccb96f9dcd18563a17fa72b"},{"author":{"_account_id":455,"name":"Stuart McLaren","email":"stuart.mclaren@hpe.com","username":"stuart-mclaren"},"change_message_id":"5a5307604476e782eb5e405f2bb3abda54a95754","unresolved":false,"context_lines":[{"line_number":1346,"context_line":""},{"line_number":1347,"context_line":"        while True:"},{"line_number":1348,"context_line":"            connect_attempts +\u003d self.attempts"},{"line_number":1349,"context_line":"            for chunk in body:"},{"line_number":1350,"context_line":"                yield chunk"},{"line_number":1351,"context_line":"                bytes_read +\u003d len(chunk)"},{"line_number":1352,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"ba7be1f8_b5bee3d2","line":1349,"in_reply_to":"ba7be1f8_2bf45e86","updated":"2015-02-27 16:00:35.000000000","message":"Thanks Donagh.\n\nConnectionError: Is it possible to get this at this point? Or is it sufficient that _retry catches this (the connection is established in _retry)?\n\nTimeout: Let me think about this. It\u0027s not handled in _retry at all, and I\u0027m not sure what the behaviour is by default. Arguably, it could be handled in a later patch (ie doing nothing may be an option for a first pass.)","commit_id":"2684596c107eab903ccb96f9dcd18563a17fa72b"},{"author":{"_account_id":455,"name":"Stuart McLaren","email":"stuart.mclaren@hpe.com","username":"stuart-mclaren"},"change_message_id":"abdcac5058cf8f7bdd1c1834004b4b7d305d0490","unresolved":false,"context_lines":[{"line_number":1346,"context_line":""},{"line_number":1347,"context_line":"        while True:"},{"line_number":1348,"context_line":"            connect_attempts +\u003d self.attempts"},{"line_number":1349,"context_line":"            for chunk in body:"},{"line_number":1350,"context_line":"                yield chunk"},{"line_number":1351,"context_line":"                bytes_read +\u003d len(chunk)"},{"line_number":1352,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"ba7be1f8_c681ba90","line":1349,"in_reply_to":"ba7be1f8_b5bee3d2","updated":"2015-03-02 11:20:59.000000000","message":"\u003e Timeout: Let me think about this. It\u0027s not handled in _retry at all.\n\nLooking again, I see that the base requests exception RequestException is handled in _retry, so Timeout is implicitly handled. It probably makes sense to do the same here.","commit_id":"2684596c107eab903ccb96f9dcd18563a17fa72b"},{"author":{"_account_id":860,"name":"Donagh McCabe","email":"donagh.mccabe@gmail.com","username":"donagh-mccabe"},"change_message_id":"149bea2004e3494d24617977f3ccc6fab4b5ce34","unresolved":false,"context_lines":[{"line_number":1358,"context_line":"                        kwargs[\u0027headers\u0027] \u003d {}"},{"line_number":1359,"context_line":"                    kwargs[\u0027headers\u0027][\u0027Range\u0027] \u003d \u0027bytes\u003d%d-\u0027 % bytes_read"},{"line_number":1360,"context_line":"                    __, body \u003d self._retry(None, get_object, *args, **kwargs)"},{"line_number":1361,"context_line":"                else:"},{"line_number":1362,"context_line":"                    break"},{"line_number":1363,"context_line":""},{"line_number":1364,"context_line":"    def get_object(self, *args, **kwargs):"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba7be1f8_ff0d9c38","line":1361,"updated":"2015-02-27 15:39:32.000000000","message":"If you catch exceptions above, you need to re-raise them here.","commit_id":"2684596c107eab903ccb96f9dcd18563a17fa72b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b4812bbc04f3eb1c3fd99243344efc3efdf0f849","unresolved":false,"context_lines":[{"line_number":200,"context_line":"                                          query_string\u003dself.query_string,"},{"line_number":201,"context_line":"                                          response_dict\u003dself.response_dict,"},{"line_number":202,"context_line":"                                          headers\u003dself.headers)"},{"line_number":203,"context_line":"            if hdrs[\u0027etag\u0027] !\u003d self.expected_etag:"},{"line_number":204,"context_line":"                raise ClientException(\u0027get_object(%r, %r, ...) failure \u0027"},{"line_number":205,"context_line":"                                      \u0027and no ability to retry.\u0027"},{"line_number":206,"context_line":"                                      % (self.container, self.obj))"}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_8da8a278","line":203,"updated":"2015-11-11 19:42:13.000000000","message":"Any reason not to just include an if-match header in headers?","commit_id":"1732b0e5ba8391da97a68be8c21d4b66c9204d26"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b4812bbc04f3eb1c3fd99243344efc3efdf0f849","unresolved":false,"context_lines":[{"line_number":995,"context_line":"                              http_status\u003dresp.status,"},{"line_number":996,"context_line":"                              http_reason\u003dresp.reason,"},{"line_number":997,"context_line":"                              http_response_content\u003dbody)"},{"line_number":998,"context_line":"    object_body \u003d _ObjectBody(resp, resp_chunk_size)"},{"line_number":999,"context_line":"    http_log((\u0027%s%s\u0027 % (url.replace(parsed.path, \u0027\u0027), path), method,),"},{"line_number":1000,"context_line":"             {\u0027headers\u0027: headers}, resp, None)"},{"line_number":1001,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_8d7c22b6","line":998,"updated":"2015-11-11 19:42:13.000000000","message":"This changes the contract for get_object -- how certain are we that *everyone* uses the Connection wrapper and *no one* uses get_object directly?","commit_id":"1732b0e5ba8391da97a68be8c21d4b66c9204d26"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f2fff89b1a3215a0eb082664422b16f20773cfbd","unresolved":false,"context_lines":[{"line_number":995,"context_line":"                              http_status\u003dresp.status,"},{"line_number":996,"context_line":"                              http_reason\u003dresp.reason,"},{"line_number":997,"context_line":"                              http_response_content\u003dbody)"},{"line_number":998,"context_line":"    object_body \u003d _ObjectBody(resp, resp_chunk_size)"},{"line_number":999,"context_line":"    http_log((\u0027%s%s\u0027 % (url.replace(parsed.path, \u0027\u0027), path), method,),"},{"line_number":1000,"context_line":"             {\u0027headers\u0027: headers}, resp, None)"},{"line_number":1001,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_c340bb36","line":998,"in_reply_to":"da85f559_8d7c22b6","updated":"2015-11-11 22:22:14.000000000","message":"do we really not have any unittests that use get_object and expect a string back or is _ObjectBody a string like!?\n\n... apparently not\n\nhttps://gist.github.com/clayg/8cde71ba20839ba28997","commit_id":"1732b0e5ba8391da97a68be8c21d4b66c9204d26"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b4812bbc04f3eb1c3fd99243344efc3efdf0f849","unresolved":false,"context_lines":[{"line_number":1536,"context_line":"    def get_object(self, container, obj, resp_chunk_size\u003dNone,"},{"line_number":1537,"context_line":"                   query_string\u003dNone, response_dict\u003dNone, headers\u003dNone):"},{"line_number":1538,"context_line":"        \"\"\"Wrapper for :func:`get_object`\"\"\""},{"line_number":1539,"context_line":"        def _norange():"},{"line_number":1540,"context_line":"            # We don\u0027t currently support data retry for range based requests"},{"line_number":1541,"context_line":"            return not headers or \u0027Range\u0027 not in headers"},{"line_number":1542,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_681bec73","line":1539,"updated":"2015-11-11 19:42:13.000000000","message":"Why does this need to be a function?","commit_id":"1732b0e5ba8391da97a68be8c21d4b66c9204d26"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f2fff89b1a3215a0eb082664422b16f20773cfbd","unresolved":false,"context_lines":[{"line_number":1536,"context_line":"    def get_object(self, container, obj, resp_chunk_size\u003dNone,"},{"line_number":1537,"context_line":"                   query_string\u003dNone, response_dict\u003dNone, headers\u003dNone):"},{"line_number":1538,"context_line":"        \"\"\"Wrapper for :func:`get_object`\"\"\""},{"line_number":1539,"context_line":"        def _norange():"},{"line_number":1540,"context_line":"            # We don\u0027t currently support data retry for range based requests"},{"line_number":1541,"context_line":"            return not headers or \u0027Range\u0027 not in headers"},{"line_number":1542,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_3e0c3eec","line":1539,"in_reply_to":"da85f559_681bec73","updated":"2015-11-11 22:22:14.000000000","message":"https://gist.github.com/clayg/2423bb7f1c30089e8b1b","commit_id":"1732b0e5ba8391da97a68be8c21d4b66c9204d26"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2feae94ab544bbd31e8ead957b47820bb834018a","unresolved":false,"context_lines":[{"line_number":199,"context_line":"class _RetryBody(_ObjectBody):"},{"line_number":200,"context_line":"    def __init__(self, resp, expected_length, etag, connection, container, obj,"},{"line_number":201,"context_line":"                 resp_chunk_size\u003dNone, query_string\u003dNone, response_dict\u003dNone,"},{"line_number":202,"context_line":"                 headers\u003d{}):"},{"line_number":203,"context_line":"        super(_RetryBody, self).__init__(resp, resp_chunk_size)"},{"line_number":204,"context_line":"        self.expected_length \u003d expected_length"},{"line_number":205,"context_line":"        self.expected_etag \u003d etag"}],"source_content_type":"text/x-python","patch_set":8,"id":"7a740942_eff62e5c","line":202,"updated":"2015-12-11 16:00:24.000000000","message":"don\u0027t use headers\u003d{}, use something like:\n\n  headers\u003dNone):\n    headers \u003d headers if headers is not None or {}\n\nsee http://docs.python-guide.org/en/latest/writing/gotchas/#mutable-default-arguments","commit_id":"efdc0294d1b7a00ee4ce135214ce12277e4a2886"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2feae94ab544bbd31e8ead957b47820bb834018a","unresolved":false,"context_lines":[{"line_number":218,"context_line":"            buf \u003d self.resp.read(length)"},{"line_number":219,"context_line":"            self.bytes_read +\u003d len(buf)"},{"line_number":220,"context_line":"        except (socket.error, RequestException) as e:"},{"line_number":221,"context_line":"            if self.connect_attempts \u003e self.retries:"},{"line_number":222,"context_line":"                logger.exception(e)"},{"line_number":223,"context_line":"                raise"},{"line_number":224,"context_line":"        if (not buf and self.bytes_read \u003c self.expected_length and"}],"source_content_type":"text/x-python","patch_set":8,"id":"7a740942_2f88b6c4","line":221,"updated":"2015-12-11 16:00:24.000000000","message":"connect_attempts and retries are not defined?? therefore this clause is never executed","commit_id":"efdc0294d1b7a00ee4ce135214ce12277e4a2886"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2feae94ab544bbd31e8ead957b47820bb834018a","unresolved":false,"context_lines":[{"line_number":1020,"context_line":"                              http_status\u003dresp.status,"},{"line_number":1021,"context_line":"                              http_reason\u003dresp.reason,"},{"line_number":1022,"context_line":"                              http_response_content\u003dbody)"},{"line_number":1023,"context_line":"    object_body \u003d _ObjectBody(resp, resp_chunk_size)"},{"line_number":1024,"context_line":"    http_log((\u0027%s%s\u0027 % (url.replace(parsed.path, \u0027\u0027), path), method,),"},{"line_number":1025,"context_line":"             {\u0027headers\u0027: headers}, resp, None)"},{"line_number":1026,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"7a740942_6f0c7bec","line":1023,"updated":"2015-12-11 16:00:24.000000000","message":"Tim already pointed out that this changes the interface contract (although the docstring is non-committal about the return type, existing callers may be expecting a String when chunk-size is not set.\n\nYou could only implement ranged retry when the resp_chunk_size is set.\n\n\u003cbrainstorm\u003e\nOr...you could (a) construct the RetryBody with a new \u0027restarts\u0027 parameter and then (b) return a RetryBody for contents IFF restarts is specified. Its an idea, I am not sure its a great idea, but I was also trying to see how you could implement this such that the benefits are seen when calling the module get_object method, and I think the only piece of the Connection object that RetryBody cares about is the retry counter, hence my idea to decouple from that and use a different \u0027restarts\u0027 counter here.\n\u003c/brainstorm\u003e","commit_id":"efdc0294d1b7a00ee4ce135214ce12277e4a2886"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2feae94ab544bbd31e8ead957b47820bb834018a","unresolved":false,"context_lines":[{"line_number":1559,"context_line":"        \"\"\"Wrapper for :func:`get_object`\"\"\""},{"line_number":1560,"context_line":"        def _norange():"},{"line_number":1561,"context_line":"            # We don\u0027t currently support data retry for range based requests"},{"line_number":1562,"context_line":"            return not headers or \u0027Range\u0027 not in headers"},{"line_number":1563,"context_line":""},{"line_number":1564,"context_line":"        rheaders, body \u003d self._retry(None, get_object, container, obj,"},{"line_number":1565,"context_line":"                                     resp_chunk_size\u003dresp_chunk_size,"}],"source_content_type":"text/x-python","patch_set":8,"id":"7a740942_f44365ad","line":1562,"updated":"2015-12-11 16:00:24.000000000","message":"I don\u0027t think we require the header names to be title-case, so you may need something like:\n\n  or not filter(lambda x: x.lower() \u003d\u003d \u0027range\u0027, headers.keys())","commit_id":"efdc0294d1b7a00ee4ce135214ce12277e4a2886"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"27131ee3abe2430fce3181df0c94e2fd0c4d74d3","unresolved":false,"context_lines":[{"line_number":232,"context_line":"                                          response_dict\u003dself.response_dict,"},{"line_number":233,"context_line":"                                          headers\u003dself.headers)"},{"line_number":234,"context_line":"            self.resp \u003d body"},{"line_number":235,"context_line":"            self.total_attempts +\u003d self.conn.attempts"},{"line_number":236,"context_line":"            buf \u003d self.read(length)"},{"line_number":237,"context_line":"        return buf"},{"line_number":238,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"3a7e1126_f085e658","line":235,"range":{"start_line":235,"start_character":17,"end_line":235,"end_character":31},"updated":"2015-12-17 18:14:53.000000000","message":"total_attempts isn\u0027t updated until *after* _retry has exhausted itself waiting for a 2xx response.","commit_id":"5b3ea63a469e930f6f44e44c775e2d54efcb4e74"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"27131ee3abe2430fce3181df0c94e2fd0c4d74d3","unresolved":false,"context_lines":[{"line_number":1446,"context_line":"        retried_auth \u003d False"},{"line_number":1447,"context_line":"        backoff \u003d self.starting_backoff"},{"line_number":1448,"context_line":"        caller_response_dict \u003d kwargs.pop(\u0027response_dict\u0027, None)"},{"line_number":1449,"context_line":"        while self.attempts \u003c\u003d self.retries:"},{"line_number":1450,"context_line":"            self.attempts +\u003d 1"},{"line_number":1451,"context_line":"            try:"},{"line_number":1452,"context_line":"                if not self.url or not self.token:"}],"source_content_type":"text/x-python","patch_set":9,"id":"3a7e1126_4578bec4","line":1449,"range":{"start_line":1449,"start_character":19,"end_line":1449,"end_character":27},"updated":"2015-12-17 18:14:53.000000000","message":"self.attempts has no insight into _RetryBody\u0027s total_attempts here.","commit_id":"5b3ea63a469e930f6f44e44c775e2d54efcb4e74"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f74302154a6087c1658cf9be834f73abef2bfe00","unresolved":false,"context_lines":[{"line_number":1499,"context_line":""},{"line_number":1500,"context_line":"    def head_account(self):"},{"line_number":1501,"context_line":"        \"\"\"Wrapper for :func:`head_account`\"\"\""},{"line_number":1502,"context_line":"        self.attempts \u003d 0"},{"line_number":1503,"context_line":"        return self._retry(None, head_account)"},{"line_number":1504,"context_line":""},{"line_number":1505,"context_line":"    def get_account(self, marker\u003dNone, limit\u003dNone, prefix\u003dNone,"}],"source_content_type":"text/x-python","patch_set":10,"id":"fa69d971_8201633a","line":1502,"range":{"start_line":1502,"start_character":8,"end_line":1502,"end_character":25},"updated":"2016-01-05 20:11:17.000000000","message":"How about instead of setting this manually all over the place, in _retry we do something like:\n\n    self.attempts \u003d kwargs.pop(\u0027attempts\u0027, 0)\n\n...and then in _RetryBody.read we can pass it as\n\n    attempts\u003dself.conn.attempts","commit_id":"44550ecef14c0604797323c2ef197a04dd9b03be"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cd119d5c085645024854b166a77b78eeae4c8cf8","unresolved":false,"context_lines":[{"line_number":196,"context_line":"        return self.next()"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"class _RetryBody(_ObjectBody):"},{"line_number":200,"context_line":"    def __init__(self, resp, expected_length, etag, connection, container, obj,"},{"line_number":201,"context_line":"                 resp_chunk_size\u003dNone, query_string\u003dNone, response_dict\u003dNone,"},{"line_number":202,"context_line":"                 headers\u003dNone):"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_8776eed6","line":199,"updated":"2016-01-07 18:16:54.000000000","message":"nit: a docstring would be nice","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":455,"name":"Stuart McLaren","email":"stuart.mclaren@hpe.com","username":"stuart-mclaren"},"change_message_id":"31295cf55b43722caef09ae525fb382ba042dee7","unresolved":false,"context_lines":[{"line_number":196,"context_line":"        return self.next()"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"class _RetryBody(_ObjectBody):"},{"line_number":200,"context_line":"    def __init__(self, resp, expected_length, etag, connection, container, obj,"},{"line_number":201,"context_line":"                 resp_chunk_size\u003dNone, query_string\u003dNone, response_dict\u003dNone,"},{"line_number":202,"context_line":"                 headers\u003dNone):"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_3d811290","line":199,"in_reply_to":"fa69d971_8776eed6","updated":"2016-01-08 13:42:50.000000000","message":"Sure, makes sense.","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cd119d5c085645024854b166a77b78eeae4c8cf8","unresolved":false,"context_lines":[{"line_number":1451,"context_line":"        retried_auth \u003d False"},{"line_number":1452,"context_line":"        backoff \u003d self.starting_backoff"},{"line_number":1453,"context_line":"        caller_response_dict \u003d kwargs.pop(\u0027response_dict\u0027, None)"},{"line_number":1454,"context_line":"        self.attempts \u003d kwargs.pop(\u0027attempts\u0027, 0)"},{"line_number":1455,"context_line":"        while self.attempts \u003c\u003d self.retries:"},{"line_number":1456,"context_line":"            self.attempts +\u003d 1"},{"line_number":1457,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_a773f2e6","line":1454,"updated":"2016-01-07 18:16:54.000000000","message":"nice!","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cd119d5c085645024854b166a77b78eeae4c8cf8","unresolved":false,"context_lines":[{"line_number":1572,"context_line":"            not headers or \u0027range\u0027 not in (k.lower() for k in headers))"},{"line_number":1573,"context_line":"        retry_is_possible \u003d ("},{"line_number":1574,"context_line":"            is_not_range_request and"},{"line_number":1575,"context_line":"            resp_chunk_size is not None and"},{"line_number":1576,"context_line":"            self.attempts \u003c\u003d self.retries)"},{"line_number":1577,"context_line":"        if retry_is_possible:"},{"line_number":1578,"context_line":"            body \u003d _RetryBody(body, int(rheaders[\u0027content-length\u0027]),"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_d27a6677","line":1575,"updated":"2016-01-07 18:16:54.000000000","message":"the equivalent check in get_object is \u0027not chunk_size\u0027. If chunk size is 0 then get_object will return a string but we\u0027ll construct a _RetryBody with that string and that will blow up when the _RetryBody is read","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":455,"name":"Stuart McLaren","email":"stuart.mclaren@hpe.com","username":"stuart-mclaren"},"change_message_id":"31295cf55b43722caef09ae525fb382ba042dee7","unresolved":false,"context_lines":[{"line_number":1572,"context_line":"            not headers or \u0027range\u0027 not in (k.lower() for k in headers))"},{"line_number":1573,"context_line":"        retry_is_possible \u003d ("},{"line_number":1574,"context_line":"            is_not_range_request and"},{"line_number":1575,"context_line":"            resp_chunk_size is not None and"},{"line_number":1576,"context_line":"            self.attempts \u003c\u003d self.retries)"},{"line_number":1577,"context_line":"        if retry_is_possible:"},{"line_number":1578,"context_line":"            body \u003d _RetryBody(body, int(rheaders[\u0027content-length\u0027]),"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_7d778ad4","line":1575,"in_reply_to":"fa69d971_d27a6677","updated":"2016-01-08 13:42:50.000000000","message":"Well spotted, thanks!","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cd119d5c085645024854b166a77b78eeae4c8cf8","unresolved":false,"context_lines":[{"line_number":1575,"context_line":"            resp_chunk_size is not None and"},{"line_number":1576,"context_line":"            self.attempts \u003c\u003d self.retries)"},{"line_number":1577,"context_line":"        if retry_is_possible:"},{"line_number":1578,"context_line":"            body \u003d _RetryBody(body, int(rheaders[\u0027content-length\u0027]),"},{"line_number":1579,"context_line":"                              rheaders[\u0027etag\u0027],"},{"line_number":1580,"context_line":"                              self, container, obj,"},{"line_number":1581,"context_line":"                              resp_chunk_size\u003dresp_chunk_size,"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_d21ee65e","line":1578,"updated":"2016-01-07 18:16:54.000000000","message":"_RetryObject.__init__ calls _ObjectBody.__init__ which (according to docstring) expects the first param to be a \u0027response\u0027 whereas here you are passing an instance of _ObjectBody.\n\nIt works because _ObjectBody has a read method, but worries me that in future someone may assume that resp in _ObjectBody really is a response.\n\nThis works and seems more consistent:\n\n  body \u003d _RetryBody(body.resp, int(rheaders[\u0027content-length\u0027])\n\nNote that if retry_is_possible is true then chunk_size is not None and therefore get_object will return an _ObjectBody","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":455,"name":"Stuart McLaren","email":"stuart.mclaren@hpe.com","username":"stuart-mclaren"},"change_message_id":"31295cf55b43722caef09ae525fb382ba042dee7","unresolved":false,"context_lines":[{"line_number":1575,"context_line":"            resp_chunk_size is not None and"},{"line_number":1576,"context_line":"            self.attempts \u003c\u003d self.retries)"},{"line_number":1577,"context_line":"        if retry_is_possible:"},{"line_number":1578,"context_line":"            body \u003d _RetryBody(body, int(rheaders[\u0027content-length\u0027]),"},{"line_number":1579,"context_line":"                              rheaders[\u0027etag\u0027],"},{"line_number":1580,"context_line":"                              self, container, obj,"},{"line_number":1581,"context_line":"                              resp_chunk_size\u003dresp_chunk_size,"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_9d727ee2","line":1578,"in_reply_to":"fa69d971_d21ee65e","updated":"2016-01-08 13:42:50.000000000","message":"Good point.","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9f92c8750f55d04bdca724b5eda3db0a7b2067e8","unresolved":false,"context_lines":[{"line_number":213,"context_line":"        :param etag: the object\u0027s etag"},{"line_number":214,"context_line":"        :param connection: Connection class instance"},{"line_number":215,"context_line":"        :param container: the name of the container the object is in"},{"line_number":216,"context_line":"        :param object: the name of object we are downloading"},{"line_number":217,"context_line":"        :param resp_chunk_size: if defined, chunk size of data to read"},{"line_number":218,"context_line":"        :param query_string: if set will be appended with \u0027?\u0027 to generated path"},{"line_number":219,"context_line":"        :param response_dict: an optional dictionary into which to place"}],"source_content_type":"text/x-python","patch_set":12,"id":"fa69d971_bfb964cd","line":216,"updated":"2016-01-08 17:08:08.000000000","message":"s/object/obj/","commit_id":"875328ad264f9cdeffd00ca71f0a23f16887fc7a"}],"tests/functional/test_swiftclient.py":[{"author":{"_account_id":860,"name":"Donagh McCabe","email":"donagh.mccabe@gmail.com","username":"donagh-mccabe"},"change_message_id":"149bea2004e3494d24617977f3ccc6fab4b5ce34","unresolved":false,"context_lines":[{"line_number":249,"context_line":""},{"line_number":250,"context_line":"    def test_download_object(self):"},{"line_number":251,"context_line":"        # Download whole object"},{"line_number":252,"context_line":"        hdrs, body \u003d self.conn.get_object(self.containername, self.objectname)"},{"line_number":253,"context_line":"        self.assertEqual(self.test_data, body)"},{"line_number":254,"context_line":""},{"line_number":255,"context_line":"        # Download in chunks, should return a generator"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba7be1f8_7fffecaa","side":"PARENT","line":252,"updated":"2015-02-27 15:39:32.000000000","message":"Does this break with the new code or is this a drive-by making it \"better\"?","commit_id":"8aff0bda9c35ab96146f4f419803e62710ab5618"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cd119d5c085645024854b166a77b78eeae4c8cf8","unresolved":false,"context_lines":[{"line_number":334,"context_line":"        self.assertEqual(\"should tolerate empty chunks\", body)"},{"line_number":335,"context_line":""},{"line_number":336,"context_line":"    def test_download_object_retry_chunked(self):"},{"line_number":337,"context_line":"        resp_chunk_size \u003d 2"},{"line_number":338,"context_line":"        # We need a handle on the non-retry-wrapped object"},{"line_number":339,"context_line":"        hdrs, _body \u003d self.conn.get_object(self.containername,"},{"line_number":340,"context_line":"                                           self.objectname,"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_d28026fa","line":337,"updated":"2016-01-07 18:16:54.000000000","message":"try changing this to 0 - conn.get_object will raise an Exception :(","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cd119d5c085645024854b166a77b78eeae4c8cf8","unresolved":false,"context_lines":[{"line_number":336,"context_line":"    def test_download_object_retry_chunked(self):"},{"line_number":337,"context_line":"        resp_chunk_size \u003d 2"},{"line_number":338,"context_line":"        # We need a handle on the non-retry-wrapped object"},{"line_number":339,"context_line":"        hdrs, _body \u003d self.conn.get_object(self.containername,"},{"line_number":340,"context_line":"                                           self.objectname,"},{"line_number":341,"context_line":"                                           resp_chunk_size\u003dresp_chunk_size)"},{"line_number":342,"context_line":"        body \u003d swiftclient.client._RetryBody(_body,"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_a7cd325f","line":339,"updated":"2016-01-07 18:16:54.000000000","message":"_body is an instance of _RetryObject","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cd119d5c085645024854b166a77b78eeae4c8cf8","unresolved":false,"context_lines":[{"line_number":339,"context_line":"        hdrs, _body \u003d self.conn.get_object(self.containername,"},{"line_number":340,"context_line":"                                           self.objectname,"},{"line_number":341,"context_line":"                                           resp_chunk_size\u003dresp_chunk_size)"},{"line_number":342,"context_line":"        body \u003d swiftclient.client._RetryBody(_body,"},{"line_number":343,"context_line":"                                             int(hdrs[\u0027content-length\u0027]),"},{"line_number":344,"context_line":"                                             hdrs[\u0027etag\u0027],"},{"line_number":345,"context_line":"                                             self.conn, self.containername,"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_a7f45287","line":342,"updated":"2016-01-07 18:16:54.000000000","message":"...so here you are wrapping an _RetryObject with another _RetryObject, whcih *works*, but maybe not intended :)","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":455,"name":"Stuart McLaren","email":"stuart.mclaren@hpe.com","username":"stuart-mclaren"},"change_message_id":"31295cf55b43722caef09ae525fb382ba042dee7","unresolved":false,"context_lines":[{"line_number":339,"context_line":"        hdrs, _body \u003d self.conn.get_object(self.containername,"},{"line_number":340,"context_line":"                                           self.objectname,"},{"line_number":341,"context_line":"                                           resp_chunk_size\u003dresp_chunk_size)"},{"line_number":342,"context_line":"        body \u003d swiftclient.client._RetryBody(_body,"},{"line_number":343,"context_line":"                                             int(hdrs[\u0027content-length\u0027]),"},{"line_number":344,"context_line":"                                             hdrs[\u0027etag\u0027],"},{"line_number":345,"context_line":"                                             self.conn, self.containername,"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_7d0c6a42","line":342,"in_reply_to":"fa69d971_a7f45287","updated":"2016-01-08 13:42:50.000000000","message":"Maybe I just wanted to be really sure the download worked! ;-)\n\nI think originally I needed to do this, but you\u0027re right -- it\u0027s not needed now.","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cd119d5c085645024854b166a77b78eeae4c8cf8","unresolved":false,"context_lines":[{"line_number":364,"context_line":"                                           self.objectname,"},{"line_number":365,"context_line":"                                           resp_chunk_size\u003dresp_chunk_size)"},{"line_number":366,"context_line":"        self.assertEqual(2, self.conn.attempts)"},{"line_number":367,"context_line":"        body \u003d swiftclient.client._RetryBody(_body,"},{"line_number":368,"context_line":"                                             int(hdrs[\u0027content-length\u0027]),"},{"line_number":369,"context_line":"                                             hdrs[\u0027etag\u0027],"},{"line_number":370,"context_line":"                                             self.conn, self.containername,"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_67ee5ab6","line":367,"updated":"2016-01-07 18:16:54.000000000","message":"as above","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cd119d5c085645024854b166a77b78eeae4c8cf8","unresolved":false,"context_lines":[{"line_number":385,"context_line":"        self.assertEqual(4, self.conn.attempts)"},{"line_number":386,"context_line":""},{"line_number":387,"context_line":"    def test_download_object_non_chunked(self):"},{"line_number":388,"context_line":"        hdrs, body \u003d self.conn._retry(None, swiftclient.client.get_object,"},{"line_number":389,"context_line":"                                      self.containername, self.objectname)"},{"line_number":390,"context_line":"        data \u003d body"},{"line_number":391,"context_line":"        self.assertEqual(self.test_data, data)"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa69d971_72a61a55","line":388,"updated":"2016-01-07 18:16:54.000000000","message":"calling _retry directly here means you bypass the retry_is_possible/construct _RetryObject test\n\nshouldn\u0027t this be calling self.conn.get_object like other tests? or did I miss some subtlety?","commit_id":"1c718ac668cf26787348230c3bf190aab9033a24"}]}
