)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"12e0914295c5ad52a65792ef2a31d20fd04a95bf","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"b6c4df93_8eed918b","updated":"2024-05-02 00:25:27.000000000","message":"I *think* this should fix the py312 failure I saw on https://review.opendev.org/c/openstack/swift/+/917878","commit_id":"a6023202276b0eb128d47a1f0f64b29f45253e65"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"03d25e24839c81610c92209cd3cdfe9b2c026d47","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"7a19b881_efca966a","updated":"2024-05-02 00:28:10.000000000","message":"I want to see those other results before I respin this.","commit_id":"a6023202276b0eb128d47a1f0f64b29f45253e65"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0c089d127055b137a9501b9df8bdc86db7120228","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"8ccaae95_beece9cd","updated":"2024-05-03 16:57:41.000000000","message":"This makes sense, but perhaps we could add a helper that we could re-use in similar situations https://review.opendev.org/c/openstack/swift/+/918106 sq: WIP: use a ClosingMapper","commit_id":"0442c2351063979823e728338c51345fe33cf1bc"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"ad8fa0b39bb1838fa284080e0f53e678c24e4863","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"ffbba3a7_ec2b925d","updated":"2024-05-09 16:50:37.000000000","message":"recheck\n\ncentos-nfv-openvswitch mirror should be better now.","commit_id":"9ec83c44fdcf5bc77baadbe042d91905a6d791bf"}],"swift/proxy/controllers/base.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"03d25e24839c81610c92209cd3cdfe9b2c026d47","unresolved":true,"context_lines":[{"line_number":1707,"context_line":""},{"line_number":1708,"context_line":"        parts_iter \u003d self._iter_parts_from_response()"},{"line_number":1709,"context_line":""},{"line_number":1710,"context_line":"        class ContentAdder(ClosingIterator):"},{"line_number":1711,"context_line":"            def _get_next_item(self):"},{"line_number":1712,"context_line":"                return add_content_type(super()._get_next_item())"},{"line_number":1713,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"be825717_e9268f96","line":1710,"range":{"start_line":1710,"start_character":14,"end_line":1710,"end_character":26},"updated":"2024-05-02 00:28:10.000000000","message":"Er, probably ought to name it `ContentTypeAdder`","commit_id":"a6023202276b0eb128d47a1f0f64b29f45253e65"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d54db269ec94f32458f32a36a1e60b519f505ef2","unresolved":false,"context_lines":[{"line_number":1707,"context_line":""},{"line_number":1708,"context_line":"        parts_iter \u003d self._iter_parts_from_response()"},{"line_number":1709,"context_line":""},{"line_number":1710,"context_line":"        class ContentAdder(ClosingIterator):"},{"line_number":1711,"context_line":"            def _get_next_item(self):"},{"line_number":1712,"context_line":"                return add_content_type(super()._get_next_item())"},{"line_number":1713,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"b4bdc0b7_065e753e","line":1710,"range":{"start_line":1710,"start_character":14,"end_line":1710,"end_character":26},"in_reply_to":"be825717_e9268f96","updated":"2024-05-02 05:03:17.000000000","message":"Done","commit_id":"a6023202276b0eb128d47a1f0f64b29f45253e65"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"03d25e24839c81610c92209cd3cdfe9b2c026d47","unresolved":true,"context_lines":[{"line_number":1709,"context_line":""},{"line_number":1710,"context_line":"        class ContentAdder(ClosingIterator):"},{"line_number":1711,"context_line":"            def _get_next_item(self):"},{"line_number":1712,"context_line":"                return add_content_type(super()._get_next_item())"},{"line_number":1713,"context_line":""},{"line_number":1714,"context_line":"        def add_content_type(response_part):"},{"line_number":1715,"context_line":"            response_part[\"content_type\"] \u003d \\"}],"source_content_type":"text/x-python","patch_set":1,"id":"60c8090d_7b265b08","line":1712,"range":{"start_line":1712,"start_character":40,"end_line":1712,"end_character":48},"updated":"2024-05-02 00:28:10.000000000","message":"Oh, right -- this won\u0027t work on py2.","commit_id":"a6023202276b0eb128d47a1f0f64b29f45253e65"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d54db269ec94f32458f32a36a1e60b519f505ef2","unresolved":false,"context_lines":[{"line_number":1709,"context_line":""},{"line_number":1710,"context_line":"        class ContentAdder(ClosingIterator):"},{"line_number":1711,"context_line":"            def _get_next_item(self):"},{"line_number":1712,"context_line":"                return add_content_type(super()._get_next_item())"},{"line_number":1713,"context_line":""},{"line_number":1714,"context_line":"        def add_content_type(response_part):"},{"line_number":1715,"context_line":"            response_part[\"content_type\"] \u003d \\"}],"source_content_type":"text/x-python","patch_set":1,"id":"2a571f82_4b055a3a","line":1712,"range":{"start_line":1712,"start_character":40,"end_line":1712,"end_character":48},"in_reply_to":"60c8090d_7b265b08","updated":"2024-05-02 05:03:17.000000000","message":"Done","commit_id":"a6023202276b0eb128d47a1f0f64b29f45253e65"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0c089d127055b137a9501b9df8bdc86db7120228","unresolved":true,"context_lines":[{"line_number":1713,"context_line":"            return response_part"},{"line_number":1714,"context_line":""},{"line_number":1715,"context_line":"        return document_iters_to_http_response_body("},{"line_number":1716,"context_line":"            (add_content_type(pi) for pi in parts_iter),"},{"line_number":1717,"context_line":"            boundary, is_multipart, self.logger)"},{"line_number":1718,"context_line":""},{"line_number":1719,"context_line":"    def get_working_response(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"f8c76573_76787b54","side":"PARENT","line":1716,"updated":"2024-05-03 16:57:41.000000000","message":"this was going to prevent closes propagating down the nested iters","commit_id":"b4dddb740639401f8166ee167b4173fc51ed03a0"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"855152d3a1528058c7974d88dd4cdec55f1935ad","unresolved":false,"context_lines":[{"line_number":1713,"context_line":"            return response_part"},{"line_number":1714,"context_line":""},{"line_number":1715,"context_line":"        return document_iters_to_http_response_body("},{"line_number":1716,"context_line":"            (add_content_type(pi) for pi in parts_iter),"},{"line_number":1717,"context_line":"            boundary, is_multipart, self.logger)"},{"line_number":1718,"context_line":""},{"line_number":1719,"context_line":"    def get_working_response(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"6099d9b5_738717ba","side":"PARENT","line":1716,"in_reply_to":"f8c76573_76787b54","updated":"2024-05-07 08:59:45.000000000","message":"Acknowledged","commit_id":"b4dddb740639401f8166ee167b4173fc51ed03a0"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0c089d127055b137a9501b9df8bdc86db7120228","unresolved":true,"context_lines":[{"line_number":1707,"context_line":""},{"line_number":1708,"context_line":"        parts_iter \u003d self._iter_parts_from_response()"},{"line_number":1709,"context_line":""},{"line_number":1710,"context_line":"        class ContentTypeAdder(ClosingIterator):"},{"line_number":1711,"context_line":"            def _get_next_item(self):"},{"line_number":1712,"context_line":"                response_part \u003d super(ContentTypeAdder, self)._get_next_item()"},{"line_number":1713,"context_line":"                headers \u003d HeaderKeyDict(response_part[\"headers\"])"}],"source_content_type":"text/x-python","patch_set":2,"id":"e0796003_5cf638ca","line":1710,"updated":"2024-05-03 16:57:41.000000000","message":"how about adding a re-usable helper class?\n\nhttps://review.opendev.org/c/openstack/swift/+/918106 sq: WIP: use a ClosingMapper","commit_id":"0442c2351063979823e728338c51345fe33cf1bc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"855152d3a1528058c7974d88dd4cdec55f1935ad","unresolved":false,"context_lines":[{"line_number":1707,"context_line":""},{"line_number":1708,"context_line":"        parts_iter \u003d self._iter_parts_from_response()"},{"line_number":1709,"context_line":""},{"line_number":1710,"context_line":"        class ContentTypeAdder(ClosingIterator):"},{"line_number":1711,"context_line":"            def _get_next_item(self):"},{"line_number":1712,"context_line":"                response_part \u003d super(ContentTypeAdder, self)._get_next_item()"},{"line_number":1713,"context_line":"                headers \u003d HeaderKeyDict(response_part[\"headers\"])"}],"source_content_type":"text/x-python","patch_set":2,"id":"3a596bfd_d1ca26ba","line":1710,"in_reply_to":"e0796003_5cf638ca","updated":"2024-05-07 08:59:45.000000000","message":"Done","commit_id":"0442c2351063979823e728338c51345fe33cf1bc"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d54db269ec94f32458f32a36a1e60b519f505ef2","unresolved":true,"context_lines":[{"line_number":9669,"context_line":"        # close"},{"line_number":9670,"context_line":"        chain \u003d utils.CloseableChain([1, 2], [3])"},{"line_number":9671,"context_line":"        chain.close()"},{"line_number":9672,"context_line":"        self.assertEqual([1, 2, 3], [x for x in chain])"},{"line_number":9673,"context_line":""},{"line_number":9674,"context_line":"        # check with generator in the chain"},{"line_number":9675,"context_line":"        generator_closed \u003d [False]"}],"source_content_type":"text/x-python","patch_set":2,"id":"42267810_385b4351","side":"PARENT","line":9672,"updated":"2024-05-02 05:03:17.000000000","message":"It\u0027s not just me, is it? This was an *insane* API we were asserting before, and we *should* fix it.","commit_id":"b4dddb740639401f8166ee167b4173fc51ed03a0"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0c089d127055b137a9501b9df8bdc86db7120228","unresolved":true,"context_lines":[{"line_number":9669,"context_line":"        # close"},{"line_number":9670,"context_line":"        chain \u003d utils.CloseableChain([1, 2], [3])"},{"line_number":9671,"context_line":"        chain.close()"},{"line_number":9672,"context_line":"        self.assertEqual([1, 2, 3], [x for x in chain])"},{"line_number":9673,"context_line":""},{"line_number":9674,"context_line":"        # check with generator in the chain"},{"line_number":9675,"context_line":"        generator_closed \u003d [False]"}],"source_content_type":"text/x-python","patch_set":2,"id":"1acb58cb_d8e10958","side":"PARENT","line":9672,"in_reply_to":"42267810_385b4351","updated":"2024-05-03 16:57:41.000000000","message":"An itertools.chain doesn\u0027t have a close method. But a generator will not yield more items after its close() has been called. So its seems surprising that a CloseableChain which does have a close() method would still yield after close.","commit_id":"b4dddb740639401f8166ee167b4173fc51ed03a0"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"176becb427ffe802ec531e7e30a40a8404e69ca4","unresolved":true,"context_lines":[{"line_number":9679,"context_line":"        wrapped \u003d FakeIterable([(2, 3), (4, 5), (6, 7)])"},{"line_number":9680,"context_line":"        it \u003d utils.ClosingMapper(func, wrapped)"},{"line_number":9681,"context_line":"        self.assertEqual(5, next(it))"},{"line_number":9682,"context_line":"        with self.assertRaises(Exception) as cm:"},{"line_number":9683,"context_line":"            next(it)"},{"line_number":9684,"context_line":"        self.assertIn(\u0027boom\u0027, str(cm.exception))"},{"line_number":9685,"context_line":"        self.assertEqual(1, wrapped.close_call_count)"}],"source_content_type":"text/x-python","patch_set":3,"id":"e0aab515_6fb2ca79","line":9682,"range":{"start_line":9682,"start_character":31,"end_line":9682,"end_character":40},"updated":"2024-05-07 16:05:09.000000000","message":"It\u0027d be much stronger if we raised \u0026 caught some more-specific exception.","commit_id":"1ddb4c795e6b6f669d5715ef6245a285e65a95fc"}],"test/unit/proxy/controllers/test_base.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"03d25e24839c81610c92209cd3cdfe9b2c026d47","unresolved":true,"context_lines":[{"line_number":1724,"context_line":"                resp \u003d handler.get_working_response()"},{"line_number":1725,"context_line":"                resp.app_iter.close()"},{"line_number":1726,"context_line":"        # verify that iter exited"},{"line_number":1727,"context_line":"        self.assertEqual({1: [\u0027next\u0027, \u0027close\u0027, \u0027__del__\u0027]},"},{"line_number":1728,"context_line":"                         factory.captured_calls)"},{"line_number":1729,"context_line":"        self.assertEqual([\"Client disconnected on read of \u0027some-path\u0027\"],"},{"line_number":1730,"context_line":"                         self.logger.get_lines_for_level(\u0027info\u0027))"}],"source_content_type":"text/x-python","patch_set":1,"id":"879e0d88_d5356e0b","line":1727,"updated":"2024-05-02 00:28:10.000000000","message":"The fact that we were asserting on `__del__` but not `close` should have been such a smell...","commit_id":"a6023202276b0eb128d47a1f0f64b29f45253e65"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"855152d3a1528058c7974d88dd4cdec55f1935ad","unresolved":false,"context_lines":[{"line_number":1724,"context_line":"                resp \u003d handler.get_working_response()"},{"line_number":1725,"context_line":"                resp.app_iter.close()"},{"line_number":1726,"context_line":"        # verify that iter exited"},{"line_number":1727,"context_line":"        self.assertEqual({1: [\u0027next\u0027, \u0027close\u0027, \u0027__del__\u0027]},"},{"line_number":1728,"context_line":"                         factory.captured_calls)"},{"line_number":1729,"context_line":"        self.assertEqual([\"Client disconnected on read of \u0027some-path\u0027\"],"},{"line_number":1730,"context_line":"                         self.logger.get_lines_for_level(\u0027info\u0027))"}],"source_content_type":"text/x-python","patch_set":1,"id":"d503e683_06b25eea","line":1727,"in_reply_to":"476c7487_8a0d7827","updated":"2024-05-07 08:59:45.000000000","message":"Acknowledged","commit_id":"a6023202276b0eb128d47a1f0f64b29f45253e65"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0c089d127055b137a9501b9df8bdc86db7120228","unresolved":true,"context_lines":[{"line_number":1724,"context_line":"                resp \u003d handler.get_working_response()"},{"line_number":1725,"context_line":"                resp.app_iter.close()"},{"line_number":1726,"context_line":"        # verify that iter exited"},{"line_number":1727,"context_line":"        self.assertEqual({1: [\u0027next\u0027, \u0027close\u0027, \u0027__del__\u0027]},"},{"line_number":1728,"context_line":"                         factory.captured_calls)"},{"line_number":1729,"context_line":"        self.assertEqual([\"Client disconnected on read of \u0027some-path\u0027\"],"},{"line_number":1730,"context_line":"                         self.logger.get_lines_for_level(\u0027info\u0027))"}],"source_content_type":"text/x-python","patch_set":1,"id":"476c7487_8a0d7827","line":1727,"in_reply_to":"879e0d88_d5356e0b","updated":"2024-05-03 16:57:41.000000000","message":"ok, so we needed to use a ClosingIter  in order to get the \u0027close\u0027, and then we needed to have ClosingIter do some cleanup in order to get the __del__. Makes sense.","commit_id":"a6023202276b0eb128d47a1f0f64b29f45253e65"}]}
