)]}'
{"releasenotes/notes/retry-decorator-7246be8f73d377ed.yaml":[{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ced7a9dbcbd36327f9bea39caf50cbf7f1e85ac6","unresolved":false,"context_lines":[{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Added a retry decorator that can be used to retry on assertion failures"},{"line_number":5,"context_line":"    when testtools throws a MismatchError exception."}],"source_content_type":"text/x-yaml","patch_set":7,"id":"3f79a3b5_5c5e7176","line":5,"range":{"start_line":5,"start_character":28,"end_line":5,"end_character":41},"updated":"2018-08-12 22:43:27.000000000","message":"This is no longer true and needs to be updated to mention \"specified exception(s)\" instead.","commit_id":"f9ac3d25b8713a6a9a4e784439b8f12c828d8b4d"}],"tempest/lib/decorators.py":[{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"549546dc37e01e6f266e8e42cd2ee6189f833699","unresolved":false,"context_lines":[{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    return decorator"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"def retry(tries\u003d3, delay\u003d3):"},{"line_number":154,"context_line":"    \"\"\"Decorator for retrying tests on assertion failure."},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"    :param times: Amount of retries, default 3"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f79a3b5_a78554d1","line":153,"range":{"start_line":153,"start_character":4,"end_line":153,"end_character":9},"updated":"2018-08-10 04:36:18.000000000","message":"Similar functionality can be achieved via: https://github.com/openstack/tempest/blob/837726a9ede64e33d0def018da24e146dd6b5af3/tempest/lib/common/utils/test_utils.py#L89\n\nBut if you want explicit retry logic then this is cleaner","commit_id":"afe684fdc356775f8c1ab4d5a9a646c6e5606372"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"549546dc37e01e6f266e8e42cd2ee6189f833699","unresolved":false,"context_lines":[{"line_number":154,"context_line":"    \"\"\"Decorator for retrying tests on assertion failure."},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"    :param times: Amount of retries, default 3"},{"line_number":157,"context_line":"    :param sleep: Delay in seconds between each retry, default 3"},{"line_number":158,"context_line":"    \"\"\""},{"line_number":159,"context_line":"    def decorator(f):"},{"line_number":160,"context_line":"        @wraps(f)"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f79a3b5_676bbc1d","line":157,"range":{"start_line":157,"start_character":11,"end_line":157,"end_character":16},"updated":"2018-08-10 04:36:18.000000000","message":"This is inconsistent with delay param above","commit_id":"afe684fdc356775f8c1ab4d5a9a646c6e5606372"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"549546dc37e01e6f266e8e42cd2ee6189f833699","unresolved":false,"context_lines":[{"line_number":159,"context_line":"    def decorator(f):"},{"line_number":160,"context_line":"        @wraps(f)"},{"line_number":161,"context_line":"        def decorator_retry(*args, **kwargs):"},{"line_number":162,"context_line":"            _tries, _delay \u003d tries, delay"},{"line_number":163,"context_line":"            while _tries \u003e 1:"},{"line_number":164,"context_line":"                try:"},{"line_number":165,"context_line":"                    return f(*args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f79a3b5_c763b041","line":162,"range":{"start_line":162,"start_character":12,"end_line":162,"end_character":41},"updated":"2018-08-10 04:36:18.000000000","message":"Why not use tries and delay directly?","commit_id":"afe684fdc356775f8c1ab4d5a9a646c6e5606372"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"549546dc37e01e6f266e8e42cd2ee6189f833699","unresolved":false,"context_lines":[{"line_number":163,"context_line":"            while _tries \u003e 1:"},{"line_number":164,"context_line":"                try:"},{"line_number":165,"context_line":"                    return f(*args, **kwargs)"},{"line_number":166,"context_line":"                except testtools.matchers._impl.MismatchError:"},{"line_number":167,"context_line":"                    time.sleep(_delay)"},{"line_number":168,"context_line":"                    _tries -\u003d 1"},{"line_number":169,"context_line":"            return f(*args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f79a3b5_2771440d","line":166,"range":{"start_line":166,"start_character":23,"end_line":166,"end_character":61},"updated":"2018-08-10 04:36:18.000000000","message":"testtools.matchers.MismatchError\n\nIt\u0027s here: https://github.com/testing-cabal/testtools/blob/f865cfefae73e540aedb16ebb19f813cc648f2b6/testtools/matchers/__init__.py#L132","commit_id":"afe684fdc356775f8c1ab4d5a9a646c6e5606372"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"c767f4c26fd7b772d8ecd0af271762b2cb6e0ed2","unresolved":false,"context_lines":[{"line_number":151,"context_line":"    return decorator"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":""},{"line_number":154,"context_line":"def retry(tries\u003d3, delay\u003d3):"},{"line_number":155,"context_line":"    \"\"\"Decorator for retrying tests on assertion failure."},{"line_number":156,"context_line":""},{"line_number":157,"context_line":"    :param tries: Amount of retries, default 3"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_aec66f67","line":154,"updated":"2018-08-12 10:22:08.000000000","message":"There are several possible reasons that we need retry.\nIf this decorator is specific to MismatchError, I believe the decorator name should include something to mention \"mismatch error\". Another way is to pass exception(s) to be caught as an argument.","commit_id":"86aefc5c9b423d648d8a4d4f60f15cd8b8ebe78d"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ced7a9dbcbd36327f9bea39caf50cbf7f1e85ac6","unresolved":false,"context_lines":[{"line_number":151,"context_line":"    return decorator"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":""},{"line_number":154,"context_line":"def retry(catch, tries\u003d3, delay\u003d3):"},{"line_number":155,"context_line":"    \"\"\"Decorator for retrying tests on caught exception(s)."},{"line_number":156,"context_line":""},{"line_number":157,"context_line":"    :param catch: Exception or list of exceptions to catch"}],"source_content_type":"text/x-python","patch_set":7,"id":"3f79a3b5_fc565d5c","line":154,"range":{"start_line":154,"start_character":17,"end_line":154,"end_character":33},"updated":"2018-08-12 22:43:27.000000000","message":"I\u0027m not sure if we should provide default values for this as it is better to be explicit as in here: http://git.openstack.org/cgit/openstack/tempest/tree/tempest/api/compute/servers/test_device_tagging.py#n87","commit_id":"f9ac3d25b8713a6a9a4e784439b8f12c828d8b4d"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ced7a9dbcbd36327f9bea39caf50cbf7f1e85ac6","unresolved":false,"context_lines":[{"line_number":154,"context_line":"def retry(catch, tries\u003d3, delay\u003d3):"},{"line_number":155,"context_line":"    \"\"\"Decorator for retrying tests on caught exception(s)."},{"line_number":156,"context_line":""},{"line_number":157,"context_line":"    :param catch: Exception or list of exceptions to catch"},{"line_number":158,"context_line":"    :param tries: Amount of retries, default 3"},{"line_number":159,"context_line":"    :param delay: Delay in seconds between each retry, default 3"},{"line_number":160,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":7,"id":"3f79a3b5_bc730516","line":157,"range":{"start_line":157,"start_character":31,"end_line":157,"end_character":35},"updated":"2018-08-12 22:43:27.000000000","message":"nit: tuple","commit_id":"f9ac3d25b8713a6a9a4e784439b8f12c828d8b4d"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ced7a9dbcbd36327f9bea39caf50cbf7f1e85ac6","unresolved":false,"context_lines":[{"line_number":158,"context_line":"    :param tries: Amount of retries, default 3"},{"line_number":159,"context_line":"    :param delay: Delay in seconds between each retry, default 3"},{"line_number":160,"context_line":"    \"\"\""},{"line_number":161,"context_line":"    def decorator(f):"},{"line_number":162,"context_line":"        @functools.wraps(f)"},{"line_number":163,"context_line":"        def decorator_retry(*args, **kwargs):"},{"line_number":164,"context_line":"            _tries \u003d tries"}],"source_content_type":"text/x-python","patch_set":7,"id":"3f79a3b5_dc4921b7","line":161,"updated":"2018-08-12 22:43:27.000000000","message":"One other consequence of this decorator is that if you apply it to a test that calls \"self.create_test_server()\" (which can result in server build errors) is that those servers are cleaned up at class level not at test level, so if you keep retrying the test you can run out of resources.\n\nSo I think it is worth putting a note in the doctring or in a comment saying that the test should properly clean up after itself at test level before applying this decorator to avoid the above issue.","commit_id":"f9ac3d25b8713a6a9a4e784439b8f12c828d8b4d"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ced7a9dbcbd36327f9bea39caf50cbf7f1e85ac6","unresolved":false,"context_lines":[{"line_number":167,"context_line":"                    return f(*args, **kwargs)"},{"line_number":168,"context_line":"                except catch as e:"},{"line_number":169,"context_line":"                    _tries -\u003d 1"},{"line_number":170,"context_line":"                    exc_name \u003d type(e).__name__"},{"line_number":171,"context_line":"                    LOG.warning(\u0027Caught exception %s, retrying \u0027"},{"line_number":172,"context_line":"                                \u0027%i more times in %i seconds\u0027,"},{"line_number":173,"context_line":"                                exc_name, _tries, delay)"}],"source_content_type":"text/x-python","patch_set":7,"id":"3f79a3b5_7c632d43","line":170,"range":{"start_line":170,"start_character":31,"end_line":170,"end_character":47},"updated":"2018-08-12 22:43:27.000000000","message":"Can also do: e.__class__.__name__","commit_id":"f9ac3d25b8713a6a9a4e784439b8f12c828d8b4d"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"e535aae9fe632056b5ba0ae643a34d91af2dfc19","unresolved":false,"context_lines":[{"line_number":167,"context_line":"        @functools.wraps(f)"},{"line_number":168,"context_line":"        def decorator_retry(*args, **kwargs):"},{"line_number":169,"context_line":"            _tries \u003d tries"},{"line_number":170,"context_line":"            while _tries \u003e 1:"},{"line_number":171,"context_line":"                try:"},{"line_number":172,"context_line":"                    return f(*args, **kwargs)"},{"line_number":173,"context_line":"                except catch as e:"}],"source_content_type":"text/x-python","patch_set":8,"id":"3f79a3b5_594d1898","line":170,"range":{"start_line":170,"start_character":12,"end_line":170,"end_character":28},"updated":"2018-08-13 12:12:03.000000000","message":"This is confusing. The number of tries and the number of retries are different. We usually assume that \u0027tries\u0027 includes the first try and tires\u003d2 means two tries but this code allows only a single try. Does it make sense?\n\nThere are two options:\n- Rename tries to retries\n- Change this to \u0027while _tries \u003e 0\u0027\n\nAnother way to write the logic is:\n\n  for i in range(tries):\n    try:\n        return f(*args, **kwargs)\n    except catch as e:\n        ....","commit_id":"f4cd5184445a1c8dc57982939cd4509728dde62b"},{"author":{"_account_id":27078,"name":"Manik Bindlish","email":"manikbindlish19@gmail.com","username":"manik"},"change_message_id":"9d81ffb91ca6a7bf99ca13f9cee2bf7b4081d224","unresolved":false,"context_lines":[{"line_number":167,"context_line":"        @functools.wraps(f)"},{"line_number":168,"context_line":"        def decorator_retry(*args, **kwargs):"},{"line_number":169,"context_line":"            _tries \u003d tries"},{"line_number":170,"context_line":"            while _tries \u003e 1:"},{"line_number":171,"context_line":"                try:"},{"line_number":172,"context_line":"                    return f(*args, **kwargs)"},{"line_number":173,"context_line":"                except catch as e:"}],"source_content_type":"text/x-python","patch_set":8,"id":"3f79a3b5_4e695089","line":170,"range":{"start_line":170,"start_character":12,"end_line":170,"end_character":28},"in_reply_to":"3f79a3b5_0ed6f850","updated":"2018-08-18 07:15:19.000000000","message":"Yeah, exactly this seems good.\n \nIt\u0027s better to change (tries -\u003e retry)\n\nAlso:\n:param tries: Amount of retries -\u003e :param retry: No. of retries\nIt seems more convenient","commit_id":"f4cd5184445a1c8dc57982939cd4509728dde62b"},{"author":{"_account_id":16137,"name":"Tobias Urdin","email":"tobias.urdin@binero.com","username":"tobasco"},"change_message_id":"2e06ec9ee7ee1dce4a27365806bf57c2055d3722","unresolved":false,"context_lines":[{"line_number":167,"context_line":"        @functools.wraps(f)"},{"line_number":168,"context_line":"        def decorator_retry(*args, **kwargs):"},{"line_number":169,"context_line":"            _tries \u003d tries"},{"line_number":170,"context_line":"            while _tries \u003e 1:"},{"line_number":171,"context_line":"                try:"},{"line_number":172,"context_line":"                    return f(*args, **kwargs)"},{"line_number":173,"context_line":"                except catch as e:"}],"source_content_type":"text/x-python","patch_set":8,"id":"3f79a3b5_b46791b7","line":170,"range":{"start_line":170,"start_character":12,"end_line":170,"end_character":28},"in_reply_to":"3f79a3b5_594d1898","updated":"2018-08-13 12:28:48.000000000","message":"Yeah it\u0027s kind of confusing but it\u0027s point is to do all retries except for the last one inside that loop, the last try should be outside the try statement (and loop) to make sure if an exception occurs on the last try we should fail on that no matter what.","commit_id":"f4cd5184445a1c8dc57982939cd4509728dde62b"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"c9a1ada0abde453ee9f69485d04b8e22d742be38","unresolved":false,"context_lines":[{"line_number":167,"context_line":"        @functools.wraps(f)"},{"line_number":168,"context_line":"        def decorator_retry(*args, **kwargs):"},{"line_number":169,"context_line":"            _tries \u003d tries"},{"line_number":170,"context_line":"            while _tries \u003e 1:"},{"line_number":171,"context_line":"                try:"},{"line_number":172,"context_line":"                    return f(*args, **kwargs)"},{"line_number":173,"context_line":"                except catch as e:"}],"source_content_type":"text/x-python","patch_set":8,"id":"3f79a3b5_0ed6f850","line":170,"range":{"start_line":170,"start_character":12,"end_line":170,"end_character":28},"in_reply_to":"3f79a3b5_73267319","updated":"2018-08-18 06:53:03.000000000","message":"There are two points which are confusing.\n\nThe one is to call the same logic in two places.\nThe other is the docstring of L.163. The variable name is \"tries\" but the description is \"the number of retries\".\n\nOn the first point, how about the following?\n\n  for i in range(tries, 0, -1):\n    try:\n      return f(*args, **kwargs)\n    except catch as e:\n      # Raise an exception as-is when it is the last try.\n      if i \u003d\u003d 1:\n        raise\n      LOG.warning(...)\n      time.sleep(delay)","commit_id":"f4cd5184445a1c8dc57982939cd4509728dde62b"},{"author":{"_account_id":27078,"name":"Manik Bindlish","email":"manikbindlish19@gmail.com","username":"manik"},"change_message_id":"62f92492cc53a325b8370d3709fae6baa868c83d","unresolved":false,"context_lines":[{"line_number":167,"context_line":"        @functools.wraps(f)"},{"line_number":168,"context_line":"        def decorator_retry(*args, **kwargs):"},{"line_number":169,"context_line":"            _tries \u003d tries"},{"line_number":170,"context_line":"            while _tries \u003e 1:"},{"line_number":171,"context_line":"                try:"},{"line_number":172,"context_line":"                    return f(*args, **kwargs)"},{"line_number":173,"context_line":"                except catch as e:"}],"source_content_type":"text/x-python","patch_set":8,"id":"3f79a3b5_73267319","line":170,"range":{"start_line":170,"start_character":12,"end_line":170,"end_character":28},"in_reply_to":"3f79a3b5_b46791b7","updated":"2018-08-18 05:45:23.000000000","message":"Yes it is confusing.\nHow about adding a condition inside exception for the last try?\nIf it is last try and under exception then failure can be raised","commit_id":"f4cd5184445a1c8dc57982939cd4509728dde62b"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"fc9858dafc50b692b17352f8823a83fa91d82520","unresolved":false,"context_lines":[{"line_number":166,"context_line":"    def decorator(f):"},{"line_number":167,"context_line":"        @functools.wraps(f)"},{"line_number":168,"context_line":"        def decorator_retry(*args, **kwargs):"},{"line_number":169,"context_line":"            for i in range(retry, 0, -1):"},{"line_number":170,"context_line":"                try:"},{"line_number":171,"context_line":"                    return f(*args, **kwargs)"},{"line_number":172,"context_line":"                except catch as e:"}],"source_content_type":"text/x-python","patch_set":9,"id":"3f79a3b5_0699ca6c","line":169,"range":{"start_line":169,"start_character":21,"end_line":169,"end_character":41},"updated":"2018-08-21 15:52:27.000000000","message":"\"retry\" does not include the first try because the first try is a normal try.\nAssume \"retry\" is 4, the max number of retries should be 5 (if all tries fail).\n\nIf you say \":param retry: No. of retries\" at L.163, the code should be: \"range(retry +1, 0, -1)\".\nOr, you need to change L.163 to \"max_tries: number of tries\".","commit_id":"c4d1cb2e8cf69c00a3b3d0e4dd348f8afab460ce"},{"author":{"_account_id":27078,"name":"Manik Bindlish","email":"manikbindlish19@gmail.com","username":"manik"},"change_message_id":"a1be0b7ff36e18de34b2e18c99e628390d8c5f1c","unresolved":false,"context_lines":[{"line_number":166,"context_line":"    def decorator(f):"},{"line_number":167,"context_line":"        @functools.wraps(f)"},{"line_number":168,"context_line":"        def decorator_retry(*args, **kwargs):"},{"line_number":169,"context_line":"            for i in range(retry, 0, -1):"},{"line_number":170,"context_line":"                try:"},{"line_number":171,"context_line":"                    return f(*args, **kwargs)"},{"line_number":172,"context_line":"                except catch as e:"}],"source_content_type":"text/x-python","patch_set":9,"id":"3f79a3b5_6f85f158","line":169,"range":{"start_line":169,"start_character":21,"end_line":169,"end_character":41},"in_reply_to":"3f79a3b5_0699ca6c","updated":"2018-09-14 08:40:05.000000000","message":"Agreed! I think it\u0027s better to change L[163] to \"max_tries: number of tries\" to avoid confusion.","commit_id":"c4d1cb2e8cf69c00a3b3d0e4dd348f8afab460ce"}],"tempest/tests/lib/test_decorators.py":[{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"549546dc37e01e6f266e8e42cd2ee6189f833699","unresolved":false,"context_lines":[{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        t \u003d TestFoo(\u0027test_foo\u0027)"},{"line_number":240,"context_line":"        if expected_to_fail:"},{"line_number":241,"context_line":"            self.assertRaises(testtools.matchers._impl.MismatchError,"},{"line_number":242,"context_line":"                              t.test_foo())"},{"line_number":243,"context_line":"        else:"},{"line_number":244,"context_line":"            t.test_foo()"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f79a3b5_e7682c1e","line":241,"range":{"start_line":241,"start_character":30,"end_line":241,"end_character":68},"updated":"2018-08-10 04:36:18.000000000","message":"Ditto use the one here: https://github.com/testing-cabal/testtools/blob/f865cfefae73e540aedb16ebb19f813cc648f2b6/testtools/matchers/__init__.py#L132","commit_id":"afe684fdc356775f8c1ab4d5a9a646c6e5606372"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"549546dc37e01e6f266e8e42cd2ee6189f833699","unresolved":false,"context_lines":[{"line_number":251,"context_line":"    def test_success(self):"},{"line_number":252,"context_line":"        def func():"},{"line_number":253,"context_line":"            self.assertEqual(True, True)"},{"line_number":254,"context_line":"        self._test_retry(func, expected_to_fail\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f79a3b5_a75eb473","line":254,"updated":"2018-08-10 04:36:18.000000000","message":"We also need a test for validating retry - as in failing the test twice then passing it the 3rd time.","commit_id":"afe684fdc356775f8c1ab4d5a9a646c6e5606372"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ced7a9dbcbd36327f9bea39caf50cbf7f1e85ac6","unresolved":false,"context_lines":[{"line_number":267,"context_line":"                self.assertEqual(True, True)"},{"line_number":268,"context_line":""},{"line_number":269,"context_line":"        func()"},{"line_number":270,"context_line":"        self.assertEqual(self.retries, 2)"},{"line_number":271,"context_line":""},{"line_number":272,"context_line":"    def test_multiple_catchers(self):"},{"line_number":273,"context_line":"        self.retries \u003d 0"}],"source_content_type":"text/x-python","patch_set":7,"id":"3f79a3b5_3c59358d","line":270,"range":{"start_line":270,"start_character":25,"end_line":270,"end_character":40},"updated":"2018-08-12 22:43:27.000000000","message":"2, self.retries\n\nShould be: self.assertEqual(expected, actual)","commit_id":"f9ac3d25b8713a6a9a4e784439b8f12c828d8b4d"},{"author":{"_account_id":23186,"name":"Felipe Monteiro","email":"felipe.carneiro.monteiro@gmail.com","username":"felipe.monteiro"},"change_message_id":"ced7a9dbcbd36327f9bea39caf50cbf7f1e85ac6","unresolved":false,"context_lines":[{"line_number":281,"context_line":"                raise ValueError()"},{"line_number":282,"context_line":""},{"line_number":283,"context_line":"        func()"},{"line_number":284,"context_line":"        self.assertEqual(self.retries, 3)"}],"source_content_type":"text/x-python","patch_set":7,"id":"3f79a3b5_9c68891d","line":284,"range":{"start_line":284,"start_character":25,"end_line":284,"end_character":40},"updated":"2018-08-12 22:43:27.000000000","message":"3, self.retries\n\nShould be: self.assertEqual(expected, actual)","commit_id":"f9ac3d25b8713a6a9a4e784439b8f12c828d8b4d"},{"author":{"_account_id":20378,"name":"Trevor McCasland","email":"TM2086@att.com","username":"twm2016"},"change_message_id":"2f79d8429803e0c62bc1207ffcee47b61f05af60","unresolved":false,"context_lines":[{"line_number":233,"context_line":"class TestRetryDecorator(base.TestCase):"},{"line_number":234,"context_line":"    def _test_retry(self, catch, f, expected_to_fail\u003dFalse):"},{"line_number":235,"context_line":"        class TestFoo(test.BaseTestCase):"},{"line_number":236,"context_line":"            @decorators.retry(catch\u003dcatch, retry\u003d3, delay\u003d0.1)"},{"line_number":237,"context_line":"            def test_foo(self):"},{"line_number":238,"context_line":"                f()"},{"line_number":239,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"3f79a3b5_da95e189","line":236,"range":{"start_line":236,"start_character":52,"end_line":236,"end_character":61},"updated":"2018-09-14 10:13:50.000000000","message":"what do you think about mocking out time to speed up the test execution? just a minor improvement :P I think? you can save 0.1 seconds here.","commit_id":"c4d1cb2e8cf69c00a3b3d0e4dd348f8afab460ce"},{"author":{"_account_id":20378,"name":"Trevor McCasland","email":"TM2086@att.com","username":"twm2016"},"change_message_id":"53da1462550335a1cdb1f27b9d643a57a3a290d1","unresolved":false,"context_lines":[{"line_number":233,"context_line":"class TestRetryDecorator(base.TestCase):"},{"line_number":234,"context_line":"    def _test_retry(self, catch, f, expected_to_fail\u003dFalse):"},{"line_number":235,"context_line":"        class TestFoo(test.BaseTestCase):"},{"line_number":236,"context_line":"            @decorators.retry(catch\u003dcatch, retry\u003d3, delay\u003d0.1)"},{"line_number":237,"context_line":"            def test_foo(self):"},{"line_number":238,"context_line":"                f()"},{"line_number":239,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"3f79a3b5_da48812f","line":236,"range":{"start_line":236,"start_character":52,"end_line":236,"end_character":61},"in_reply_to":"3f79a3b5_da95e189","updated":"2018-09-14 10:15:00.000000000","message":"my mistake, 0.3 here cause retry\u003d3, right?","commit_id":"c4d1cb2e8cf69c00a3b3d0e4dd348f8afab460ce"},{"author":{"_account_id":20378,"name":"Trevor McCasland","email":"TM2086@att.com","username":"twm2016"},"change_message_id":"2f79d8429803e0c62bc1207ffcee47b61f05af60","unresolved":false,"context_lines":[{"line_number":258,"context_line":"    def test_retry(self):"},{"line_number":259,"context_line":"        self.retries \u003d 0"},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"        @decorators.retry(testtools.matchers.MismatchError, retry\u003d3, delay\u003d0.1)"},{"line_number":262,"context_line":"        def func():"},{"line_number":263,"context_line":"            self.retries +\u003d 1"},{"line_number":264,"context_line":"            if self.retries \u003c 2:"}],"source_content_type":"text/x-python","patch_set":9,"id":"3f79a3b5_5ae79147","line":261,"range":{"start_line":261,"start_character":69,"end_line":261,"end_character":78},"updated":"2018-09-14 10:13:50.000000000","message":"what do you think about mocking out time to speed up the test execution? just a minor improvement :P I think? you can save 0.3 seconds here.","commit_id":"c4d1cb2e8cf69c00a3b3d0e4dd348f8afab460ce"},{"author":{"_account_id":20378,"name":"Trevor McCasland","email":"TM2086@att.com","username":"twm2016"},"change_message_id":"2f79d8429803e0c62bc1207ffcee47b61f05af60","unresolved":false,"context_lines":[{"line_number":272,"context_line":"    def test_multiple_catchers(self):"},{"line_number":273,"context_line":"        self.retries \u003d 0"},{"line_number":274,"context_line":""},{"line_number":275,"context_line":"        @decorators.retry((KeyError, ValueError), retry\u003d4, delay\u003d0.1)"},{"line_number":276,"context_line":"        def func():"},{"line_number":277,"context_line":"            self.retries +\u003d 1"},{"line_number":278,"context_line":"            if self.retries \u003d\u003d 1:"}],"source_content_type":"text/x-python","patch_set":9,"id":"3f79a3b5_1af11902","line":275,"range":{"start_line":275,"start_character":59,"end_line":275,"end_character":68},"updated":"2018-09-14 10:13:50.000000000","message":"what do you think about mocking out time to speed up the test execution? just a minor improvement :P I think? you can save 0.3 seconds here.","commit_id":"c4d1cb2e8cf69c00a3b3d0e4dd348f8afab460ce"}]}
