)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"58a909783f6fe0c818a590b348d36f60194d371a","unresolved":false,"context_lines":[{"line_number":15,"context_line":"it is not necessary for the object server to write an async_pending"},{"line_number":16,"context_line":"for that queue row\u0027s deletion."},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"Currently, however, each object server does write such an"},{"line_number":19,"context_line":"async_pending. Given Rc container replicas and Ro object replicas, the"},{"line_number":20,"context_line":"net result is (Ro + 1) * Rc DELETE requests to container servers. With"},{"line_number":21,"context_line":"3 replicas of everything, that\u0027s 12 requests to container servers for"},{"line_number":22,"context_line":"each deleted object. With 10+4 EC, that\u0027s 45 requests."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"7f96bb07_2504104a","line":19,"range":{"start_line":18,"start_character":0,"end_line":19,"end_character":13},"updated":"2018-01-12 18:36:48.000000000","message":"is this still true? since [1] it is just 2 of the obj servers\n\n[1] https://review.openstack.org/#/c/532342/4","commit_id":"0fb23b6ff404eb3169e80799d216c8952cb43488"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8652f54593e48d3f607374496384734119886a7e","unresolved":false,"context_lines":[{"line_number":26,"context_line":"container server requests to Rc (typically 3), all issued directly"},{"line_number":27,"context_line":"from the object expirer."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Change-Id: Icd63c80c73f864d2561e745c3154fbfda02bd0cc"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"7f96bb07_8bdb8beb","line":29,"updated":"2018-01-15 17:04:37.000000000","message":"This totally deserves a\n\n Closes-Bug: 1076202","commit_id":"c68f3cc69359c1ba123e6b37845fbf234043ebb1"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"d30aed9cf2e2c05c5c532096c3dffb9e5a42f9c5","unresolved":false,"context_lines":[{"line_number":26,"context_line":"container server requests to Rc (typically 3), all issued directly"},{"line_number":27,"context_line":"from the object expirer."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Change-Id: Icd63c80c73f864d2561e745c3154fbfda02bd0cc"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"7f96bb07_91773cd5","line":29,"in_reply_to":"7f96bb07_8bdb8beb","updated":"2018-01-16 00:14:30.000000000","message":"Done","commit_id":"c68f3cc69359c1ba123e6b37845fbf234043ebb1"}],"swift/obj/expirer.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9cd154e46e47fe1ef5c5d11537c3d139b4fbcad1","unresolved":false,"context_lines":[{"line_number":305,"context_line":"        self.swift.make_request("},{"line_number":306,"context_line":"            \u0027DELETE\u0027, path,"},{"line_number":307,"context_line":"            {\u0027X-If-Delete-At\u0027: str(timestamp), \u0027X-Timestamp\u0027: str(timestamp),"},{"line_number":308,"context_line":"             \u0027X-Backend-Clean-Expiring-Object-Queue\u0027: \u0027no\u0027},"},{"line_number":309,"context_line":"            (2,))"}],"source_content_type":"text/x-python","patch_set":1,"id":"7f96bb07_6504957c","line":308,"updated":"2018-01-10 22:21:21.000000000","message":"very good then","commit_id":"523fa2a59c8ea4ae5c2afaf22d50fe02cbd65c79"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"58a909783f6fe0c818a590b348d36f60194d371a","unresolved":false,"context_lines":[{"line_number":305,"context_line":"        self.swift.make_request("},{"line_number":306,"context_line":"            \u0027DELETE\u0027, path,"},{"line_number":307,"context_line":"            {\u0027X-If-Delete-At\u0027: str(timestamp), \u0027X-Timestamp\u0027: str(timestamp),"},{"line_number":308,"context_line":"             \u0027X-Backend-Clean-Expiring-Object-Queue\u0027: \u0027no\u0027},"},{"line_number":309,"context_line":"            (2,))"}],"source_content_type":"text/x-python","patch_set":3,"id":"7f96bb07_05031411","line":308,"range":{"start_line":308,"start_character":55,"end_line":308,"end_character":57},"updated":"2018-01-12 18:36:48.000000000","message":"hehe, I think \u0027no thank you\u0027 would work ;)","commit_id":"0fb23b6ff404eb3169e80799d216c8952cb43488"}],"swift/proxy/controllers/obj.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"58a909783f6fe0c818a590b348d36f60194d371a","unresolved":false,"context_lines":[{"line_number":357,"context_line":"        # small."},{"line_number":358,"context_line":"        n_desired_queue_updates \u003d 2"},{"line_number":359,"context_line":"        for i in range(len(headers)):"},{"line_number":360,"context_line":"            headers[i].setdefault(\u0027X-Backend-Clean-Expiring-Object-Queue\u0027,"},{"line_number":361,"context_line":"                                  \u0027t\u0027 if i \u003c n_desired_queue_updates else \u0027f\u0027)"},{"line_number":362,"context_line":""},{"line_number":363,"context_line":"        for i, node in enumerate(delete_at_nodes or []):"}],"source_content_type":"text/x-python","patch_set":3,"id":"7f96bb07_b0286086","line":360,"range":{"start_line":360,"start_character":23,"end_line":360,"end_character":33},"updated":"2018-01-12 18:36:48.000000000","message":"ok, so if expirer has already set to false then that\u0027s the way it stays for all replicas","commit_id":"0fb23b6ff404eb3169e80799d216c8952cb43488"}],"test/probe/test_object_expirer.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9cd154e46e47fe1ef5c5d11537c3d139b4fbcad1","unresolved":false,"context_lines":[{"line_number":163,"context_line":"                        async_pendings.extend(["},{"line_number":164,"context_line":"                            os.path.join(ap_dir_fullpath, ent)"},{"line_number":165,"context_line":"                            for ent in os.listdir(ap_dir_fullpath)])"},{"line_number":166,"context_line":"            return async_pendings"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"        # Make an expiring object"},{"line_number":169,"context_line":"        obj_brain \u003d BrainSplitter(self.url, self.token, self.container_name,"}],"source_content_type":"text/x-python","patch_set":1,"id":"7f96bb07_05f9117f","line":166,"updated":"2018-01-10 22:21:21.000000000","message":"I can already tell I love this test...","commit_id":"523fa2a59c8ea4ae5c2afaf22d50fe02cbd65c79"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"487eab78488d68a2d1f9eea37cd10de19db1112e","unresolved":false,"context_lines":[{"line_number":186,"context_line":"        # expire the object"},{"line_number":187,"context_line":"        Manager([\u0027object-expirer\u0027]).once()"},{"line_number":188,"context_line":"        pendings_after \u003d gather_async_pendings(onodes)"},{"line_number":189,"context_line":"        self.assertEqual(pendings_after, pendings_before)"},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"    def test_expirer_object_should_not_be_expired(self):"},{"line_number":192,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"7f96bb07_3c8f6d2b","line":189,"updated":"2018-01-11 20:49:11.000000000","message":"integration test","commit_id":"0fb23b6ff404eb3169e80799d216c8952cb43488"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"56d491903cb3a8b93d245c5027cf37c42434b0cf","unresolved":false,"context_lines":[{"line_number":147,"context_line":"            async_pendings \u003d []"},{"line_number":148,"context_line":"            for onode in onodes:"},{"line_number":149,"context_line":"                async_pending_dir \u003d os.path.join("},{"line_number":150,"context_line":"                    self.device_dir(\u0027\u0027, onode), \u0027async_pending\u0027)"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"                try:"},{"line_number":153,"context_line":"                    ap_dirs \u003d os.listdir(async_pending_dir)"}],"source_content_type":"text/x-python","patch_set":4,"id":"7f96bb07_8c350849","line":150,"updated":"2018-01-13 01:27:57.000000000","message":"This needs to consider the policy index of the container, or look at all async_pending* directories.\n\nI burned a bit of time backing out the changes under swift/ then getting confused about how it didn\u0027t cause the probe test to fail...\n\n diff --git a/test/probe/test_object_expirer.py b/test/probe/test_object_expirer.py\n index 3362adf..b9fecbc 100644\n --- a/test/probe/test_object_expirer.py\n +++ b/test/probe/test_object_expirer.py\n @@ -19,6 +19,7 @@ import time\n  import uuid\n  import unittest\n \n +from swift.obj.diskfile import get_async_dir\n  from swift.common.internal_client import InternalClient, UnexpectedResponse\n  from swift.common.manager import Manager\n  from swift.common.utils import Timestamp\n @@ -147,7 +148,7 @@ class TestObjectExpirer(ReplProbeTest):\n              async_pendings \u003d []\n              for onode in onodes:\n                  async_pending_dir \u003d os.path.join(\n -                    self.device_dir(\u0027\u0027, onode), \u0027async_pending\u0027)\n +                    self.device_dir(\u0027\u0027, onode), get_async_dir(self.policy))\n \n                  try:\n                      ap_dirs \u003d os.listdir(async_pending_dir)\n\nshould do it.","commit_id":"c68f3cc69359c1ba123e6b37845fbf234043ebb1"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"d30aed9cf2e2c05c5c532096c3dffb9e5a42f9c5","unresolved":false,"context_lines":[{"line_number":147,"context_line":"            async_pendings \u003d []"},{"line_number":148,"context_line":"            for onode in onodes:"},{"line_number":149,"context_line":"                async_pending_dir \u003d os.path.join("},{"line_number":150,"context_line":"                    self.device_dir(\u0027\u0027, onode), \u0027async_pending\u0027)"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"                try:"},{"line_number":153,"context_line":"                    ap_dirs \u003d os.listdir(async_pending_dir)"}],"source_content_type":"text/x-python","patch_set":4,"id":"7f96bb07_658983c8","line":150,"in_reply_to":"7f96bb07_64e517a8","updated":"2018-01-16 00:14:30.000000000","message":"New version has one expiring object per enabled policy and checks all the async pendings.","commit_id":"c68f3cc69359c1ba123e6b37845fbf234043ebb1"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"af9c41dd47101c2bed2206d722ba948624bcd3b7","unresolved":false,"context_lines":[{"line_number":147,"context_line":"            async_pendings \u003d []"},{"line_number":148,"context_line":"            for onode in onodes:"},{"line_number":149,"context_line":"                async_pending_dir \u003d os.path.join("},{"line_number":150,"context_line":"                    self.device_dir(\u0027\u0027, onode), \u0027async_pending\u0027)"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"                try:"},{"line_number":153,"context_line":"                    ap_dirs \u003d os.listdir(async_pending_dir)"}],"source_content_type":"text/x-python","patch_set":4,"id":"7f96bb07_64e517a8","line":150,"in_reply_to":"7f96bb07_8c350849","updated":"2018-01-15 15:36:56.000000000","message":"+1 \n\nI reverted the change to the expirer, forced my probe test to use policy index 1, and saw the test pass :(","commit_id":"c68f3cc69359c1ba123e6b37845fbf234043ebb1"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9f74cc8e1d84cfa26447e2d9bf10c0bf24a88e69","unresolved":false,"context_lines":[{"line_number":188,"context_line":"        # listing so the expirer can find them"},{"line_number":189,"context_line":"        Manager([\u0027container-updater\u0027]).once()"},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"        opart, onodes \u003d self.object_ring.get_nodes("},{"line_number":192,"context_line":"            self.account, self.container_name, self.object_name)"},{"line_number":193,"context_line":"        pendings_before \u003d gather_async_pendings(onodes)"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"        # expire the objects"}],"source_content_type":"text/x-python","patch_set":7,"id":"7f96bb07_f128b597","line":192,"range":{"start_line":191,"start_character":8,"end_line":192,"end_character":64},"updated":"2018-01-17 15:12:46.000000000","message":"only gathers async_pendings on the default policy nodes\n\n - see my follow up patch","commit_id":"1342f5c68a38f02f0d967fd09e2819f1a4bce85e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"39693385b439ac1dbccdf4ee4c2c89b41832b4d6","unresolved":false,"context_lines":[{"line_number":188,"context_line":"        # listing so the expirer can find them"},{"line_number":189,"context_line":"        Manager([\u0027container-updater\u0027]).once()"},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"        opart, onodes \u003d self.object_ring.get_nodes("},{"line_number":192,"context_line":"            self.account, self.container_name, self.object_name)"},{"line_number":193,"context_line":"        pendings_before \u003d gather_async_pendings(onodes)"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"        # expire the objects"}],"source_content_type":"text/x-python","patch_set":7,"id":"7f96bb07_2f20f1ab","line":192,"range":{"start_line":191,"start_character":8,"end_line":192,"end_character":64},"in_reply_to":"7f96bb07_f128b597","updated":"2018-01-17 17:23:16.000000000","message":"How big do we really expect a probe test cluster to be? Should we just grab all nodes, since we\u0027re hitting all policies?","commit_id":"1342f5c68a38f02f0d967fd09e2819f1a4bce85e"}],"test/unit/obj/test_expirer.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9cd154e46e47fe1ef5c5d11537c3d139b4fbcad1","unresolved":false,"context_lines":[{"line_number":800,"context_line":"        header \u003d \u0027X-Backend-Clean-Expiring-Object-Queue\u0027"},{"line_number":801,"context_line":"        self.assertEqual("},{"line_number":802,"context_line":"            x.swift.make_request.call_args[0][2].get(header),"},{"line_number":803,"context_line":"            \u0027no\u0027)"},{"line_number":804,"context_line":""},{"line_number":805,"context_line":"    def test_pop_queue(self):"},{"line_number":806,"context_line":"        class InternalClient(object):"}],"source_content_type":"text/x-python","patch_set":1,"id":"7f96bb07_e5ef45ae","line":803,"updated":"2018-01-10 22:21:21.000000000","message":"yes!","commit_id":"523fa2a59c8ea4ae5c2afaf22d50fe02cbd65c79"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"487eab78488d68a2d1f9eea37cd10de19db1112e","unresolved":false,"context_lines":[{"line_number":800,"context_line":"        header \u003d \u0027X-Backend-Clean-Expiring-Object-Queue\u0027"},{"line_number":801,"context_line":"        self.assertEqual("},{"line_number":802,"context_line":"            x.swift.make_request.call_args[0][2].get(header),"},{"line_number":803,"context_line":"            \u0027no\u0027)"},{"line_number":804,"context_line":""},{"line_number":805,"context_line":"    def test_pop_queue(self):"},{"line_number":806,"context_line":"        class InternalClient(object):"}],"source_content_type":"text/x-python","patch_set":3,"id":"7f96bb07_bc913d55","line":803,"updated":"2018-01-11 20:49:11.000000000","message":"test expirer to internal client","commit_id":"0fb23b6ff404eb3169e80799d216c8952cb43488"}],"test/unit/proxy/controllers/test_obj.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"487eab78488d68a2d1f9eea37cd10de19db1112e","unresolved":false,"context_lines":[{"line_number":505,"context_line":"            True: 0,"},{"line_number":506,"context_line":"            False: o_replicas,"},{"line_number":507,"context_line":"            None: 0,"},{"line_number":508,"context_line":"        })"},{"line_number":509,"context_line":""},{"line_number":510,"context_line":"    def test_DELETE_write_affinity_before_replication(self):"},{"line_number":511,"context_line":"        policy_conf \u003d self.app.get_policy_options(self.policy)"}],"source_content_type":"text/x-python","patch_set":3,"id":"7f96bb07_1c8ab11a","line":508,"updated":"2018-01-11 20:49:11.000000000","message":"test internal client to backend servers","commit_id":"0fb23b6ff404eb3169e80799d216c8952cb43488"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"56d491903cb3a8b93d245c5027cf37c42434b0cf","unresolved":false,"context_lines":[{"line_number":479,"context_line":"            None: 0,"},{"line_number":480,"context_line":"        })"},{"line_number":481,"context_line":""},{"line_number":482,"context_line":"    def test_internal_DELETE_supresses_expirer_queue_updates(self):"},{"line_number":483,"context_line":"        req \u003d swift.common.swob.Request.blank("},{"line_number":484,"context_line":"            \u0027/v1/a/c/o\u0027, method\u003d\u0027DELETE\u0027, headers\u003d{"},{"line_number":485,"context_line":"                \u0027X-Backend-Clean-Expiring-Object-Queue\u0027: \u0027no\u0027})"}],"source_content_type":"text/x-python","patch_set":4,"id":"7f96bb07_cc3790b0","line":482,"range":{"start_line":482,"start_character":13,"end_line":482,"end_character":21},"updated":"2018-01-13 01:27:57.000000000","message":"nit: Better as\n\n test_expirer_DELETE_supresses_expirer_queue_updates\n\nThere are other internal clients, and they wouldn\u0027t necessarily (and probably shouldn\u0027t?) do the suppression.","commit_id":"c68f3cc69359c1ba123e6b37845fbf234043ebb1"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"d30aed9cf2e2c05c5c532096c3dffb9e5a42f9c5","unresolved":false,"context_lines":[{"line_number":479,"context_line":"            None: 0,"},{"line_number":480,"context_line":"        })"},{"line_number":481,"context_line":""},{"line_number":482,"context_line":"    def test_internal_DELETE_supresses_expirer_queue_updates(self):"},{"line_number":483,"context_line":"        req \u003d swift.common.swob.Request.blank("},{"line_number":484,"context_line":"            \u0027/v1/a/c/o\u0027, method\u003d\u0027DELETE\u0027, headers\u003d{"},{"line_number":485,"context_line":"                \u0027X-Backend-Clean-Expiring-Object-Queue\u0027: \u0027no\u0027})"}],"source_content_type":"text/x-python","patch_set":4,"id":"7f96bb07_e8d24a5c","line":482,"range":{"start_line":482,"start_character":13,"end_line":482,"end_character":21},"in_reply_to":"7f96bb07_cc3790b0","updated":"2018-01-16 00:14:30.000000000","message":"Done. I also remembered how to spell \"suppresses\" while I was in there. :)","commit_id":"c68f3cc69359c1ba123e6b37845fbf234043ebb1"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"56d491903cb3a8b93d245c5027cf37c42434b0cf","unresolved":false,"context_lines":[{"line_number":496,"context_line":""},{"line_number":497,"context_line":"        counts \u003d {True: 0, False: 0, None: 0}"},{"line_number":498,"context_line":"        for headers in captured_headers:"},{"line_number":499,"context_line":"            v \u003d headers.get(\u0027X-Backend-Clean-Expiring-Object-Queue\u0027)"},{"line_number":500,"context_line":"            norm_v \u003d None if v is None else utils.config_true_value(v)"},{"line_number":501,"context_line":"            counts[norm_v] +\u003d 1"},{"line_number":502,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"7f96bb07_cc60f0a8","line":499,"updated":"2018-01-13 01:27:57.000000000","message":"Adding something like\n\n diff --git a/test/unit/proxy/controllers/test_obj.py b/test/unit/proxy/controllers/test_obj.py\n index 870b842..ebd8b18 100644\n --- a/test/unit/proxy/controllers/test_obj.py\n +++ b/test/unit/proxy/controllers/test_obj.py\n @@ -496,6 +496,8 @@ class BaseObjectControllerMixin(object):\n \n          counts \u003d {True: 0, False: 0, None: 0}\n          for headers in captured_headers:\n +            for suffix in (\u0027Container\u0027, \u0027Partition\u0027, \u0027Host\u0027, \u0027Device\u0027):\n +                self.assertNotIn(\u0027X-Delete-At-\u0027 + suffix, headers)\n              v \u003d headers.get(\u0027X-Backend-Clean-Expiring-Object-Queue\u0027)\n              norm_v \u003d None if v is None else utils.config_true_value(v)\n              counts[norm_v] +\u003d 1\n\n...might be nice. That gave me more confidence in the probe test results, since I could rule out the object server firing an update while handling the DELETE.\n\nI suppose I could also have checked the call to _backend_requests in DELETE in proxy/controllers/obj.py ... but that was pretty removed from the diff...","commit_id":"c68f3cc69359c1ba123e6b37845fbf234043ebb1"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"d30aed9cf2e2c05c5c532096c3dffb9e5a42f9c5","unresolved":false,"context_lines":[{"line_number":496,"context_line":""},{"line_number":497,"context_line":"        counts \u003d {True: 0, False: 0, None: 0}"},{"line_number":498,"context_line":"        for headers in captured_headers:"},{"line_number":499,"context_line":"            v \u003d headers.get(\u0027X-Backend-Clean-Expiring-Object-Queue\u0027)"},{"line_number":500,"context_line":"            norm_v \u003d None if v is None else utils.config_true_value(v)"},{"line_number":501,"context_line":"            counts[norm_v] +\u003d 1"},{"line_number":502,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"7f96bb07_e82eca41","line":499,"in_reply_to":"7f96bb07_cc60f0a8","updated":"2018-01-16 00:14:30.000000000","message":"Done","commit_id":"c68f3cc69359c1ba123e6b37845fbf234043ebb1"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cb6a0093e1883c7d816d4b0001fa483cb4bd53ed","unresolved":false,"context_lines":[{"line_number":479,"context_line":"            None: 0,"},{"line_number":480,"context_line":"        })"},{"line_number":481,"context_line":""},{"line_number":482,"context_line":"    def test_expirer_DELETE_suppresses_expirer_queue_updates(self):"},{"line_number":483,"context_line":"        req \u003d swift.common.swob.Request.blank("},{"line_number":484,"context_line":"            \u0027/v1/a/c/o\u0027, method\u003d\u0027DELETE\u0027, headers\u003d{"},{"line_number":485,"context_line":"                \u0027X-Backend-Clean-Expiring-Object-Queue\u0027: \u0027no\u0027})"}],"source_content_type":"text/x-python","patch_set":5,"id":"7f96bb07_5be74aad","line":482,"updated":"2018-01-17 14:59:05.000000000","message":"ok, fails if I revert use of setdefault in obj controller","commit_id":"9d6013c9a7297a8b46d9ccea4d66a32839c5033f"}]}
