)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f3e3ea3df141dc197a9634fda29fffdb70bafc46","unresolved":false,"context_lines":[{"line_number":22,"context_line":"down."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"This patch eliminates the issue by detecting when no objects are"},{"line_number":25,"context_line":"returned for a shard range. The `_cleave_shard_range` method now"},{"line_number":26,"context_line":"returns 3 possible results:"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"  - CLEAVE_SUCCESS"},{"line_number":29,"context_line":"  - CLEAVE_FAILED"},{"line_number":30,"context_line":"  - CLEAVE_EMPTY"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"They all are pretty self explanitory. When `CLEAVE_EMPTY` is returned"},{"line_number":33,"context_line":"the code will:"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"3fa7e38b_263d8fdc","line":30,"range":{"start_line":25,"start_character":28,"end_line":30,"end_character":16},"updated":"2019-09-26 23:20:05.000000000","message":"At first I wasn\u0027t sure about using some return enum -- I kinda wanted to track the number of rows cleaved an return that, or None on error. But then I realized that we aren\u0027t necessarily moving rows this cycle -- that\u0027s why we write down the sync-points...\n\nI can get behind this.","commit_id":"bb3f5eea8a9b747b62673bcc4fab7e7136f0940f"}],"swift/container/sharder.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"dcc2c581689d36a9a2e12de85fd409a7e19dce20","unresolved":false,"context_lines":[{"line_number":794,"context_line":"        dest_shard_range_iter \u003d dest_shard_range \u003d None"},{"line_number":795,"context_line":"        try:"},{"line_number":796,"context_line":"            for objs, info in self.yield_objects(broker, src_shard_range):"},{"line_number":797,"context_line":"                if not objs:"},{"line_number":798,"context_line":"                    return"},{"line_number":799,"context_line":""},{"line_number":800,"context_line":"                def next_or_none(it):"},{"line_number":801,"context_line":"                    try:"}],"source_content_type":"text/x-python","patch_set":1,"id":"7faddb67_48947144","line":798,"range":{"start_line":797,"start_character":16,"end_line":798,"end_character":26},"updated":"2019-08-17 00:29:27.000000000","message":"Off-topic: we can\u0027t trip this, can we?","commit_id":"33a033be08d1c440fd6ba16c991a10c0cc5911b0"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"c80a2742953d9d0fa9e38ccf9b0f6a491be618f7","unresolved":false,"context_lines":[{"line_number":794,"context_line":"        dest_shard_range_iter \u003d dest_shard_range \u003d None"},{"line_number":795,"context_line":"        try:"},{"line_number":796,"context_line":"            for objs, info in self.yield_objects(broker, src_shard_range):"},{"line_number":797,"context_line":"                if not objs:"},{"line_number":798,"context_line":"                    return"},{"line_number":799,"context_line":""},{"line_number":800,"context_line":"                def next_or_none(it):"},{"line_number":801,"context_line":"                    try:"}],"source_content_type":"text/x-python","patch_set":1,"id":"7faddb67_d7cb1c1b","line":798,"range":{"start_line":797,"start_character":16,"end_line":798,"end_character":26},"in_reply_to":"7faddb67_48947144","updated":"2019-08-19 00:24:27.000000000","message":"I don\u0027t think so. Because it\u0027s at the yield_objects level where we fire and expection on a real not objs (empty shard range).\n\nIt does get a little confusing. The way yield it\u0027s a little \"interesing\" It seems to loop through not including deleted and then with deleted. But it makes it harder to just deal with no objs checks.\n\nMaybe we shouldn\u0027t mix exceptions in layers of method calls as a way to manage logic control.. maybe we should rework it smarter.","commit_id":"33a033be08d1c440fd6ba16c991a10c0cc5911b0"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"dcc2c581689d36a9a2e12de85fd409a7e19dce20","unresolved":false,"context_lines":[{"line_number":1161,"context_line":"                self.logger.info(\"Cleaving \u0027%s\u0027: %r - zero objects found\","},{"line_number":1162,"context_line":"                                 broker.path, shard_range)"},{"line_number":1163,"context_line":"                # We don\u0027t need to replicate this SR because there was"},{"line_number":1164,"context_line":"                # nothing there.. So cleanup and remove the"},{"line_number":1165,"context_line":"                # shard_broker from it\u0027s hand off location"},{"line_number":1166,"context_line":"                self.delete_db(shard_broker)"},{"line_number":1167,"context_line":"                cleaving_context.cursor \u003d shard_range.upper_str"},{"line_number":1168,"context_line":"                cleaving_context.ranges_done +\u003d 1"}],"source_content_type":"text/x-python","patch_set":1,"id":"7faddb67_a884050c","line":1165,"range":{"start_line":1164,"start_character":34,"end_line":1165,"end_character":58},"updated":"2019-08-17 00:29:27.000000000","message":"I appreciate not wanting to have to replicate out 1500 empty shard dbs... but what if the shard_broker happened to already exist, with rows? Is delete_db() safe for that?\n\nWould it be worth lazy-loading shard_broker instead?","commit_id":"33a033be08d1c440fd6ba16c991a10c0cc5911b0"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"c80a2742953d9d0fa9e38ccf9b0f6a491be618f7","unresolved":false,"context_lines":[{"line_number":1161,"context_line":"                self.logger.info(\"Cleaving \u0027%s\u0027: %r - zero objects found\","},{"line_number":1162,"context_line":"                                 broker.path, shard_range)"},{"line_number":1163,"context_line":"                # We don\u0027t need to replicate this SR because there was"},{"line_number":1164,"context_line":"                # nothing there.. So cleanup and remove the"},{"line_number":1165,"context_line":"                # shard_broker from it\u0027s hand off location"},{"line_number":1166,"context_line":"                self.delete_db(shard_broker)"},{"line_number":1167,"context_line":"                cleaving_context.cursor \u003d shard_range.upper_str"},{"line_number":1168,"context_line":"                cleaving_context.ranges_done +\u003d 1"}],"source_content_type":"text/x-python","patch_set":1,"id":"7faddb67_77cca833","line":1165,"range":{"start_line":1164,"start_character":34,"end_line":1165,"end_character":58},"in_reply_to":"7faddb67_a884050c","updated":"2019-08-19 00:24:27.000000000","message":"Hmm, yeah interesting idea. In  theory we \"should\" be cleaving from a \"locked\" expiring broker. So if has nothing once, it should the second time... but there could be a case where this is one around.\n\nLazy loading the broker would mitigate, hmm.. interesting, I need to think about this some more now.. thanks Tim ;P","commit_id":"33a033be08d1c440fd6ba16c991a10c0cc5911b0"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"dcc2c581689d36a9a2e12de85fd409a7e19dce20","unresolved":false,"context_lines":[{"line_number":1233,"context_line":"        self._min_stat(\u0027cleaved\u0027, \u0027min_time\u0027, elapsed)"},{"line_number":1234,"context_line":"        self._max_stat(\u0027cleaved\u0027, \u0027max_time\u0027, elapsed)"},{"line_number":1235,"context_line":"        broker.merge_shard_ranges(shard_range)"},{"line_number":1236,"context_line":"        cleaving_context.cursor \u003d shard_range.upper_str"},{"line_number":1237,"context_line":"        cleaving_context.ranges_done +\u003d 1"},{"line_number":1238,"context_line":"        cleaving_context.ranges_todo -\u003d 1"},{"line_number":1239,"context_line":"        if shard_range.upper \u003e\u003d own_shard_range.upper:"},{"line_number":1240,"context_line":"            # cleaving complete"},{"line_number":1241,"context_line":"            cleaving_context.cleaving_done \u003d True"},{"line_number":1242,"context_line":"        cleaving_context.store(broker)"},{"line_number":1243,"context_line":"        self.logger.info("},{"line_number":1244,"context_line":"            \u0027Cleaved %s for shard range %s in %gs.\u0027,"},{"line_number":1245,"context_line":"            broker.path, shard_range, elapsed)"}],"source_content_type":"text/x-python","patch_set":1,"id":"7faddb67_689fed4f","line":1242,"range":{"start_line":1236,"start_character":8,"end_line":1242,"end_character":38},"updated":"2019-08-17 00:29:27.000000000","message":"Cool, so this is where we cribbed the context-update from; looks good.\n\nShould we do anything with shard_range? I\u0027m just eyeing that\n\n broker.merge_shard_ranges(shard_range)\n\nabove... I\u0027m not actually sure anything needs to happen, though.","commit_id":"33a033be08d1c440fd6ba16c991a10c0cc5911b0"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"c80a2742953d9d0fa9e38ccf9b0f6a491be618f7","unresolved":false,"context_lines":[{"line_number":1233,"context_line":"        self._min_stat(\u0027cleaved\u0027, \u0027min_time\u0027, elapsed)"},{"line_number":1234,"context_line":"        self._max_stat(\u0027cleaved\u0027, \u0027max_time\u0027, elapsed)"},{"line_number":1235,"context_line":"        broker.merge_shard_ranges(shard_range)"},{"line_number":1236,"context_line":"        cleaving_context.cursor \u003d shard_range.upper_str"},{"line_number":1237,"context_line":"        cleaving_context.ranges_done +\u003d 1"},{"line_number":1238,"context_line":"        cleaving_context.ranges_todo -\u003d 1"},{"line_number":1239,"context_line":"        if shard_range.upper \u003e\u003d own_shard_range.upper:"},{"line_number":1240,"context_line":"            # cleaving complete"},{"line_number":1241,"context_line":"            cleaving_context.cleaving_done \u003d True"},{"line_number":1242,"context_line":"        cleaving_context.store(broker)"},{"line_number":1243,"context_line":"        self.logger.info("},{"line_number":1244,"context_line":"            \u0027Cleaved %s for shard range %s in %gs.\u0027,"},{"line_number":1245,"context_line":"            broker.path, shard_range, elapsed)"}],"source_content_type":"text/x-python","patch_set":1,"id":"7faddb67_f7df38d4","line":1242,"range":{"start_line":1236,"start_character":8,"end_line":1242,"end_character":38},"in_reply_to":"7faddb67_689fed4f","updated":"2019-08-19 00:24:27.000000000","message":"I\u0027ll confirm. The context.store does update the broker. But I\u0027ll confirm these is nothing in the range we\u0027d need to also back up.","commit_id":"33a033be08d1c440fd6ba16c991a10c0cc5911b0"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"dcc2c581689d36a9a2e12de85fd409a7e19dce20","unresolved":false,"context_lines":[{"line_number":1299,"context_line":"                    if self._cleave_shard_range("},{"line_number":1300,"context_line":"                            broker, cleaving_context, shard_range):"},{"line_number":1301,"context_line":"                        ranges_done.append(shard_range)"},{"line_number":1302,"context_line":"                        if len(ranges_done) \u003d\u003d self.cleave_batch_size:"},{"line_number":1303,"context_line":"                            break"},{"line_number":1304,"context_line":"                    else:"},{"line_number":1305,"context_line":"                        break"}],"source_content_type":"text/x-python","patch_set":1,"id":"7faddb67_08c1992f","line":1302,"range":{"start_line":1302,"start_character":44,"end_line":1302,"end_character":45},"updated":"2019-08-17 00:29:27.000000000","message":"Shouldn\u0027t really matter, but for my own OCD, maybe this should be a\n\n \u003e\u003d\n\n(I\u0027m still a little haunted by https://github.com/openstack/swift/commit/2e7a7347f ;-)","commit_id":"33a033be08d1c440fd6ba16c991a10c0cc5911b0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"764b1b500feef388ade88c04c6d8b46489ae1f4b","unresolved":false,"context_lines":[{"line_number":773,"context_line":"                marker \u003d objects[-1][\u0027name\u0027]"},{"line_number":774,"context_line":"        if not objs_found:"},{"line_number":775,"context_line":"            self.logger.debug(\u0027no objects found\u0027)"},{"line_number":776,"context_line":"            raise ZeroCleavedObjectsException()"},{"line_number":777,"context_line":""},{"line_number":778,"context_line":"    def yield_objects_to_shard_range(self, broker, src_shard_range,"},{"line_number":779,"context_line":"                                     dest_shard_ranges):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_f36e3062","line":776,"updated":"2019-08-21 16:43:53.000000000","message":"I\u0027m finding it difficult to conceptualize around why the primary generator should raise an exception on the empty case...\n\nIt might be helpful to me, if you could point me at, *any* other generator in swift or stdlib that works this way.","commit_id":"4f41f875b9fe15952566577c6dbae864e1757b20"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"764b1b500feef388ade88c04c6d8b46489ae1f4b","unresolved":false,"context_lines":[{"line_number":832,"context_line":"                                   dest_shard_range,"},{"line_number":833,"context_line":"                                   info)"},{"line_number":834,"context_line":"                        last_index \u003d next_index"},{"line_number":835,"context_line":"                        dest_shard_range \u003d next_or_none(dest_shard_range_iter)"},{"line_number":836,"context_line":"                    next_index +\u003d 1"},{"line_number":837,"context_line":""},{"line_number":838,"context_line":"                if next_index !\u003d last_index:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_33236807","line":835,"updated":"2019-08-21 16:43:53.000000000","message":"we\u0027ve added another level to indention to this iteration block and add significant cyclomatic complexity - please consider cleaning this up with a method extraction.","commit_id":"4f41f875b9fe15952566577c6dbae864e1757b20"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"764b1b500feef388ade88c04c6d8b46489ae1f4b","unresolved":false,"context_lines":[{"line_number":843,"context_line":"                           None if unplaced else dest_shard_range,"},{"line_number":844,"context_line":"                           info)"},{"line_number":845,"context_line":"        except ZeroCleavedObjectsException:"},{"line_number":846,"context_line":"            return"},{"line_number":847,"context_line":""},{"line_number":848,"context_line":"    def _post_replicate_hook(self, broker, info, responses):"},{"line_number":849,"context_line":"        # override superclass behaviour"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_b392f849","line":846,"updated":"2019-08-21 16:43:53.000000000","message":"This handling does not make this look like an exceptional condition","commit_id":"4f41f875b9fe15952566577c6dbae864e1757b20"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"764b1b500feef388ade88c04c6d8b46489ae1f4b","unresolved":false,"context_lines":[{"line_number":1161,"context_line":"                    shard_broker.merge_items(objects)"},{"line_number":1162,"context_line":"            except ZeroCleavedObjectsException:"},{"line_number":1163,"context_line":"                self.logger.info(\"Cleaving \u0027%s\u0027: %r - zero objects found\","},{"line_number":1164,"context_line":"                                 broker.path, shard_range)"},{"line_number":1165,"context_line":"                if shard_broker.get_info()[\u0027put_timestamp\u0027] \u003d\u003d put_timestamp:"},{"line_number":1166,"context_line":"                    # This was just created, so don\u0027t need to replicate this"},{"line_number":1167,"context_line":"                    # SR because there was nothing there.. So cleanup and"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_33ccc85f","line":1164,"updated":"2019-08-21 16:43:53.000000000","message":"This message is un-conditoinal under zero objects?","commit_id":"4f41f875b9fe15952566577c6dbae864e1757b20"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d66c5cbf457f0b42e52748b2cfea1da4da03f2cf","unresolved":false,"context_lines":[{"line_number":1162,"context_line":"            except ZeroCleavedObjectsException:"},{"line_number":1163,"context_line":"                self.logger.info(\"Cleaving \u0027%s\u0027: %r - zero objects found\","},{"line_number":1164,"context_line":"                                 broker.path, shard_range)"},{"line_number":1165,"context_line":"                if shard_broker.get_info()[\u0027put_timestamp\u0027] \u003d\u003d put_timestamp:"},{"line_number":1166,"context_line":"                    # This was just created, so don\u0027t need to replicate this"},{"line_number":1167,"context_line":"                    # SR because there was nothing there.. So cleanup and"},{"line_number":1168,"context_line":"                    # remove the shard_broker from it\u0027s hand off location."}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_9631f85b","line":1165,"updated":"2019-08-21 05:31:40.000000000","message":"Oh, I think I get it...\n\nI was originally thinking of setting shard_broker to None and checking for that inside the loop above, but now I see that the sync_point check would complicate things.","commit_id":"4f41f875b9fe15952566577c6dbae864e1757b20"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d66c5cbf457f0b42e52748b2cfea1da4da03f2cf","unresolved":false,"context_lines":[{"line_number":1166,"context_line":"                    # This was just created, so don\u0027t need to replicate this"},{"line_number":1167,"context_line":"                    # SR because there was nothing there.. So cleanup and"},{"line_number":1168,"context_line":"                    # remove the shard_broker from it\u0027s hand off location."},{"line_number":1169,"context_line":"                    self.delete_db(shard_broker)"},{"line_number":1170,"context_line":"                    cleaving_context.cursor \u003d shard_range.upper_str"},{"line_number":1171,"context_line":"                    cleaving_context.ranges_done +\u003d 1"},{"line_number":1172,"context_line":"                    cleaving_context.ranges_todo -\u003d 1"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_b320d1b1","line":1169,"range":{"start_line":1169,"start_character":25,"end_line":1169,"end_character":48},"updated":"2019-08-21 05:31:40.000000000","message":"I think I\u0027d be fine with *just* having the delete guarded like this...","commit_id":"4f41f875b9fe15952566577c6dbae864e1757b20"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"764b1b500feef388ade88c04c6d8b46489ae1f4b","unresolved":false,"context_lines":[{"line_number":1178,"context_line":"                    # batch count. However if it wasn\u0027t newly created by us"},{"line_number":1179,"context_line":"                    # we don\u0027t know what\u0027s in it or why, so let it get"},{"line_number":1180,"context_line":"                    # replicated and counted in the batch count."},{"line_number":1181,"context_line":"                    raise"},{"line_number":1182,"context_line":"            # Note: the max row stored as a sync point is sampled *before*"},{"line_number":1183,"context_line":"            # objects are yielded to ensure that is less than or equal to"},{"line_number":1184,"context_line":"            # the last yielded row. Other sync points are also copied from the"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_b32e78f7","line":1181,"updated":"2019-08-21 16:43:53.000000000","message":"this re-raise (of the ZeroCleavedObjectsException?) is only way out of this block once we\u0027ve established the put_timestamp equivalency?","commit_id":"4f41f875b9fe15952566577c6dbae864e1757b20"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"764b1b500feef388ade88c04c6d8b46489ae1f4b","unresolved":false,"context_lines":[{"line_number":1311,"context_line":"                    else:"},{"line_number":1312,"context_line":"                        break"},{"line_number":1313,"context_line":"                except ZeroCleavedObjectsException:"},{"line_number":1314,"context_line":"                    continue"},{"line_number":1315,"context_line":"            else:"},{"line_number":1316,"context_line":"                self.logger.warning(\u0027Unexpected shard range state for cleave\u0027,"},{"line_number":1317,"context_line":"                                    shard_range.state)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_133f4c25","line":1314,"updated":"2019-08-21 16:43:53.000000000","message":"this is where we\u0027re catching the re-raise?  our handling does not make it seem exceptional","commit_id":"4f41f875b9fe15952566577c6dbae864e1757b20"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f3e3ea3df141dc197a9634fda29fffdb70bafc46","unresolved":false,"context_lines":[{"line_number":612,"context_line":"        \"\"\""},{"line_number":613,"context_line":"        part \u003d self.ring.get_part(shard_range.account, shard_range.container)"},{"line_number":614,"context_line":"        node \u003d self.find_local_handoff_for_part(part)"},{"line_number":615,"context_line":"        put_timestamp \u003d Timestamp(time.time()).internal"},{"line_number":616,"context_line":"        if not node:"},{"line_number":617,"context_line":"            raise DeviceUnavailable("},{"line_number":618,"context_line":"                \u0027No mounted devices found suitable for creating shard broker \u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_26482f85","line":615,"updated":"2019-09-26 23:20:05.000000000","message":"nit: Timestamp.now()? *shrug*","commit_id":"bb3f5eea8a9b747b62673bcc4fab7e7136f0940f"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"66987a536b08ed62d108ec2daec24339f0691d6e","unresolved":false,"context_lines":[{"line_number":811,"context_line":"            for obj in objs:"},{"line_number":812,"context_line":"                if dest_shard_range is None:"},{"line_number":813,"context_line":"                    # no more destinations: yield remainder of batch and"},{"line_number":814,"context_line":"                    # return NB there may be more batches of objects but"},{"line_number":815,"context_line":"                    # none of them will be placed so no point fetching them"},{"line_number":816,"context_line":"                    yield objs[last_index:], None, info"},{"line_number":817,"context_line":"                    return"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_f06e50c7","line":814,"updated":"2019-09-26 19:41:27.000000000","message":"NB stands for \"Nota Bene\" and opens a new sentence. If you want to reformat this way, you ought to a period at least. Honestly I thought \"NB\" was a number of batches, being returned.","commit_id":"bb3f5eea8a9b747b62673bcc4fab7e7136f0940f"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f3e3ea3df141dc197a9634fda29fffdb70bafc46","unresolved":false,"context_lines":[{"line_number":811,"context_line":"            for obj in objs:"},{"line_number":812,"context_line":"                if dest_shard_range is None:"},{"line_number":813,"context_line":"                    # no more destinations: yield remainder of batch and"},{"line_number":814,"context_line":"                    # return NB there may be more batches of objects but"},{"line_number":815,"context_line":"                    # none of them will be placed so no point fetching them"},{"line_number":816,"context_line":"                    yield objs[last_index:], None, info"},{"line_number":817,"context_line":"                    return"}],"source_content_type":"text/x-python","patch_set":4,"id":"3fa7e38b_46344bfc","line":814,"in_reply_to":"3fa7e38b_f06e50c7","updated":"2019-09-26 23:20:05.000000000","message":"I had a few more comments I wanted to add while reviewing; I\u0027ll clean this up when I push those.","commit_id":"bb3f5eea8a9b747b62673bcc4fab7e7136f0940f"}]}
