)]}'
{"swift/common/middleware/slo.py":[{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"0f88022e6a82d78a402b4bb32d4470b5084e2c91","unresolved":false,"context_lines":[{"line_number":41,"context_line":"    size_bytes: the size of the complete segment object in"},{"line_number":42,"context_line":"                bytes, or null"},{"line_number":43,"context_line":"    range: (Optional) the range within the object to use as a"},{"line_number":44,"context_line":"           segment. If ommitted, the entire object is used."},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"The format of the list will be::"},{"line_number":47,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"da20952f_97d9d759","line":44,"updated":"2015-09-04 01:35:53.000000000","message":"nit: \"omitted\"","commit_id":"cd815d82842db4a3f9c8236b1c735a381a84c1c3"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1e7ff186f13787dfca04f164dd835e4f2396255f","unresolved":false,"context_lines":[{"line_number":41,"context_line":"    size_bytes: the size of the complete segment object in"},{"line_number":42,"context_line":"                bytes, or null"},{"line_number":43,"context_line":"    range: (Optional) the range within the object to use as a"},{"line_number":44,"context_line":"           segment. If ommitted, the entire object is used."},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"The format of the list will be::"},{"line_number":47,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"da20952f_173e2728","line":44,"in_reply_to":"da20952f_97d9d759","updated":"2015-09-04 04:28:47.000000000","message":"Done","commit_id":"cd815d82842db4a3f9c8236b1c735a381a84c1c3"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"0f88022e6a82d78a402b4bb32d4470b5084e2c91","unresolved":false,"context_lines":[{"line_number":312,"context_line":"            if range is None:"},{"line_number":313,"context_line":"                range \u003d (0, seg_length - 1)"},{"line_number":314,"context_line":"            else:"},{"line_number":315,"context_line":"                range \u003d map(int, range.split(\u0027-\u0027))"},{"line_number":316,"context_line":""},{"line_number":317,"context_line":"            if config_true_value(seg_dict.get(\u0027sub_slo\u0027)):"},{"line_number":318,"context_line":"                # do this check here so that we can avoid fetching this last"}],"source_content_type":"text/x-python","patch_set":5,"id":"da20952f_37da4b4c","line":315,"updated":"2015-09-04 01:35:53.000000000","message":"nit: can we get a 1 here as the second arg to split(), or a comment maybe? Right now I see the \u0027if\u0027 branch always giving a 2-tuple but the \u0027else\u0027 branch doesn\u0027t give anything so interesting.\n\nAlso, I wonder if this will fail on python 3 because map is lazy there. Probably doesn\u0027t matter right now, but it might be worth a look if you\u0027ve got the time.","commit_id":"cd815d82842db4a3f9c8236b1c735a381a84c1c3"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1e7ff186f13787dfca04f164dd835e4f2396255f","unresolved":false,"context_lines":[{"line_number":312,"context_line":"            if range is None:"},{"line_number":313,"context_line":"                range \u003d (0, seg_length - 1)"},{"line_number":314,"context_line":"            else:"},{"line_number":315,"context_line":"                range \u003d map(int, range.split(\u0027-\u0027))"},{"line_number":316,"context_line":""},{"line_number":317,"context_line":"            if config_true_value(seg_dict.get(\u0027sub_slo\u0027)):"},{"line_number":318,"context_line":"                # do this check here so that we can avoid fetching this last"}],"source_content_type":"text/x-python","patch_set":5,"id":"da20952f_7713e3b8","line":315,"in_reply_to":"da20952f_37da4b4c","updated":"2015-09-04 04:28:47.000000000","message":"Done","commit_id":"cd815d82842db4a3f9c8236b1c735a381a84c1c3"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"0f88022e6a82d78a402b4bb32d4470b5084e2c91","unresolved":false,"context_lines":[{"line_number":691,"context_line":"                        segment_length \u003d head_seg_resp.content_length"},{"line_number":692,"context_line":"                    else:"},{"line_number":693,"context_line":"                        seg_dict[\u0027range\u0027] \u003d \u0027,\u0027.join("},{"line_number":694,"context_line":"                            \u0027%d-%d\u0027 % (r[0], r[1] - 1) for r in ranges)"},{"line_number":695,"context_line":"                        segment_length \u003d sum(r[1] - r[0] for r in ranges)"},{"line_number":696,"context_line":""},{"line_number":697,"context_line":"                if segment_length \u003c self.min_segment_size and \\"}],"source_content_type":"text/x-python","patch_set":5,"id":"da20952f_57dfbf39","line":694,"updated":"2015-09-04 01:35:53.000000000","message":"Do we actually have multiple ranges here, or is it always just one?","commit_id":"cd815d82842db4a3f9c8236b1c735a381a84c1c3"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1e7ff186f13787dfca04f164dd835e4f2396255f","unresolved":false,"context_lines":[{"line_number":691,"context_line":"                        segment_length \u003d head_seg_resp.content_length"},{"line_number":692,"context_line":"                    else:"},{"line_number":693,"context_line":"                        seg_dict[\u0027range\u0027] \u003d \u0027,\u0027.join("},{"line_number":694,"context_line":"                            \u0027%d-%d\u0027 % (r[0], r[1] - 1) for r in ranges)"},{"line_number":695,"context_line":"                        segment_length \u003d sum(r[1] - r[0] for r in ranges)"},{"line_number":696,"context_line":""},{"line_number":697,"context_line":"                if segment_length \u003c self.min_segment_size and \\"}],"source_content_type":"text/x-python","patch_set":5,"id":"da20952f_570edf8c","line":694,"in_reply_to":"da20952f_57dfbf39","updated":"2015-09-04 04:28:47.000000000","message":"Holdover from when I was allowing multiple ranges. Cleaned up.","commit_id":"cd815d82842db4a3f9c8236b1c735a381a84c1c3"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"b99eeea76f263fb3283c13f59c6951296a571e7a","unresolved":false,"context_lines":[{"line_number":211,"context_line":"                    raise HTTPBadRequest(\u0027Invalid SLO Manifest File\u0027)"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"            # Stuff the optional headers back into the manifest"},{"line_number":214,"context_line":"            seg_dict.update(opt_dict)"},{"line_number":215,"context_line":"    except (AttributeError, TypeError):"},{"line_number":216,"context_line":"        raise HTTPBadRequest(\u0027Invalid SLO Manifest File\u0027)"},{"line_number":217,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"ba15a1d1_eb239dbb","line":214,"updated":"2015-09-23 02:45:08.000000000","message":"Popping out creating an opt_keys set, just to merge them back in seems a little unclean.. couldn\u0027t we just:\n\n  if req_keys.issubset(set(seg_dict)) or\n          \u0027/\u0027 not in seg_dict[\u0027path\u0027].lstrip(\u0027/\u0027)):\n      raise HTTPBadRequest(\u0027Invalid SLO Manifest File\u0027)\n\nThen simply check for range in the original seg_dict?\n\n  if seg_dict.get(\u0027range\u0027):\n      # validate range etc.","commit_id":"a6236d87a4ed7bd3ec1e8e5edf6a7908789c2abe"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a4ffbd5a4e60608a8d4e7f5957eb2f2802c6e89d","unresolved":false,"context_lines":[{"line_number":211,"context_line":"                    raise HTTPBadRequest(\u0027Invalid SLO Manifest File\u0027)"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"            # Stuff the optional headers back into the manifest"},{"line_number":214,"context_line":"            seg_dict.update(opt_dict)"},{"line_number":215,"context_line":"    except (AttributeError, TypeError):"},{"line_number":216,"context_line":"        raise HTTPBadRequest(\u0027Invalid SLO Manifest File\u0027)"},{"line_number":217,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"ba15a1d1_7ccd1130","line":214,"in_reply_to":"ba15a1d1_2e0e838c","updated":"2015-09-23 05:42:33.000000000","message":"Good point! Still need the other check, though (so,\n\n req_keys.issubset(set(seg_dict)) and set(seg_dict).issubset(req_keys | opt_keys)\n\n). Will fix.","commit_id":"a6236d87a4ed7bd3ec1e8e5edf6a7908789c2abe"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"4933a74e4f1ec311a27ef92720fec7c4b1aa1264","unresolved":false,"context_lines":[{"line_number":211,"context_line":"                    raise HTTPBadRequest(\u0027Invalid SLO Manifest File\u0027)"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"            # Stuff the optional headers back into the manifest"},{"line_number":214,"context_line":"            seg_dict.update(opt_dict)"},{"line_number":215,"context_line":"    except (AttributeError, TypeError):"},{"line_number":216,"context_line":"        raise HTTPBadRequest(\u0027Invalid SLO Manifest File\u0027)"},{"line_number":217,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"ba15a1d1_2e0e838c","line":214,"in_reply_to":"ba15a1d1_eb239dbb","updated":"2015-09-23 02:58:24.000000000","message":"Oops meant:\n\n If not req_keys.issubset(set(seg_dict)) or ...","commit_id":"a6236d87a4ed7bd3ec1e8e5edf6a7908789c2abe"}],"test/unit/common/middleware/test_slo.py":[{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"0f88022e6a82d78a402b4bb32d4470b5084e2c91","unresolved":false,"context_lines":[{"line_number":1812,"context_line":"        status, headers, body, exc \u003d self.call_slo(req, expect_exception\u003dTrue)"},{"line_number":1813,"context_line":"        headers \u003d swob.HeaderKeyDict(headers)"},{"line_number":1814,"context_line":""},{"line_number":1815,"context_line":"        self.assertIsInstance(exc, ListingIterError)"},{"line_number":1816,"context_line":"        # we don\u0027t know at header-sending time that things are going to go"},{"line_number":1817,"context_line":"        # wrong, so we end up with a 200 and a truncated body"},{"line_number":1818,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)"}],"source_content_type":"text/x-python","patch_set":5,"id":"da20952f_f7e853e4","line":1815,"updated":"2015-09-04 01:35:53.000000000","message":"nice","commit_id":"cd815d82842db4a3f9c8236b1c735a381a84c1c3"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"0f88022e6a82d78a402b4bb32d4470b5084e2c91","unresolved":false,"context_lines":[{"line_number":1965,"context_line":"        self.assertEqual(self.app.calls, ["},{"line_number":1966,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/manifest-abcd\u0027),"},{"line_number":1967,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/manifest-bc\u0027),"},{"line_number":1968,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/a_5?multipart-manifest\u003dget\u0027),"},{"line_number":1969,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/b_10?multipart-manifest\u003dget\u0027),"},{"line_number":1970,"context_line":"            # This one has the error, and so is the last one we fetch."},{"line_number":1971,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/c_15?multipart-manifest\u003dget\u0027)])"}],"source_content_type":"text/x-python","patch_set":5,"id":"da20952f_17e62715","line":1968,"updated":"2015-09-04 01:35:53.000000000","message":"Why did these change, out of curiosity? It\u0027s not the end of the world, of course, but it was nice before that Swift only had to fetch one manifest before getting a segment. Keeps time-to-first-byte low.","commit_id":"cd815d82842db4a3f9c8236b1c735a381a84c1c3"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1e7ff186f13787dfca04f164dd835e4f2396255f","unresolved":false,"context_lines":[{"line_number":1965,"context_line":"        self.assertEqual(self.app.calls, ["},{"line_number":1966,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/manifest-abcd\u0027),"},{"line_number":1967,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/manifest-bc\u0027),"},{"line_number":1968,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/a_5?multipart-manifest\u003dget\u0027),"},{"line_number":1969,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/b_10?multipart-manifest\u003dget\u0027),"},{"line_number":1970,"context_line":"            # This one has the error, and so is the last one we fetch."},{"line_number":1971,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/c_15?multipart-manifest\u003dget\u0027)])"}],"source_content_type":"text/x-python","patch_set":5,"id":"da20952f_f76e132e","line":1968,"in_reply_to":"da20952f_17e62715","updated":"2015-09-04 04:28:47.000000000","message":"We don\u0027t know whether or not manifest-bc starts out requesting bytes from a_5 or not. If it *does*, we want to coalesce the requests.","commit_id":"cd815d82842db4a3f9c8236b1c735a381a84c1c3"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"0f88022e6a82d78a402b4bb32d4470b5084e2c91","unresolved":false,"context_lines":[{"line_number":1985,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/manifest-abcd\u0027),"},{"line_number":1986,"context_line":"            # This one has the error, and so is the last one we fetch."},{"line_number":1987,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/manifest-bc\u0027),"},{"line_number":1988,"context_line":"            # But we ewre looking ahead to see if we could combine ranges,"},{"line_number":1989,"context_line":"            # so we still get the first segment out"},{"line_number":1990,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/a_5?multipart-manifest\u003dget\u0027)])"},{"line_number":1991,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"da20952f_b7ee5beb","line":1988,"updated":"2015-09-04 01:35:53.000000000","message":"nit: were","commit_id":"cd815d82842db4a3f9c8236b1c735a381a84c1c3"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1e7ff186f13787dfca04f164dd835e4f2396255f","unresolved":false,"context_lines":[{"line_number":1985,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/manifest-abcd\u0027),"},{"line_number":1986,"context_line":"            # This one has the error, and so is the last one we fetch."},{"line_number":1987,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/manifest-bc\u0027),"},{"line_number":1988,"context_line":"            # But we ewre looking ahead to see if we could combine ranges,"},{"line_number":1989,"context_line":"            # so we still get the first segment out"},{"line_number":1990,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/a_5?multipart-manifest\u003dget\u0027)])"},{"line_number":1991,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"da20952f_176ce733","line":1988,"in_reply_to":"da20952f_b7ee5beb","updated":"2015-09-04 04:28:47.000000000","message":"Done","commit_id":"cd815d82842db4a3f9c8236b1c735a381a84c1c3"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"2b8d6dd1fb139f05dcb6a9dba3439f387feaef16","unresolved":false,"context_lines":[{"line_number":524,"context_line":"            \u0027/v1/AUTH_test/checktest/man_3?multipart-manifest\u003dput\u0027,"},{"line_number":525,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027PUT\u0027}, body\u003dbad_data)"},{"line_number":526,"context_line":"        self.assertRaises(HTTPException, self.slo.handle_multipart_put, req,"},{"line_number":527,"context_line":"                          fake_start_response)"},{"line_number":528,"context_line":""},{"line_number":529,"context_line":"    def test_handle_single_ranges(self):"},{"line_number":530,"context_line":"        good_data \u003d json.dumps("}],"source_content_type":"text/x-python","patch_set":9,"id":"ba15a1d1_32adc731","line":527,"updated":"2015-09-21 19:50:17.000000000","message":"If you do this:\n\n    with self.assertRaises(HTTPException) as catcher:\n        self.slo_handle_multipart_put(req, fake_start_response)\n\nthen you can also do this:\n\n    self.assertEqual(400, catcher.exception.status_int)\n\nand get some stronger assertion about the error. It\u0027s not super-important, but HTTPServerError is-a HTTPException, so not having the status code here just makes me a touch nervous. I mean, I checked that it worked by hand, so I know the test is good *now*; I\u0027m only nervous about future slo breakage not being caught.","commit_id":"a6236d87a4ed7bd3ec1e8e5edf6a7908789c2abe"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a4ffbd5a4e60608a8d4e7f5957eb2f2802c6e89d","unresolved":false,"context_lines":[{"line_number":524,"context_line":"            \u0027/v1/AUTH_test/checktest/man_3?multipart-manifest\u003dput\u0027,"},{"line_number":525,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027PUT\u0027}, body\u003dbad_data)"},{"line_number":526,"context_line":"        self.assertRaises(HTTPException, self.slo.handle_multipart_put, req,"},{"line_number":527,"context_line":"                          fake_start_response)"},{"line_number":528,"context_line":""},{"line_number":529,"context_line":"    def test_handle_single_ranges(self):"},{"line_number":530,"context_line":"        good_data \u003d json.dumps("}],"source_content_type":"text/x-python","patch_set":9,"id":"ba15a1d1_5c64cd20","line":527,"in_reply_to":"ba15a1d1_32adc731","updated":"2015-09-23 05:42:33.000000000","message":"Can do.","commit_id":"a6236d87a4ed7bd3ec1e8e5edf6a7908789c2abe"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"e9184ed096bee19541387770d7a42ee6d7ba49c9","unresolved":false,"context_lines":[{"line_number":525,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027PUT\u0027}, body\u003dbad_data)"},{"line_number":526,"context_line":"        with self.assertRaises(HTTPException) as catcher:"},{"line_number":527,"context_line":"            self.slo.handle_multipart_put(req, fake_start_response)"},{"line_number":528,"context_line":"        self.assertEqual(400, catcher.exception.status_int)"},{"line_number":529,"context_line":""},{"line_number":530,"context_line":"    def test_handle_single_ranges(self):"},{"line_number":531,"context_line":"        good_data \u003d json.dumps("}],"source_content_type":"text/x-python","patch_set":12,"id":"ba15a1d1_05e9eab6","line":528,"updated":"2015-09-24 02:28:28.000000000","message":"NIT: This can be a follow up. But are there any other ranges you can add to this test?\n\nOtherwise the test name is lying  (ranges or range) :)","commit_id":"25d5e686a172a2418fc6e4028174a354df29e0f1"}]}
