)]}'
{"swift/common/internal_client.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"170f84719cea4acbd707786aac584a1418272d20","unresolved":false,"context_lines":[{"line_number":880,"context_line":""},{"line_number":881,"context_line":"    def retry_request(self, method, **kwargs):"},{"line_number":882,"context_line":"        retries \u003d kwargs.pop(\u0027retries\u0027, self.retries)"},{"line_number":883,"context_line":"        acceptable_statuses \u003d kwargs.pop(\u0027acceptable_statuses\u0027, ())"},{"line_number":884,"context_line":"        self.attempts \u003d 0"},{"line_number":885,"context_line":"        backoff \u003d self.starting_backoff"},{"line_number":886,"context_line":"        while self.attempts \u003c\u003d retries:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_38414a0b","line":883,"updated":"2019-10-29 16:14:42.000000000","message":"I think this would read better if named something like \"do_not_retry_statuses\"","commit_id":"f88b980d552895b954962214dc1ff996be4f6f86"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a93c2bf78977675e28f7cb8b95f28b89bed8151a","unresolved":false,"context_lines":[{"line_number":880,"context_line":""},{"line_number":881,"context_line":"    def retry_request(self, method, **kwargs):"},{"line_number":882,"context_line":"        retries \u003d kwargs.pop(\u0027retries\u0027, self.retries)"},{"line_number":883,"context_line":"        acceptable_statuses \u003d kwargs.pop(\u0027acceptable_statuses\u0027, ())"},{"line_number":884,"context_line":"        self.attempts \u003d 0"},{"line_number":885,"context_line":"        backoff \u003d self.starting_backoff"},{"line_number":886,"context_line":"        while self.attempts \u003c\u003d retries:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_932cdf99","line":883,"in_reply_to":"3fa7e38b_38414a0b","updated":"2019-10-29 16:28:05.000000000","message":"I think I\u0027d be OK with the name if we change the behavior... looks like the HTTPError would have all the headers we\u0027d need to fulfill the base_request contract.","commit_id":"f88b980d552895b954962214dc1ff996be4f6f86"},{"author":{"_account_id":27887,"name":"Gilles Biannic","email":"gilles.biannic@corp.ovh.com","username":"gillesbiannic"},"change_message_id":"284aa1def7ce033483e12aa4cff5f80632732602","unresolved":false,"context_lines":[{"line_number":880,"context_line":""},{"line_number":881,"context_line":"    def retry_request(self, method, **kwargs):"},{"line_number":882,"context_line":"        retries \u003d kwargs.pop(\u0027retries\u0027, self.retries)"},{"line_number":883,"context_line":"        acceptable_statuses \u003d kwargs.pop(\u0027acceptable_statuses\u0027, ())"},{"line_number":884,"context_line":"        self.attempts \u003d 0"},{"line_number":885,"context_line":"        backoff \u003d self.starting_backoff"},{"line_number":886,"context_line":"        while self.attempts \u003c\u003d retries:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_48bf7460","line":883,"in_reply_to":"3fa7e38b_932cdf99","updated":"2019-10-31 16:20:48.000000000","message":"I prefer to keep \"acceptable_statuses\" and stop raising exception","commit_id":"f88b980d552895b954962214dc1ff996be4f6f86"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a93c2bf78977675e28f7cb8b95f28b89bed8151a","unresolved":false,"context_lines":[{"line_number":892,"context_line":"                if isinstance(err, urllib2.HTTPError) and \\"},{"line_number":893,"context_line":"                        err.getcode() in acceptable_statuses:"},{"line_number":894,"context_line":"                    raise ClientException(\u0027Raise acceptable status\u0027,"},{"line_number":895,"context_line":"                                          http_status\u003derr.getcode())"},{"line_number":896,"context_line":"                elif self.attempts \u003e retries:"},{"line_number":897,"context_line":"                    if isinstance(err, urllib2.HTTPError):"},{"line_number":898,"context_line":"                        raise ClientException(\u0027Raise too many retries\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_389f0a03","line":895,"updated":"2019-10-29 16:28:05.000000000","message":"It feels a little funny that we call the statuses \"acceptable\" but then we still raise an error... what do you think about doing something like\n\n return [err.info(), None]\n\n? It\u0027s not great that the message object from info() doesn\u0027t include the status, though; I could see callers wanting to differentiate between success and allowable failure... maybe we could add that?","commit_id":"f88b980d552895b954962214dc1ff996be4f6f86"},{"author":{"_account_id":27887,"name":"Gilles Biannic","email":"gilles.biannic@corp.ovh.com","username":"gillesbiannic"},"change_message_id":"284aa1def7ce033483e12aa4cff5f80632732602","unresolved":false,"context_lines":[{"line_number":892,"context_line":"                if isinstance(err, urllib2.HTTPError) and \\"},{"line_number":893,"context_line":"                        err.getcode() in acceptable_statuses:"},{"line_number":894,"context_line":"                    raise ClientException(\u0027Raise acceptable status\u0027,"},{"line_number":895,"context_line":"                                          http_status\u003derr.getcode())"},{"line_number":896,"context_line":"                elif self.attempts \u003e retries:"},{"line_number":897,"context_line":"                    if isinstance(err, urllib2.HTTPError):"},{"line_number":898,"context_line":"                        raise ClientException(\u0027Raise too many retries\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_b9a3e09d","line":895,"in_reply_to":"3fa7e38b_389f0a03","updated":"2019-10-31 16:20:48.000000000","message":"IMHO, the return is preferable.\nI\u0027m not sure to understand why we want the status since we consider the request successful with a 404 or 409","commit_id":"f88b980d552895b954962214dc1ff996be4f6f86"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"170f84719cea4acbd707786aac584a1418272d20","unresolved":false,"context_lines":[{"line_number":893,"context_line":"                        err.getcode() in acceptable_statuses:"},{"line_number":894,"context_line":"                    raise ClientException(\u0027Raise acceptable status\u0027,"},{"line_number":895,"context_line":"                                          http_status\u003derr.getcode())"},{"line_number":896,"context_line":"                elif self.attempts \u003e retries:"},{"line_number":897,"context_line":"                    if isinstance(err, urllib2.HTTPError):"},{"line_number":898,"context_line":"                        raise ClientException(\u0027Raise too many retries\u0027,"},{"line_number":899,"context_line":"                                              http_status\u003derr.getcode())"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_18b32e9c","line":896,"updated":"2019-10-29 16:14:42.000000000","message":"The multiple isinstance checks under an exception block had a smell to me, but struggled to make any substantial improvement.  This seems about the same to me:\n\n\tdiff --git a/swift/common/internal_client.py b/swift/common/internal_client.py\n\tindex 2cced2988..b39698c2a 100644\n\t--- a/swift/common/internal_client.py\n\t+++ b/swift/common/internal_client.py\n\t@@ -880,25 +880,24 @@ class SimpleClient(object):\n\t \n\t     def retry_request(self, method, **kwargs):\n\t\t retries \u003d kwargs.pop(\u0027retries\u0027, self.retries)\n\t-        acceptable_statuses \u003d kwargs.pop(\u0027acceptable_statuses\u0027, ())\n\t+        do_not_retry_statuses \u003d kwargs.pop(\u0027do_not_retry_statuses\u0027, ())\n\t\t self.attempts \u003d 0\n\t\t backoff \u003d self.starting_backoff\n\t\t while self.attempts \u003c\u003d retries:\n\t\t     self.attempts +\u003d 1\n\t\t     try:\n\t\t\t return self.base_request(method, **kwargs)\n\t+            except urllib2.HTTPError as err:\n\t+                if self.attempts \u003e retries:\n\t+                    raise ClientException(\u0027Raise too many retries\u0027,\n\t+                                          http_status\u003derr.getcode())\n\t+                elif err.getcode() in do_not_retry_statuses:\n\t+                    raise ClientException(\u0027Do not retry\u0027,\n\t+                                          http_status\u003derr.getcode())\n\t\t     except (socket.error, httplib.HTTPException, urllib2.URLError) \\\n\t\t\t     as err:\n\t-                if isinstance(err, urllib2.HTTPError) and \\\n\t-                        err.getcode() in acceptable_statuses:\n\t-                    raise ClientException(\u0027Raise acceptable status\u0027,\n\t-                                          http_status\u003derr.getcode())\n\t-                elif self.attempts \u003e retries:\n\t-                    if isinstance(err, urllib2.HTTPError):\n\t-                        raise ClientException(\u0027Raise too many retries\u0027,\n\t-                                              http_status\u003derr.getcode())\n\t-                    else:\n\t-                        raise\n\t+                if self.attempts \u003e retries:\n\t+                    raise\n\t\t     sleep(backoff)\n\t\t     backoff \u003d min(backoff * 2, self.max_backoff)\n\t \n\n\n\nwhat do you think?","commit_id":"f88b980d552895b954962214dc1ff996be4f6f86"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4d6d3a9591a8ac9ce2f093fbc70a5cacbffd6081","unresolved":false,"context_lines":[{"line_number":891,"context_line":"                if self.attempts \u003e retries:"},{"line_number":892,"context_line":"                    raise ClientException(\u0027Raise too many retries\u0027,"},{"line_number":893,"context_line":"                                          http_status\u003derr.getcode())"},{"line_number":894,"context_line":"                elif err.getcode() in acceptable_statuses:"},{"line_number":895,"context_line":"                    return [err.info(), None]"},{"line_number":896,"context_line":"            except (socket.error, httplib.HTTPException, urllib2.URLError) \\"},{"line_number":897,"context_line":"                    as err:"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_44496e64","line":894,"updated":"2019-11-05 14:23:39.000000000","message":"I\u0027d swap the order of these checks -- otherwise, retries\u003d0 means we ignore acceptable_statuses.","commit_id":"a9ca1cf413a3568aef5b27f886f2a180766f888a"},{"author":{"_account_id":27887,"name":"Gilles Biannic","email":"gilles.biannic@corp.ovh.com","username":"gillesbiannic"},"change_message_id":"2ec9719ed45e9f3419fa227aff9c46f9e1b475ba","unresolved":false,"context_lines":[{"line_number":891,"context_line":"                if self.attempts \u003e retries:"},{"line_number":892,"context_line":"                    raise ClientException(\u0027Raise too many retries\u0027,"},{"line_number":893,"context_line":"                                          http_status\u003derr.getcode())"},{"line_number":894,"context_line":"                elif err.getcode() in acceptable_statuses:"},{"line_number":895,"context_line":"                    return [err.info(), None]"},{"line_number":896,"context_line":"            except (socket.error, httplib.HTTPException, urllib2.URLError) \\"},{"line_number":897,"context_line":"                    as err:"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_390c8938","line":894,"in_reply_to":"3fa7e38b_44496e64","updated":"2019-11-06 17:32:28.000000000","message":"Done","commit_id":"a9ca1cf413a3568aef5b27f886f2a180766f888a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"410cb2bef4d6b154fc385ef5005f36df31fc3821","unresolved":false,"context_lines":[{"line_number":887,"context_line":""},{"line_number":888,"context_line":"    def retry_request(self, method, **kwargs):"},{"line_number":889,"context_line":"        retries \u003d kwargs.pop(\u0027retries\u0027, self.retries)"},{"line_number":890,"context_line":"        acceptable_statuses \u003d kwargs.pop(\u0027acceptable_statuses\u0027, ())"},{"line_number":891,"context_line":"        self.attempts \u003d 0"},{"line_number":892,"context_line":"        backoff \u003d self.starting_backoff"},{"line_number":893,"context_line":"        while self.attempts \u003c\u003d retries:"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_8c8452d5","line":890,"range":{"start_line":890,"start_character":42,"end_line":890,"end_character":61},"updated":"2019-11-07 12:39:27.000000000","message":"OK, so I think Clay\u0027s sold me on the wisdom of *not* having two things called \"acceptable_statuses\" that do *almost* but *not quite* the same thing in the same module for very different clients. That implicit 2xx is a bit of a foot-gun!\n\nMaybe we could call this \"allowable_failures\" or something? Or we just say something like\n\n if not is_server_error(err.getcode()):\n     raise\n elif self.attempts \u003e retries:\n     raise ClientException(...)\n # else, fall through and retry\n\nand keep the exception handling in container_sync.","commit_id":"a94a798c1dd279822bcd57227749d7d3ffb81f83"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8bb6cc6f1a37112e542e23f2cef3c61bb244a094","unresolved":false,"context_lines":[{"line_number":931,"context_line":"            try:"},{"line_number":932,"context_line":"                return self.base_request(method, **kwargs)"},{"line_number":933,"context_line":"            except urllib2.HTTPError as err:"},{"line_number":934,"context_line":"                if is_client_error(err.getcode() or 500):"},{"line_number":935,"context_line":"                    raise ClientException(\u0027Client error\u0027,"},{"line_number":936,"context_line":"                                          http_status\u003derr.getcode())"},{"line_number":937,"context_line":"                elif self.attempts \u003e retries:"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_6bfc5940","line":934,"updated":"2020-01-31 21:09:37.000000000","message":"not obvious to me when getcode returns 0 or None and I couldn\u0027t find any relevant documentation to link","commit_id":"f68e22d43a1bfbbdf182b1cc6819bdc83d166d5d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8bb6cc6f1a37112e542e23f2cef3c61bb244a094","unresolved":false,"context_lines":[{"line_number":933,"context_line":"            except urllib2.HTTPError as err:"},{"line_number":934,"context_line":"                if is_client_error(err.getcode() or 500):"},{"line_number":935,"context_line":"                    raise ClientException(\u0027Client error\u0027,"},{"line_number":936,"context_line":"                                          http_status\u003derr.getcode())"},{"line_number":937,"context_line":"                elif self.attempts \u003e retries:"},{"line_number":938,"context_line":"                    raise ClientException(\u0027Raise too many retries\u0027,"},{"line_number":939,"context_line":"                                          http_status\u003derr.getcode())"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_2bdd01de","line":936,"updated":"2020-01-31 21:09:37.000000000","message":"This seems like a solid improvement - for valid http client error respones there\u0027s no great reason to try and retry the request at this level - if the application wants to \"allow\" 404 or keep trying until they get a 2XX this interface easily supports that in a consistent and expected and efficient way","commit_id":"f68e22d43a1bfbbdf182b1cc6819bdc83d166d5d"}],"swift/container/sync.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a93c2bf78977675e28f7cb8b95f28b89bed8151a","unresolved":false,"context_lines":[{"line_number":562,"context_line":"                                                       HTTP_CONFLICT),"},{"line_number":563,"context_line":"                                  timeout\u003dself.conn_timeout)"},{"line_number":564,"context_line":"                except ClientException as err:"},{"line_number":565,"context_line":"                    if err.http_status !\u003d HTTP_NOT_FOUND:"},{"line_number":566,"context_line":"                        raise"},{"line_number":567,"context_line":"                self.container_deletes +\u003d 1"},{"line_number":568,"context_line":"                self.container_stats[\u0027deletes\u0027] +\u003d 1"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_38eaaa73","line":565,"updated":"2019-10-29 16:28:05.000000000","message":"We might want to make this more like\n\n if err.http_status not in (HTTP_NOT_FOUND, HTTP_CONFLICT):","commit_id":"f88b980d552895b954962214dc1ff996be4f6f86"},{"author":{"_account_id":27887,"name":"Gilles Biannic","email":"gilles.biannic@corp.ovh.com","username":"gillesbiannic"},"change_message_id":"284aa1def7ce033483e12aa4cff5f80632732602","unresolved":false,"context_lines":[{"line_number":562,"context_line":"                                                       HTTP_CONFLICT),"},{"line_number":563,"context_line":"                                  timeout\u003dself.conn_timeout)"},{"line_number":564,"context_line":"                except ClientException as err:"},{"line_number":565,"context_line":"                    if err.http_status !\u003d HTTP_NOT_FOUND:"},{"line_number":566,"context_line":"                        raise"},{"line_number":567,"context_line":"                self.container_deletes +\u003d 1"},{"line_number":568,"context_line":"                self.container_stats[\u0027deletes\u0027] +\u003d 1"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_2614af4c","line":565,"in_reply_to":"3fa7e38b_38eaaa73","updated":"2019-10-31 16:20:48.000000000","message":"Yep, the HTTP_CONFLICT was missing here.\nHowever, no need to filter the error anymore (since we stop raising an error but just returning [err.info(), None] in internal_client.py)","commit_id":"f88b980d552895b954962214dc1ff996be4f6f86"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4d6d3a9591a8ac9ce2f093fbc70a5cacbffd6081","unresolved":false,"context_lines":[{"line_number":562,"context_line":"                                                       HTTP_CONFLICT),"},{"line_number":563,"context_line":"                                  timeout\u003dself.conn_timeout)"},{"line_number":564,"context_line":"                except ClientException as err:"},{"line_number":565,"context_line":"                    raise"},{"line_number":566,"context_line":"                self.container_deletes +\u003d 1"},{"line_number":567,"context_line":"                self.container_stats[\u0027deletes\u0027] +\u003d 1"},{"line_number":568,"context_line":"                self.logger.increment(\u0027deletes\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_4472ceb2","line":565,"updated":"2019-11-05 14:23:39.000000000","message":"Assuming we keep the acceptable_statuses interface -- we don\u0027t need the try/except at all anymore.","commit_id":"a9ca1cf413a3568aef5b27f886f2a180766f888a"},{"author":{"_account_id":27887,"name":"Gilles Biannic","email":"gilles.biannic@corp.ovh.com","username":"gillesbiannic"},"change_message_id":"2ec9719ed45e9f3419fa227aff9c46f9e1b475ba","unresolved":false,"context_lines":[{"line_number":562,"context_line":"                                                       HTTP_CONFLICT),"},{"line_number":563,"context_line":"                                  timeout\u003dself.conn_timeout)"},{"line_number":564,"context_line":"                except ClientException as err:"},{"line_number":565,"context_line":"                    raise"},{"line_number":566,"context_line":"                self.container_deletes +\u003d 1"},{"line_number":567,"context_line":"                self.container_stats[\u0027deletes\u0027] +\u003d 1"},{"line_number":568,"context_line":"                self.logger.increment(\u0027deletes\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_d69ae26d","line":565,"in_reply_to":"3fa7e38b_4472ceb2","updated":"2019-11-06 17:32:28.000000000","message":"Done","commit_id":"a9ca1cf413a3568aef5b27f886f2a180766f888a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8bb6cc6f1a37112e542e23f2cef3c61bb244a094","unresolved":false,"context_lines":[{"line_number":562,"context_line":"                                  timeout\u003dself.conn_timeout)"},{"line_number":563,"context_line":"                except ClientException as err:"},{"line_number":564,"context_line":"                    if err.http_status not in ("},{"line_number":565,"context_line":"                            HTTP_NOT_FOUND, HTTP_CONFLICT):"},{"line_number":566,"context_line":"                        raise"},{"line_number":567,"context_line":"                self.container_deletes +\u003d 1"},{"line_number":568,"context_line":"                self.container_stats[\u0027deletes\u0027] +\u003d 1"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_abc9f124","line":565,"updated":"2020-01-31 21:09:37.000000000","message":"this is a very obvious change, we\u0027re just extending the error codes we were already testing - no change in the simpleclient api, and we don\u0027t have to think about retry logic","commit_id":"f68e22d43a1bfbbdf182b1cc6819bdc83d166d5d"}],"test/unit/common/test_internal_client.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4d6d3a9591a8ac9ce2f093fbc70a5cacbffd6081","unresolved":false,"context_lines":[{"line_number":1618,"context_line":""},{"line_number":1619,"context_line":"        with mock.patch(\u0027swift.common.internal_client.sleep\u0027) \\"},{"line_number":1620,"context_line":"                as mock_sleep:"},{"line_number":1621,"context_line":"            self.assertRaises(exceptions.ClientException,"},{"line_number":1622,"context_line":"                              internal_client.delete_object,"},{"line_number":1623,"context_line":"                              \u0027http://127.0.0.1\u0027,"},{"line_number":1624,"context_line":"                              container\u003d\u0027con\u0027, name\u003d\u0027obj\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_be50702d","line":1621,"range":{"start_line":1621,"start_character":17,"end_line":1621,"end_character":29},"updated":"2019-11-05 14:23:39.000000000","message":"This doesn\u0027t raise any more...","commit_id":"a9ca1cf413a3568aef5b27f886f2a180766f888a"},{"author":{"_account_id":27887,"name":"Gilles Biannic","email":"gilles.biannic@corp.ovh.com","username":"gillesbiannic"},"change_message_id":"2ec9719ed45e9f3419fa227aff9c46f9e1b475ba","unresolved":false,"context_lines":[{"line_number":1618,"context_line":""},{"line_number":1619,"context_line":"        with mock.patch(\u0027swift.common.internal_client.sleep\u0027) \\"},{"line_number":1620,"context_line":"                as mock_sleep:"},{"line_number":1621,"context_line":"            self.assertRaises(exceptions.ClientException,"},{"line_number":1622,"context_line":"                              internal_client.delete_object,"},{"line_number":1623,"context_line":"                              \u0027http://127.0.0.1\u0027,"},{"line_number":1624,"context_line":"                              container\u003d\u0027con\u0027, name\u003d\u0027obj\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_398249a7","line":1621,"range":{"start_line":1621,"start_character":17,"end_line":1621,"end_character":29},"in_reply_to":"3fa7e38b_be50702d","updated":"2019-11-06 17:32:28.000000000","message":"Done","commit_id":"a9ca1cf413a3568aef5b27f886f2a180766f888a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8bb6cc6f1a37112e542e23f2cef3c61bb244a094","unresolved":false,"context_lines":[{"line_number":1613,"context_line":"                                          container\u003d\u0027con\u0027, name\u003d\u0027obj\u0027)"},{"line_number":1614,"context_line":"        self.assertEqual(caught.exception.http_status, 404)"},{"line_number":1615,"context_line":"        self.assertEqual(mock_sleep.call_count, 0)"},{"line_number":1616,"context_line":"        self.assertEqual(mock_urlopen.call_count, 1)"},{"line_number":1617,"context_line":""},{"line_number":1618,"context_line":"    @mock.patch.object(urllib2, \u0027urlopen\u0027)"},{"line_number":1619,"context_line":"    def test_delete_object_with_409_no_retry(self, mock_urlopen):"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_ebbfe976","line":1616,"updated":"2020-01-31 21:09:37.000000000","message":"FAIL: test_delete_object_with_404_no_retry (test.unit.common.test_internal_client.TestSimpleClient)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n  File \"/usr/local/lib/python2.7/dist-packages/mock/mock.py\", line 1330, in patched\n    return func(*args, **keywargs)\n  File \"/home/vagrant/swift/test/unit/common/test_internal_client.py\", line 1615, in test_delete_object_with_404_no_retry\n    self.assertEqual(mock_sleep.call_count, 0)\nAssertionError: 5 !\u003d 0\n\n\n\nand I can see above we DO test the retry behavior for server side error","commit_id":"f68e22d43a1bfbbdf182b1cc6819bdc83d166d5d"}],"test/unit/container/test_sync.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"170f84719cea4acbd707786aac584a1418272d20","unresolved":false,"context_lines":[{"line_number":821,"context_line":""},{"line_number":822,"context_line":"            def fake_delete_object(path, name\u003dNone, headers\u003dNone, proxy\u003dNone,"},{"line_number":823,"context_line":"                                   acceptable_statuses\u003d(), logger\u003dNone,"},{"line_number":824,"context_line":"                                   timeout\u003dNone):"},{"line_number":825,"context_line":"                self.assertEqual(path, \u0027http://sync/to/path\u0027)"},{"line_number":826,"context_line":"                self.assertEqual(name, \u0027object\u0027)"},{"line_number":827,"context_line":"                if realm:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_386dca02","line":824,"updated":"2019-10-29 16:14:42.000000000","message":"I don\u0027t think this is a sufficient unittest behavioral assertions to maintain this change, what about:\n\n\tdiff --git a/test/unit/common/test_internal_client.py b/test/unit/common/test_internal_client.py\n\tindex dcf3d7547..d0e9b715e 100644\n\t--- a/test/unit/common/test_internal_client.py\n\t+++ b/test/unit/common/test_internal_client.py\n\t@@ -1593,6 +1593,39 @@ class TestSimpleClient(unittest.TestCase):\n\t\t     self.assertEqual(mock_sleep.call_count, 1)\n\t\t     self.assertEqual(mock_urlopen.call_count, 2)\n\t \n\t+    @mock.patch.object(urllib2, \u0027urlopen\u0027)\n\t+    def test_delete_object_with_404_retry(self, mock_urlopen):\n\t+        mock_response \u003d mock.MagicMock()\n\t+        mock_response.read.return_value \u003d b\u0027\u0027\n\t+        err_args \u003d [None, 404, None, None, None]\n\t+        mock_urlopen.side_effect \u003d [urllib2.HTTPError(*err_args)] * 6\n\t+\n\t+        with mock.patch(\u0027swift.common.internal_client.sleep\u0027) \\\n\t+                as mock_sleep:\n\t+            self.assertRaises(exceptions.ClientException,\n\t+                              internal_client.delete_object,\n\t+                              \u0027http://127.0.0.1\u0027,\n\t+                              container\u003d\u0027con\u0027, name\u003d\u0027obj\u0027)\n\t+        self.assertEqual(mock_sleep.call_count, 5)\n\t+        self.assertEqual(mock_urlopen.call_count, 6)\n\t+\n\t+    @mock.patch.object(urllib2, \u0027urlopen\u0027)\n\t+    def test_delete_object_with_404_no_retry(self, mock_urlopen):\n\t+        mock_response \u003d mock.MagicMock()\n\t+        mock_response.read.return_value \u003d b\u0027\u0027\n\t+        err_args \u003d [None, 404, None, None, None]\n\t+        mock_urlopen.side_effect \u003d urllib2.HTTPError(*err_args)\n\t+\n\t+        with mock.patch(\u0027swift.common.internal_client.sleep\u0027) \\\n\t+                as mock_sleep:\n\t+            self.assertRaises(exceptions.ClientException,\n\t+                              internal_client.delete_object,\n\t+                              \u0027http://127.0.0.1\u0027,\n\t+                              container\u003d\u0027con\u0027, name\u003d\u0027obj\u0027,\n\t+                              do_not_retry_statuses\u003d(404,))\n\t+        self.assertEqual(mock_sleep.call_count, 0)\n\t+        self.assertEqual(mock_urlopen.call_count, 1)\n\t+\n\t     def test_proxy(self):\n\t\t # check that proxy arg is passed through to the urllib Request\n\t\t scheme \u003d \u0027http\u0027","commit_id":"f88b980d552895b954962214dc1ff996be4f6f86"},{"author":{"_account_id":27887,"name":"Gilles Biannic","email":"gilles.biannic@corp.ovh.com","username":"gillesbiannic"},"change_message_id":"284aa1def7ce033483e12aa4cff5f80632732602","unresolved":false,"context_lines":[{"line_number":821,"context_line":""},{"line_number":822,"context_line":"            def fake_delete_object(path, name\u003dNone, headers\u003dNone, proxy\u003dNone,"},{"line_number":823,"context_line":"                                   acceptable_statuses\u003d(), logger\u003dNone,"},{"line_number":824,"context_line":"                                   timeout\u003dNone):"},{"line_number":825,"context_line":"                self.assertEqual(path, \u0027http://sync/to/path\u0027)"},{"line_number":826,"context_line":"                self.assertEqual(name, \u0027object\u0027)"},{"line_number":827,"context_line":"                if realm:"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_d12fa5f3","line":824,"in_reply_to":"3fa7e38b_386dca02","updated":"2019-10-31 16:20:48.000000000","message":"Done","commit_id":"f88b980d552895b954962214dc1ff996be4f6f86"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4d6d3a9591a8ac9ce2f093fbc70a5cacbffd6081","unresolved":false,"context_lines":[{"line_number":913,"context_line":"                realm, realm_key))"},{"line_number":914,"context_line":"            self.assertEqual(cs.container_deletes, 2)"},{"line_number":915,"context_line":"            self.assertEqual(len(exc), 2)"},{"line_number":916,"context_line":"            self.assertNotEqual(str(exc[-1]), \u0027test client exception: 404\u0027)"},{"line_number":917,"context_line":"        finally:"},{"line_number":918,"context_line":"            sync.uuid \u003d orig_uuid"},{"line_number":919,"context_line":"            sync.delete_object \u003d orig_delete_object"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_04a136f8","line":916,"updated":"2019-11-05 14:23:39.000000000","message":"This feels like a brittle assertion -- but maybe the lower length assertion is all we really need?","commit_id":"a9ca1cf413a3568aef5b27f886f2a180766f888a"},{"author":{"_account_id":27887,"name":"Gilles Biannic","email":"gilles.biannic@corp.ovh.com","username":"gillesbiannic"},"change_message_id":"2ec9719ed45e9f3419fa227aff9c46f9e1b475ba","unresolved":false,"context_lines":[{"line_number":913,"context_line":"                realm, realm_key))"},{"line_number":914,"context_line":"            self.assertEqual(cs.container_deletes, 2)"},{"line_number":915,"context_line":"            self.assertEqual(len(exc), 2)"},{"line_number":916,"context_line":"            self.assertNotEqual(str(exc[-1]), \u0027test client exception: 404\u0027)"},{"line_number":917,"context_line":"        finally:"},{"line_number":918,"context_line":"            sync.uuid \u003d orig_uuid"},{"line_number":919,"context_line":"            sync.delete_object \u003d orig_delete_object"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_f943513e","line":916,"in_reply_to":"3fa7e38b_04a136f8","updated":"2019-11-06 17:32:28.000000000","message":"Yeah ... I remove it ;)","commit_id":"a9ca1cf413a3568aef5b27f886f2a180766f888a"}]}
