)]}'
{"etc/proxy-server.conf-sample":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"dfdf1b1198a4c87e2b37f41d3558ec459dca5834","unresolved":false,"context_lines":[{"line_number":1028,"context_line":"# `?multipart-manifest\u003ddelete\u0026async\u003don`. You may want to turn this off if it"},{"line_number":1029,"context_line":"# negatively impacts your expirers; in that case, the deletes will still"},{"line_number":1030,"context_line":"# be done as part of the client request."},{"line_number":1031,"context_line":"# allow_async_delete \u003d true"},{"line_number":1032,"context_line":""},{"line_number":1033,"context_line":"# Note: Put after auth and staticweb in the pipeline."},{"line_number":1034,"context_line":"# If you don\u0027t put it in the pipeline, it will be inserted for you."}],"source_content_type":"application/octet-stream","patch_set":12,"id":"7f6b1bfe_d5343d4d","line":1031,"range":{"start_line":1031,"start_character":23,"end_line":1031,"end_character":27},"updated":"2020-10-14 21:42:16.000000000","message":"We should default to false, at least for now.","commit_id":"a7e429d2f1b21ab8d18d7faa97893dc0a6731471"}],"swift/common/middleware/s3api/controllers/bucket.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":348,"context_line":"                # s3api cannot support multiple regions currently."},{"line_number":349,"context_line":"                raise InvalidLocationConstraint()"},{"line_number":350,"context_line":""},{"line_number":351,"context_line":"        resp \u003d req.get_response(self.app, body\u003d\u0027\u0027)"},{"line_number":352,"context_line":""},{"line_number":353,"context_line":"        resp.status \u003d HTTP_OK"},{"line_number":354,"context_line":"        resp.location \u003d \u0027/\u0027 + req.container_name"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_8301f470","line":351,"updated":"2020-09-29 15:49:21.000000000","message":"it\u0027s not obvious to me we should be circumventing the wsgi.input passed in from the client req.environ\n\nhow is this related to https://review.opendev.org/#/c/331291/","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"3cee5ef8a04a790707c3fbad9965e500f41735f9","unresolved":false,"context_lines":[{"line_number":348,"context_line":"                # s3api cannot support multiple regions currently."},{"line_number":349,"context_line":"                raise InvalidLocationConstraint()"},{"line_number":350,"context_line":""},{"line_number":351,"context_line":"        resp \u003d req.get_response(self.app, body\u003d\u0027\u0027)"},{"line_number":352,"context_line":""},{"line_number":353,"context_line":"        resp.status \u003d HTTP_OK"},{"line_number":354,"context_line":"        resp.location \u003d \u0027/\u0027 + req.container_name"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_4bd36e02","line":351,"in_reply_to":"9f560f44_55b82d10","updated":"2020-09-30 00:38:47.000000000","message":"Done","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0f055cd93488c309834f15e509439dc01d970bf2","unresolved":false,"context_lines":[{"line_number":348,"context_line":"                # s3api cannot support multiple regions currently."},{"line_number":349,"context_line":"                raise InvalidLocationConstraint()"},{"line_number":350,"context_line":""},{"line_number":351,"context_line":"        resp \u003d req.get_response(self.app, body\u003d\u0027\u0027)"},{"line_number":352,"context_line":""},{"line_number":353,"context_line":"        resp.status \u003d HTTP_OK"},{"line_number":354,"context_line":"        resp.location \u003d \u0027/\u0027 + req.container_name"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_55b82d10","line":351,"in_reply_to":"9f560f44_8301f470","updated":"2020-09-29 18:24:37.000000000","message":"It\u0027s fallout from that test helper change -- I could re-work it to avoid this if you\u0027d rather.","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"}],"swift/common/middleware/s3api/s3request.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"ffd4b50b13d7d70635ce121ca48782674ab2c4d7","unresolved":false,"context_lines":[{"line_number":1484,"context_line":"        resp \u003d self.get_response(app, \u0027HEAD\u0027, obj\u003dobj, query\u003dquery)"},{"line_number":1485,"context_line":"        if not resp.is_slo:"},{"line_number":1486,"context_line":"            return {}"},{"line_number":1487,"context_line":"        elif resp.sysmeta_headers.get(sysmeta_header(\u0027object\u0027, \u0027etag\u0027)):"},{"line_number":1488,"context_line":"            return {\u0027multipart-manifest\u0027: \u0027delete\u0027, \u0027async\u0027: \u0027on\u0027}"},{"line_number":1489,"context_line":"        else:"},{"line_number":1490,"context_line":"            return {\u0027multipart-manifest\u0027: \u0027delete\u0027}"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_bd08a72e","line":1487,"updated":"2020-09-28 15:53:45.000000000","message":"I should probably plumb in a config option here -- I think on-by-default is probably fine, but if it turns out this is a terrible idea, it\u0027ll be nice to have a way to quickly \u0026 easily turn it back off.","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0f055cd93488c309834f15e509439dc01d970bf2","unresolved":false,"context_lines":[{"line_number":1484,"context_line":"        resp \u003d self.get_response(app, \u0027HEAD\u0027, obj\u003dobj, query\u003dquery)"},{"line_number":1485,"context_line":"        if not resp.is_slo:"},{"line_number":1486,"context_line":"            return {}"},{"line_number":1487,"context_line":"        elif resp.sysmeta_headers.get(sysmeta_header(\u0027object\u0027, \u0027etag\u0027)):"},{"line_number":1488,"context_line":"            return {\u0027multipart-manifest\u0027: \u0027delete\u0027, \u0027async\u0027: \u0027on\u0027}"},{"line_number":1489,"context_line":"        else:"},{"line_number":1490,"context_line":"            return {\u0027multipart-manifest\u0027: \u0027delete\u0027}"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_f5c7c197","line":1487,"in_reply_to":"9f560f44_98dddf43","updated":"2020-09-29 18:24:37.000000000","message":"Good point -- I really was just thinking about s3api, but you\u0027re right that slo is the better place for it.","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":1484,"context_line":"        resp \u003d self.get_response(app, \u0027HEAD\u0027, obj\u003dobj, query\u003dquery)"},{"line_number":1485,"context_line":"        if not resp.is_slo:"},{"line_number":1486,"context_line":"            return {}"},{"line_number":1487,"context_line":"        elif resp.sysmeta_headers.get(sysmeta_header(\u0027object\u0027, \u0027etag\u0027)):"},{"line_number":1488,"context_line":"            return {\u0027multipart-manifest\u0027: \u0027delete\u0027, \u0027async\u0027: \u0027on\u0027}"},{"line_number":1489,"context_line":"        else:"},{"line_number":1490,"context_line":"            return {\u0027multipart-manifest\u0027: \u0027delete\u0027}"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_98dddf43","line":1487,"in_reply_to":"9f560f44_bd08a72e","updated":"2020-09-29 15:49:21.000000000","message":"yes please, bonus points if s3api is \"just\" using /info","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"6e5dd9dccfd82eb6fa9442357515af0302bfc0c5","unresolved":false,"context_lines":[{"line_number":1485,"context_line":"        if not resp.is_slo:"},{"line_number":1486,"context_line":"            return {}"},{"line_number":1487,"context_line":"        elif resp.sysmeta_headers.get(sysmeta_header(\u0027object\u0027, \u0027etag\u0027)):"},{"line_number":1488,"context_line":"            # Even if allow_asynd_delete is turned off, SLO will just handle"},{"line_number":1489,"context_line":"            # the delete synchronously"},{"line_number":1490,"context_line":"            return {\u0027multipart-manifest\u0027: \u0027delete\u0027, \u0027async\u0027: \u0027on\u0027}"},{"line_number":1491,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":15,"id":"1f621f24_c3f1a797","line":1488,"updated":"2020-11-10 06:18:05.000000000","message":"There\u0027s typo in allow_async_delete - it is in comments but should be visible with grep.\n\nAlso, the logic of this comment seems inverted. Aren\u0027t you setting \u0027async\u0027:\u0027on\u0027 just a line below?","commit_id":"d870936ba381cbcd69d519cf5b2c6d3ed41a0d46"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"715c048d2f9420bdce1be3b4a5345c83a30b1352","unresolved":false,"context_lines":[{"line_number":1485,"context_line":"        if not resp.is_slo:"},{"line_number":1486,"context_line":"            return {}"},{"line_number":1487,"context_line":"        elif resp.sysmeta_headers.get(sysmeta_header(\u0027object\u0027, \u0027etag\u0027)):"},{"line_number":1488,"context_line":"            # Even if allow_asynd_delete is turned off, SLO will just handle"},{"line_number":1489,"context_line":"            # the delete synchronously"},{"line_number":1490,"context_line":"            return {\u0027multipart-manifest\u0027: \u0027delete\u0027, \u0027async\u0027: \u0027on\u0027}"},{"line_number":1491,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":15,"id":"1f621f24_f3d747ed","line":1488,"in_reply_to":"1f621f24_c3f1a797","updated":"2020-11-10 18:19:58.000000000","message":"#willfix\n\nThe point of the comment was more about why I\u0027m not looking at\n\n get_swift_info().get(\u0027slo\u0027, {}).get(\u0027allow_async_delete\u0027)\n\nbefore deciding whether to include async\u003don or not. I\u0027ll always set it because even if the operator turned off async deletes in SLO\u0027s config, it\u0027s not going to trip an error.","commit_id":"d870936ba381cbcd69d519cf5b2c6d3ed41a0d46"}],"swift/common/middleware/slo.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"1c2da6e9dd3145d3241a0bbf3708950f221e3788","unresolved":false,"context_lines":[{"line_number":1576,"context_line":"            headers\u003d{\u0027Content-Type\u0027: \u0027application/json\u0027,"},{"line_number":1577,"context_line":"                     \u0027X-Backend-Storage-Policy-Index\u0027: \u00270\u0027,"},{"line_number":1578,"context_line":"                     \u0027X-Backend-Allow-Private-Methods\u0027: \u0027True\u0027},"},{"line_number":1579,"context_line":"        )"},{"line_number":1580,"context_line":"        resp \u003d enqueue_req.get_response(self.app)"},{"line_number":1581,"context_line":"        if not resp.is_success:"},{"line_number":1582,"context_line":"            self.logger.error("}],"source_content_type":"text/x-python","patch_set":1,"id":"ff570b3c_69521f15","line":1579,"updated":"2020-06-02 23:29:36.000000000","message":"this is awesome.","commit_id":"17f7aea46239c97a9fdc5fe7a58c5bc1e6bf94a3"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"03a449efe0d6eb5770c1b58eb13f68579885e9d1","unresolved":false,"context_lines":[{"line_number":295,"context_line":"    ?multipart-manifest\u003ddelete\u0026async\u003dyes"},{"line_number":296,"context_line":""},{"line_number":297,"context_line":"will schedule all the segments referenced in the manifest to be deleted"},{"line_number":298,"context_line":"asynchronously and then delete the manifest itself. This option is only"},{"line_number":299,"context_line":"available when all segments are in the same container and none of them are"},{"line_number":300,"context_line":"nested SLOs."},{"line_number":301,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"ff570b3c_6614c94d","line":298,"updated":"2020-06-06 04:21:24.000000000","message":"Should probably call out how the segments will continue to appear in listings and count against quotas until the expirer cleans them up.","commit_id":"cc18bf2b53ac984410477eec98f163ab2033de07"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a2e86b349bf6041f6de06d0daabfbf17b772a937","unresolved":false,"context_lines":[{"line_number":295,"context_line":"    ?multipart-manifest\u003ddelete\u0026async\u003dyes"},{"line_number":296,"context_line":""},{"line_number":297,"context_line":"will schedule all the segments referenced in the manifest to be deleted"},{"line_number":298,"context_line":"asynchronously and then delete the manifest itself. This option is only"},{"line_number":299,"context_line":"available when all segments are in the same container and none of them are"},{"line_number":300,"context_line":"nested SLOs."},{"line_number":301,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9f560f44_ba4237aa","line":298,"in_reply_to":"ff570b3c_6614c94d","updated":"2020-09-16 15:13:20.000000000","message":"Done","commit_id":"cc18bf2b53ac984410477eec98f163ab2033de07"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d40d4454b587313362452b5119f8f5b921ac3095","unresolved":false,"context_lines":[{"line_number":1528,"context_line":"            obj_path \u003d (\u0027/%s/%s\u0027 % (container, obj)).decode(\u0027utf-8\u0027)"},{"line_number":1529,"context_line":"        else:"},{"line_number":1530,"context_line":"            obj_path \u003d \u0027/%s/%s\u0027 % (wsgi_to_str(container), wsgi_to_str(obj))"},{"line_number":1531,"context_line":"        segments \u003d self.get_slo_segments(obj_path, req)"},{"line_number":1532,"context_line":"        if not segments:"},{"line_number":1533,"context_line":"            # Degenerate case: just delete the manifest"},{"line_number":1534,"context_line":"            return self.app"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff570b3c_59224aa4","line":1531,"updated":"2020-06-06 04:34:33.000000000","message":"Need to filter out data segments.","commit_id":"cc18bf2b53ac984410477eec98f163ab2033de07"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a2e86b349bf6041f6de06d0daabfbf17b772a937","unresolved":false,"context_lines":[{"line_number":1528,"context_line":"            obj_path \u003d (\u0027/%s/%s\u0027 % (container, obj)).decode(\u0027utf-8\u0027)"},{"line_number":1529,"context_line":"        else:"},{"line_number":1530,"context_line":"            obj_path \u003d \u0027/%s/%s\u0027 % (wsgi_to_str(container), wsgi_to_str(obj))"},{"line_number":1531,"context_line":"        segments \u003d self.get_slo_segments(obj_path, req)"},{"line_number":1532,"context_line":"        if not segments:"},{"line_number":1533,"context_line":"            # Degenerate case: just delete the manifest"},{"line_number":1534,"context_line":"            return self.app"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f560f44_1a11a3b0","line":1531,"in_reply_to":"ff570b3c_59224aa4","updated":"2020-09-16 15:13:20.000000000","message":"Done","commit_id":"cc18bf2b53ac984410477eec98f163ab2033de07"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d40d4454b587313362452b5119f8f5b921ac3095","unresolved":false,"context_lines":[{"line_number":1548,"context_line":"        segment_container \u003d segment_containers.pop()"},{"line_number":1549,"context_line":"        if \u0027swift.authorize\u0027 in req.environ:"},{"line_number":1550,"context_line":"            container_info \u003d get_container_info("},{"line_number":1551,"context_line":"                req.environ, self.app, swift_source\u003d\u0027VW\u0027)"},{"line_number":1552,"context_line":"            req.acl \u003d container_info.get(\u0027write_acl\u0027)"},{"line_number":1553,"context_line":"            aresp \u003d req.environ[\u0027swift.authorize\u0027](req)"},{"line_number":1554,"context_line":"            if aresp:"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff570b3c_394e766e","line":1551,"range":{"start_line":1551,"start_character":53,"end_line":1551,"end_character":55},"updated":"2020-06-06 04:34:33.000000000","message":"Forgot to update this one\u0027s source when I lifted it.\n\nI wonder if we could hoist much of this check into swob, so we\u0027d have something like\n\n resp \u003d req.check_access(\u0027write_acl\u0027, swift_source\u003d\u0027SLO\u0027)\n if resp:\n     return resp\n if segment_container !\u003d container:\n     resp \u003d req.check_access(\n         \u0027write_acl\u0027, account, segment_container, swift_source\u003d\u0027SLO\u0027)\n     if resp:\n         return resp","commit_id":"cc18bf2b53ac984410477eec98f163ab2033de07"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a2e86b349bf6041f6de06d0daabfbf17b772a937","unresolved":false,"context_lines":[{"line_number":1548,"context_line":"        segment_container \u003d segment_containers.pop()"},{"line_number":1549,"context_line":"        if \u0027swift.authorize\u0027 in req.environ:"},{"line_number":1550,"context_line":"            container_info \u003d get_container_info("},{"line_number":1551,"context_line":"                req.environ, self.app, swift_source\u003d\u0027VW\u0027)"},{"line_number":1552,"context_line":"            req.acl \u003d container_info.get(\u0027write_acl\u0027)"},{"line_number":1553,"context_line":"            aresp \u003d req.environ[\u0027swift.authorize\u0027](req)"},{"line_number":1554,"context_line":"            if aresp:"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f560f44_ba1b57c8","line":1551,"range":{"start_line":1551,"start_character":53,"end_line":1551,"end_character":55},"in_reply_to":"ff570b3c_394e766e","updated":"2020-09-16 15:13:20.000000000","message":"Fixed the source. Will look into a refactor as a separate patch.","commit_id":"cc18bf2b53ac984410477eec98f163ab2033de07"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"c72069937d1cccdb1536c85b911bb69644d9f22c","unresolved":false,"context_lines":[{"line_number":1571,"context_line":"        enqueue_req \u003d make_pre_authed_request("},{"line_number":1572,"context_line":"            req.environ,"},{"line_number":1573,"context_line":"            method\u003d\u0027UPDATE\u0027,"},{"line_number":1574,"context_line":"            path\u003d\"/v1/.expiring_objects/%d\" % int(ts),"},{"line_number":1575,"context_line":"            body\u003djson.dumps(expirer_jobs),"},{"line_number":1576,"context_line":"            headers\u003d{\u0027Content-Type\u0027: \u0027application/json\u0027,"},{"line_number":1577,"context_line":"                     \u0027X-Backend-Storage-Policy-Index\u0027: \u00270\u0027,"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff570b3c_9cfda50a","line":1574,"updated":"2020-06-11 03:19:15.000000000","message":"What is going to happen if the expirer has expiring_objects_account_name set or dequeue_from_legacy unset?","commit_id":"cc18bf2b53ac984410477eec98f163ab2033de07"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a2e86b349bf6041f6de06d0daabfbf17b772a937","unresolved":false,"context_lines":[{"line_number":1571,"context_line":"        enqueue_req \u003d make_pre_authed_request("},{"line_number":1572,"context_line":"            req.environ,"},{"line_number":1573,"context_line":"            method\u003d\u0027UPDATE\u0027,"},{"line_number":1574,"context_line":"            path\u003d\"/v1/.expiring_objects/%d\" % int(ts),"},{"line_number":1575,"context_line":"            body\u003djson.dumps(expirer_jobs),"},{"line_number":1576,"context_line":"            headers\u003d{\u0027Content-Type\u0027: \u0027application/json\u0027,"},{"line_number":1577,"context_line":"                     \u0027X-Backend-Storage-Policy-Index\u0027: \u00270\u0027,"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f560f44_5a803bc0","line":1574,"in_reply_to":"ff570b3c_172f9d88","updated":"2020-09-16 15:13:20.000000000","message":"Done","commit_id":"cc18bf2b53ac984410477eec98f163ab2033de07"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5c739297dbf24ecd61f5181f4eab5829994d2cf2","unresolved":false,"context_lines":[{"line_number":1571,"context_line":"        enqueue_req \u003d make_pre_authed_request("},{"line_number":1572,"context_line":"            req.environ,"},{"line_number":1573,"context_line":"            method\u003d\u0027UPDATE\u0027,"},{"line_number":1574,"context_line":"            path\u003d\"/v1/.expiring_objects/%d\" % int(ts),"},{"line_number":1575,"context_line":"            body\u003djson.dumps(expirer_jobs),"},{"line_number":1576,"context_line":"            headers\u003d{\u0027Content-Type\u0027: \u0027application/json\u0027,"},{"line_number":1577,"context_line":"                     \u0027X-Backend-Storage-Policy-Index\u0027: \u00270\u0027,"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff570b3c_172f9d88","line":1574,"in_reply_to":"ff570b3c_9cfda50a","updated":"2020-06-11 22:37:29.000000000","message":"Good catch! Fortunately, looks like we recommend it be set in the [DEFAULT] section for proxy-server, too, so it should be fairly accessible; I\u0027ll update this to use it.\n\nCome to think of it, I wonder if we should move it to constraints, similar to what we did with auto_create_account_prefix in https://github.com/openstack/swift/commit/4601548da... hmm...\n\nI\u0027m less worried about dequeue_from_legacy -- if anyone\u0027s got that turned off, they\u0027re already in a world of hurt since we haven\u0027t landed https://review.opendev.org/#/c/517389/.","commit_id":"cc18bf2b53ac984410477eec98f163ab2033de07"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"5acc80ea16bc368bc9f5fc3e08aa8513fca3a8f7","unresolved":false,"context_lines":[{"line_number":1542,"context_line":"            obj_path \u003d (\u0027/%s/%s\u0027 % (container, obj)).decode(\u0027utf-8\u0027)"},{"line_number":1543,"context_line":"        else:"},{"line_number":1544,"context_line":"            obj_path \u003d \u0027/%s/%s\u0027 % (wsgi_to_str(container), wsgi_to_str(obj))"},{"line_number":1545,"context_line":"        segments \u003d [seg for seg in self.get_slo_segments(obj_path, req)"},{"line_number":1546,"context_line":"                    if \u0027data\u0027 not in seg]"},{"line_number":1547,"context_line":"        if not segments:"},{"line_number":1548,"context_line":"            # Degenerate case: just delete the manifest"}],"source_content_type":"text/x-python","patch_set":7,"id":"9f560f44_b36d21ce","line":1545,"updated":"2020-09-18 02:04:15.000000000","message":"I think I\u0027m seeing a small typing mismatch here.\n\nget_slo_segments() returns str, because json.loads(resp.body), right?\nSo, in sequence:\nsegments str\nsegment_containers str\nsegment_container str\nthen, you compare it to container, which comes out of split_path.","commit_id":"b091c3b5b61f755c38880c1b1db0439504936c59"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"6f405fa705196c03e9f0554620e332d3584add2b","unresolved":false,"context_lines":[{"line_number":1570,"context_line":"            if aresp:"},{"line_number":1571,"context_line":"                return aresp"},{"line_number":1572,"context_line":""},{"line_number":1573,"context_line":"            if bytes_to_wsgi(segment_container.encode(\u0027utf-8\u0027)) !\u003d container:"},{"line_number":1574,"context_line":"                path \u003d \u0027/%s/%s/%s\u0027 % (vrs, account, bytes_to_wsgi("},{"line_number":1575,"context_line":"                    segment_container.encode(\u0027utf-8\u0027)))"},{"line_number":1576,"context_line":"                seg_container_info \u003d get_container_info("}],"source_content_type":"text/x-python","patch_set":9,"id":"9f560f44_705024d6","line":1573,"updated":"2020-09-24 22:21:24.000000000","message":"pep8: F821 undefined name \u0027bytes_to_wsgi\u0027","commit_id":"66b6b2376f0c909e7971953230baee38b760e657"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"6f405fa705196c03e9f0554620e332d3584add2b","unresolved":false,"context_lines":[{"line_number":1571,"context_line":"                return aresp"},{"line_number":1572,"context_line":""},{"line_number":1573,"context_line":"            if bytes_to_wsgi(segment_container.encode(\u0027utf-8\u0027)) !\u003d container:"},{"line_number":1574,"context_line":"                path \u003d \u0027/%s/%s/%s\u0027 % (vrs, account, bytes_to_wsgi("},{"line_number":1575,"context_line":"                    segment_container.encode(\u0027utf-8\u0027)))"},{"line_number":1576,"context_line":"                seg_container_info \u003d get_container_info("},{"line_number":1577,"context_line":"                    make_env(req.environ, path\u003dpath, swift_source\u003d\u0027SLO\u0027),"}],"source_content_type":"text/x-python","patch_set":9,"id":"9f560f44_504b6026","line":1574,"updated":"2020-09-24 22:21:24.000000000","message":"pep8: F821 undefined name \u0027bytes_to_wsgi\u0027","commit_id":"66b6b2376f0c909e7971953230baee38b760e657"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":1542,"context_line":"            obj_path \u003d (\u0027/%s/%s\u0027 % (container, obj)).decode(\u0027utf-8\u0027)"},{"line_number":1543,"context_line":"        else:"},{"line_number":1544,"context_line":"            obj_path \u003d \u0027/%s/%s\u0027 % (wsgi_to_str(container), wsgi_to_str(obj))"},{"line_number":1545,"context_line":"        segments \u003d [seg for seg in self.get_slo_segments(obj_path, req)"},{"line_number":1546,"context_line":"                    if \u0027data\u0027 not in seg]"},{"line_number":1547,"context_line":"        if not segments:"},{"line_number":1548,"context_line":"            # Degenerate case: just delete the manifest"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_63e94018","line":1545,"updated":"2020-09-29 15:49:21.000000000","message":"get_slo_segments is nice, prevents people playing games with async\u003don for some random json with objects that were never validated:\n\n\t\u003c HTTP/1.1 400 Bad Request\n\t\u003c Content-Length: 19\n\t\u003c Content-Type: text/html; charset\u003dUTF-8\n\t\u003c X-Trans-Id: tx29738cbdaeb34e658c1e7-005f72596a\n\t\u003c X-Openstack-Request-Id: tx29738cbdaeb34e658c1e7-005f72596a\n\t\u003c Date: Mon, 28 Sep 2020 21:45:14 GMT\n\t\u003c \n\t* Connection #0 to host saio left intact\n\tNot an SLO manifest","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":1543,"context_line":"        else:"},{"line_number":1544,"context_line":"            obj_path \u003d \u0027/%s/%s\u0027 % (wsgi_to_str(container), wsgi_to_str(obj))"},{"line_number":1545,"context_line":"        segments \u003d [seg for seg in self.get_slo_segments(obj_path, req)"},{"line_number":1546,"context_line":"                    if \u0027data\u0027 not in seg]"},{"line_number":1547,"context_line":"        if not segments:"},{"line_number":1548,"context_line":"            # Degenerate case: just delete the manifest"},{"line_number":1549,"context_line":"            return self.app"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_e3c6fd4a","line":1546,"updated":"2020-09-29 15:49:21.000000000","message":"there\u0027s some tiny overlap with get_segments_to_delete_iter (e.g. they both have code to filter data segments) - but mostly this is different...","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":1555,"context_line":"            container_csv \u003d \u0027, \u0027.join("},{"line_number":1556,"context_line":"                \u0027\"%s\"\u0027 % quote(c) for c in segment_containers)"},{"line_number":1557,"context_line":"            raise HTTPBadRequest(\u0027All segments must be in one container. \u0027"},{"line_number":1558,"context_line":"                                 \u0027Found segments in %s\u0027 % container_csv)"},{"line_number":1559,"context_line":"        if any(seg.get(\u0027sub_slo\u0027) for seg in segments):"},{"line_number":1560,"context_line":"            raise HTTPBadRequest(\u0027No segments may be large objects.\u0027)"},{"line_number":1561,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_639cad70","line":1558,"updated":"2020-09-29 15:49:21.000000000","message":"I like this:\n\n\t\u003c HTTP/1.1 400 Bad Request\n\t\u003c Content-Length: 91\n\t\u003c Content-Type: text/html; charset\u003dUTF-8\n\t\u003c X-Trans-Id: txa715b08799824133b8a14-005f72572a\n\t\u003c X-Openstack-Request-Id: txa715b08799824133b8a14-005f72572a\n\t\u003c Date: Mon, 28 Sep 2020 21:35:38 GMT\n\t\u003c \n\t* Connection #0 to host saio left intact\n\tAll segments must be in one container. Found segments in \"test_segments1\", \"test_segments2\"\n\n\nand of course dropping async\u003don works great:\n\n\t\u003e DELETE /v1/AUTH_test/test/manifest?multipart-manifest\u003ddelete HTTP/1.1\n\t\u003e Host: saio:8080\n\t\u003e User-Agent: curl/7.58.0\n\t\u003e Accept: */*\n\t\u003e x-auth-token: AUTH_tk616fc2b5d03c41a4a876900b8a42579d\n\t\u003e \n\t\u003c HTTP/1.1 200 OK\n\t\u003c Content-Type: text/plain\n\t\u003c X-Trans-Id: txca47c3a034d04952833dc-005f725741\n\t\u003c X-Openstack-Request-Id: txca47c3a034d04952833dc-005f725741\n\t\u003c Date: Mon, 28 Sep 2020 21:36:01 GMT\n\t\u003c Transfer-Encoding: chunked\n\t\u003c \n\tNumber Deleted: 3\n\tNumber Not Found: 0\n\tResponse Body: \n\tResponse Status: 200 OK\n\tErrors:","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":1557,"context_line":"            raise HTTPBadRequest(\u0027All segments must be in one container. \u0027"},{"line_number":1558,"context_line":"                                 \u0027Found segments in %s\u0027 % container_csv)"},{"line_number":1559,"context_line":"        if any(seg.get(\u0027sub_slo\u0027) for seg in segments):"},{"line_number":1560,"context_line":"            raise HTTPBadRequest(\u0027No segments may be large objects.\u0027)"},{"line_number":1561,"context_line":""},{"line_number":1562,"context_line":"        # Auth checks"},{"line_number":1563,"context_line":"        segment_container \u003d segment_containers.pop()"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_03f4c4cf","line":1560,"updated":"2020-09-29 15:49:21.000000000","message":"e.g. get_segments_to_delete_iter will traverse sub slo\u0027s - although it could potentially be useful to parameterize that behavior is SLOs that meet s3api conventions continue to grow differentiated behaviors from more complex SLO manifests.","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"3cee5ef8a04a790707c3fbad9965e500f41735f9","unresolved":false,"context_lines":[{"line_number":1602,"context_line":"                resp.status, resp.body)"},{"line_number":1603,"context_line":"            return HTTPServiceUnavailable()"},{"line_number":1604,"context_line":"        # consume the response (should be short)"},{"line_number":1605,"context_line":"        resp.body"},{"line_number":1606,"context_line":""},{"line_number":1607,"context_line":"        # Finally, delete the manifest"},{"line_number":1608,"context_line":"        return self.app"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_6bc11230","line":1605,"updated":"2020-09-30 00:38:47.000000000","message":"drain_and_close()?","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":1615,"context_line":"        :param req: a :class:`~swift.common.swob.Request` with an obj in path"},{"line_number":1616,"context_line":"        :returns: swob.Response whose app_iter set to Bulk.handle_delete_iter"},{"line_number":1617,"context_line":"        \"\"\""},{"line_number":1618,"context_line":"        if config_true_value(req.params.get(\u0027async\u0027)):"},{"line_number":1619,"context_line":"            return self.handle_async_delete(req)"},{"line_number":1620,"context_line":""},{"line_number":1621,"context_line":"        req.headers[\u0027Content-Type\u0027] \u003d None  # Ignore content-type from client"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_582ea742","line":1618,"updated":"2020-09-29 15:49:21.000000000","message":"if self.allow_async_delete and ...","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":1716,"context_line":"                        # this used to be configurable; report it as 1 for"},{"line_number":1717,"context_line":"                        # clients that might still care"},{"line_number":1718,"context_line":"                        min_segment_size\u003d1,"},{"line_number":1719,"context_line":"                        allow_async_delete\u003dTrue)"},{"line_number":1720,"context_line":""},{"line_number":1721,"context_line":"    def slo_filter(app):"},{"line_number":1722,"context_line":"        return StaticLargeObject("}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_00a4c74a","line":1719,"updated":"2020-09-29 15:49:21.000000000","message":"since this exposes a potential amplification vector it seems reasonable this feature could be opt-out","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"3cee5ef8a04a790707c3fbad9965e500f41735f9","unresolved":false,"context_lines":[{"line_number":1591,"context_line":"        enqueue_req \u003d make_pre_authed_request("},{"line_number":1592,"context_line":"            req.environ,"},{"line_number":1593,"context_line":"            method\u003d\u0027UPDATE\u0027,"},{"line_number":1594,"context_line":"            path\u003d\"/v1/%s/%d\" % (self.expiring_objects_account, int(ts)),"},{"line_number":1595,"context_line":"            body\u003djson.dumps(expirer_jobs),"},{"line_number":1596,"context_line":"            headers\u003d{\u0027Content-Type\u0027: \u0027application/json\u0027,"},{"line_number":1597,"context_line":"                     \u0027X-Backend-Storage-Policy-Index\u0027: \u00270\u0027,"}],"source_content_type":"text/x-python","patch_set":11,"id":"9f560f44_e1942339","line":1594,"range":{"start_line":1594,"start_character":63,"end_line":1594,"end_character":70},"updated":"2020-09-30 00:38:47.000000000","message":"I do wonder if this should use expiring_objects_container_divisor -- but maybe since it\u0027s getting scheduled for deletion *right now* it doesn\u0027t matter too much? The container should get deleted quickly enough...","commit_id":"049c5c2be5434725d3c2362c81e7ef5f42fb7b2f"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"ea37d26ca729d04c7f62f09f933629f62dcc2cf4","unresolved":false,"context_lines":[{"line_number":1591,"context_line":"        enqueue_req \u003d make_pre_authed_request("},{"line_number":1592,"context_line":"            req.environ,"},{"line_number":1593,"context_line":"            method\u003d\u0027UPDATE\u0027,"},{"line_number":1594,"context_line":"            path\u003d\"/v1/%s/%d\" % (self.expiring_objects_account, int(ts)),"},{"line_number":1595,"context_line":"            body\u003djson.dumps(expirer_jobs),"},{"line_number":1596,"context_line":"            headers\u003d{\u0027Content-Type\u0027: \u0027application/json\u0027,"},{"line_number":1597,"context_line":"                     \u0027X-Backend-Storage-Policy-Index\u0027: \u00270\u0027,"}],"source_content_type":"text/x-python","patch_set":14,"id":"3f65232a_ead9a8f4","line":1594,"range":{"start_line":1594,"start_character":63,"end_line":1594,"end_character":70},"updated":"2020-10-21 17:05:45.000000000","message":"Just want to call attention to this again; I\u0027m still torn about whether this ought to use expiring_objects_container_divisor ...","commit_id":"e93787c1ce17e00bd9bc1d406c90a9107766189d"}],"swift/obj/expirer.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":485,"context_line":"        path \u003d \u0027/v1/\u0027 + wsgi_quote(str_to_wsgi(actual_obj.lstrip(\u0027/\u0027)))"},{"line_number":486,"context_line":"        if is_async_delete:"},{"line_number":487,"context_line":"            headers \u003d {\u0027X-Timestamp\u0027: timestamp.normal}"},{"line_number":488,"context_line":"            acceptable_statuses \u003d (2, HTTP_CONFLICT, HTTP_NOT_FOUND)"},{"line_number":489,"context_line":"        else:"},{"line_number":490,"context_line":"            headers \u003d {\u0027X-Timestamp\u0027: timestamp.normal,"},{"line_number":491,"context_line":"                       \u0027X-If-Delete-At\u0027: timestamp.normal,"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_a3d88552","line":488,"updated":"2020-09-29 15:49:21.000000000","message":"I found the 409 here means if the object changed (i.e. reuploaded, newer timestamp) after the async\u003don DELETE was issued it would just NOT get deleted (assuming all primaries were online and in-sync; I\u0027m sure there\u0027s some failure mode that writes a tombstone somewhere and it IS deleted which questions the wisdom of returning 409 in the first place)\n\n404 here is great, it means the client can also handle cleanup if the expirer is running late","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0f055cd93488c309834f15e509439dc01d970bf2","unresolved":false,"context_lines":[{"line_number":485,"context_line":"        path \u003d \u0027/v1/\u0027 + wsgi_quote(str_to_wsgi(actual_obj.lstrip(\u0027/\u0027)))"},{"line_number":486,"context_line":"        if is_async_delete:"},{"line_number":487,"context_line":"            headers \u003d {\u0027X-Timestamp\u0027: timestamp.normal}"},{"line_number":488,"context_line":"            acceptable_statuses \u003d (2, HTTP_CONFLICT, HTTP_NOT_FOUND)"},{"line_number":489,"context_line":"        else:"},{"line_number":490,"context_line":"            headers \u003d {\u0027X-Timestamp\u0027: timestamp.normal,"},{"line_number":491,"context_line":"                       \u0027X-If-Delete-At\u0027: timestamp.normal,"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_75e29132","line":488,"in_reply_to":"9f560f44_a3d88552","updated":"2020-09-29 18:24:37.000000000","message":"If we write down a tombstone, it\u0027ll have the (high precision!) timestamp, so if there was an overwrite out on some handoff, we\u0027d compare timestamps, last write would win, and we get all the normal eventually-consistent behavior we\u0027ve come to expect.\n\nNote that today, on master, there are no checks that we\u0027re actually deleting the same data that was referenced in the manifest. If you create a manifest and overwrite one of the segments with different data, when you issue a ?multipart-manifest\u003ddelete request it\u0027s gonna get deleted.","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"}],"test/probe/test_object_expirer.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"be93467cdd7999504dfb650f3984618c3a01fd8e","unresolved":false,"context_lines":[{"line_number":371,"context_line":"        # But segments are still around and accessible"},{"line_number":372,"context_line":"        _, objects \u003d client.get_container(self.url, self.token,"},{"line_number":373,"context_line":"                                          segment_container)"},{"line_number":374,"context_line":"        self.assertEqual([o[\u0027name\u0027] for o in objects],"},{"line_number":375,"context_line":"                         [\u0027segment_1\u0027, \u0027segment_2\u0027])"},{"line_number":376,"context_line":"        _, body \u003d client.get_object(self.url, self.token,"},{"line_number":377,"context_line":"                                    segment_container, \u0027segment_1\u0027)"},{"line_number":378,"context_line":"        self.assertEqual(body, b\u00271234\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"ff570b3c_f06536b0","line":375,"range":{"start_line":374,"start_character":8,"end_line":375,"end_character":52},"updated":"2020-06-05 17:04:57.000000000","message":"Segments are still in listings.","commit_id":"b92ef95794d98898c6e4006a409af9b5a6951b8d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d732d0fdbbd9fa5372089b4f60eaaa764e8a5269","unresolved":false,"context_lines":[{"line_number":378,"context_line":"        self.assertEqual(body, b\u00271234\u0027)"},{"line_number":379,"context_line":"        _, body \u003d client.get_object(self.url, self.token,"},{"line_number":380,"context_line":"                                    segment_container, \u0027segment_2\u0027)"},{"line_number":381,"context_line":"        self.assertEqual(body, b\u00275678\u0027)"},{"line_number":382,"context_line":""},{"line_number":383,"context_line":"        # make sure auto-created expirer-queue containers get in the account"},{"line_number":384,"context_line":"        # listing so the expirer can find them"}],"source_content_type":"text/x-python","patch_set":3,"id":"ff570b3c_45a542b4","line":381,"updated":"2020-06-05 16:09:42.000000000","message":"I think this isn\u0027t great.  What\u0027s the listing look like?  What happens if the client overwrites these segments at this point?","commit_id":"b92ef95794d98898c6e4006a409af9b5a6951b8d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"be93467cdd7999504dfb650f3984618c3a01fd8e","unresolved":false,"context_lines":[{"line_number":378,"context_line":"        self.assertEqual(body, b\u00271234\u0027)"},{"line_number":379,"context_line":"        _, body \u003d client.get_object(self.url, self.token,"},{"line_number":380,"context_line":"                                    segment_container, \u0027segment_2\u0027)"},{"line_number":381,"context_line":"        self.assertEqual(body, b\u00275678\u0027)"},{"line_number":382,"context_line":""},{"line_number":383,"context_line":"        # make sure auto-created expirer-queue containers get in the account"},{"line_number":384,"context_line":"        # listing so the expirer can find them"}],"source_content_type":"text/x-python","patch_set":3,"id":"ff570b3c_90815afe","line":381,"in_reply_to":"ff570b3c_45a542b4","updated":"2020-06-05 17:04:57.000000000","message":"As long as you\u0027ve got low time skew between servers and some \"reasonable\" gap between the delete and the re-upload, it\u0027ll be fine. The deletes will still be scheduled, but for a timestamp that predates the new segment. So when the expirer comes around to it:\n\n* object-server responds 409,\n* expirer cleans up the queue, and \n* the segment data is still there, accessible and in listings.\n\nThat\u0027s part of why I got high-precision timestamps into the expirer queue -- I\u0027d see 409s on the DELETEs and the segments would still show up in listings down at line 391. I debated about just adding one to the delete timestamp, but then I got to worrying about someone issuing an async delete then turning around and overwriting the segments -- and I didn\u0027t want the scheduled delete to be able to delete the new data.","commit_id":"b92ef95794d98898c6e4006a409af9b5a6951b8d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":397,"context_line":"        with self.assertRaises(client.ClientException) as caught:"},{"line_number":398,"context_line":"            client.get_object(self.url, self.token,"},{"line_number":399,"context_line":"                              segment_container, \u0027segment_2\u0027)"},{"line_number":400,"context_line":"        self.assertEqual(404, caught.exception.http_status)"},{"line_number":401,"context_line":""},{"line_number":402,"context_line":""},{"line_number":403,"context_line":"if __name__ \u003d\u003d \"__main__\":"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_98ab1f87","line":400,"updated":"2020-09-29 15:49:21.000000000","message":"this probe test is really great; kudos","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"}],"test/unit/cli/test_container_deleter.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"03a449efe0d6eb5770c1b58eb13f68579885e9d1","unresolved":false,"context_lines":[{"line_number":70,"context_line":"            container_deleter.make_delete_jobs("},{"line_number":71,"context_line":"                \u0027acct\u0027, \u0027cont\u0027, [\u0027obj1\u0027, \u0027obj2\u0027],"},{"line_number":72,"context_line":"                utils.Timestamp(ts)),"},{"line_number":73,"context_line":"            [{\u0027name\u0027: ts.split(\u0027.\u0027)[0] + \u0027-acct/cont/obj1\u0027,"},{"line_number":74,"context_line":"              \u0027deleted\u0027: 0,"},{"line_number":75,"context_line":"              \u0027created_at\u0027: ts,"},{"line_number":76,"context_line":"              \u0027etag\u0027: utils.MD5_OF_EMPTY_STRING,"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff570b3c_06050d14","side":"PARENT","line":73,"range":{"start_line":73,"start_character":24,"end_line":73,"end_character":38},"updated":"2020-06-06 04:21:24.000000000","message":"In retrospect, this should always have been a little suspect.","commit_id":"4f440ad44d16fcc51dd060ca7040e3ed5c7b7483"}],"test/unit/common/middleware/helpers.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"a9f4e36107e5a07c1a41b0f81669d47483e4d0e8","unresolved":false,"context_lines":[{"line_number":46,"context_line":"        self.mark_closed(self.key)"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"FakeSwiftCall \u003d namedtuple(\u0027FakeSwiftCall\u0027, [\u0027method\u0027, \u0027path\u0027, \u0027headers\u0027, \u0027body\u0027])"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"def normalize_query_string(qs):"}],"source_content_type":"text/x-python","patch_set":6,"id":"9f560f44_3afba647","line":49,"updated":"2020-09-17 21:51:02.000000000","message":"pep8: E501 line too long (82 \u003e 79 characters)","commit_id":"e18cb01e02f7196e9e3314fd02e03c9138c8f501"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":142,"context_line":"                    (method, path),))"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"        req_body \u003d b\u0027\u0027.join(iter(env[\u0027wsgi.input\u0027].read, b\u0027\u0027)) \\"},{"line_number":145,"context_line":"            if method in (\u0027PUT\u0027, \u0027UPDATE\u0027) else None"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":"        # simulate object PUT"},{"line_number":148,"context_line":"        if method \u003d\u003d \u0027PUT\u0027 and obj:"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_a3ab5886","line":145,"updated":"2020-09-29 15:49:21.000000000","message":"perhaps it\u0027s reasonable for tests to require env[\u0027wsgi.input\u0027] to not be None for container PUT requests\n\nI\u0027m seeing a TypeError here when wsgi.input is an \"UnreadableBody\"","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0f055cd93488c309834f15e509439dc01d970bf2","unresolved":false,"context_lines":[{"line_number":142,"context_line":"                    (method, path),))"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"        req_body \u003d b\u0027\u0027.join(iter(env[\u0027wsgi.input\u0027].read, b\u0027\u0027)) \\"},{"line_number":145,"context_line":"            if method in (\u0027PUT\u0027, \u0027UPDATE\u0027) else None"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":"        # simulate object PUT"},{"line_number":148,"context_line":"        if method \u003d\u003d \u0027PUT\u0027 and obj:"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_156235da","line":145,"in_reply_to":"9f560f44_a3ab5886","updated":"2020-09-29 18:24:37.000000000","message":"Maybe I should do something like\n\n req_body \u003d None\n if (method \u003d\u003d \u0027UPDATE\u0027 and cont and not obj) or (\n         method \u003d\u003d \u0027PUT\u0027 and obj):\n     req_body \u003d b\u0027\u0027.join(iter(env[\u0027wsgi.input\u0027].read, b\u0027\u0027))\n\nIIRC, those are the only two cases down in the proxy-server app that we actually read wsgi.input; otherwise, we punt to eventlet to discard() any body that might be present before moving on to the next request in the pipeline.","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"}],"test/unit/common/middleware/s3api/test_obj.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":1546,"context_line":"        self.assertIn((\u0027DELETE\u0027, \u0027/v1/AUTH_test/bucket/object\u0027"},{"line_number":1547,"context_line":"                                 \u0027?async\u003don\u0026multipart-manifest\u003ddelete\u0027),"},{"line_number":1548,"context_line":"                      self.swift.calls)"},{"line_number":1549,"context_line":"        _, path, headers \u003d self.swift.calls_with_headers[-1]"},{"line_number":1550,"context_line":"        path, query_string \u003d path.split(\u0027?\u0027, 1)"},{"line_number":1551,"context_line":"        query \u003d {}"},{"line_number":1552,"context_line":"        for q in query_string.split(\u0027\u0026\u0027):"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_b868a3f4","line":1549,"updated":"2020-09-29 15:49:21.000000000","message":"the @s3acl helper makes it harder to make direct assertions about swift.calls; but the s3acl decorator makes it harder to make direct assertions about all of swift.calls; but assertIn might still be unnecessarily weak","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":1551,"context_line":"        query \u003d {}"},{"line_number":1552,"context_line":"        for q in query_string.split(\u0027\u0026\u0027):"},{"line_number":1553,"context_line":"            key, arg \u003d q.split(\u0027\u003d\u0027)"},{"line_number":1554,"context_line":"            query[key] \u003d arg"},{"line_number":1555,"context_line":"        self.assertEqual(query[\u0027multipart-manifest\u0027], \u0027delete\u0027)"},{"line_number":1556,"context_line":"        self.assertEqual(query[\u0027async\u0027], \u0027on\u0027)"},{"line_number":1557,"context_line":"        self.assertNotIn(\u0027Content-Type\u0027, headers)"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_38a77353","line":1554,"updated":"2020-09-29 15:49:21.000000000","message":"I always have a hard time remembering where all of these moves are at in six:\n\n\tdiff --git a/test/unit/common/middleware/s3api/test_obj.py b/test/unit/common/middleware/s3api/test_obj.py\n\tindex 856992566..a756c2f5d 100644\n\t--- a/test/unit/common/middleware/s3api/test_obj.py\n\t+++ b/test/unit/common/middleware/s3api/test_obj.py\n\t@@ -22,6 +22,7 @@ from os.path import join\n\t import time\n\t from mock import patch\n\t import six\n\t+from six.moves.urllib.parse import urlparse, parse_qsl\n\t import json\n\t \n\t from swift.common import swob\n\t@@ -1543,15 +1544,12 @@ class TestS3ApiObj(S3ApiTestCase):\n\t \n\t\t self.assertIn((\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket/object?symlink\u003dget\u0027),\n\t\t\t       self.swift.calls)\n\t-        self.assertIn((\u0027DELETE\u0027, \u0027/v1/AUTH_test/bucket/object\u0027\n\t-                                 \u0027?async\u003don\u0026multipart-manifest\u003ddelete\u0027),\n\t-                      self.swift.calls)\n\t-        _, path, headers \u003d self.swift.calls_with_headers[-1]\n\t-        path, query_string \u003d path.split(\u0027?\u0027, 1)\n\t-        query \u003d {}\n\t-        for q in query_string.split(\u0027\u0026\u0027):\n\t-            key, arg \u003d q.split(\u0027\u003d\u0027)\n\t-            query[key] \u003d arg\n\t+        self.assertEqual((\u0027DELETE\u0027, \u0027/v1/AUTH_test/bucket/object\u0027\n\t+                          \u0027?async\u003don\u0026multipart-manifest\u003ddelete\u0027),\n\t+                         self.swift.calls[-1])\n\t+        method, path, headers \u003d self.swift.calls_with_headers[-1]\n\t+        self.assertEqual(method, \u0027DELETE\u0027)\n\t+        query \u003d dict(parse_qsl(urlparse(path).query))\n\t\t self.assertEqual(query[\u0027multipart-manifest\u0027], \u0027delete\u0027)\n\t\t self.assertEqual(query[\u0027async\u0027], \u0027on\u0027)\n\t\t self.assertNotIn(\u0027Content-Type\u0027, headers)\n\n\n\n... but it\u0027s probably better to use them","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"}],"test/unit/common/middleware/test_slo.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"6b81411db24e0ddbfdbabd9b54a7a8f12bf23f1c","unresolved":false,"context_lines":[{"line_number":1547,"context_line":"             \u0027/v1/AUTH_test/deltest/man-all-there?multipart-manifest\u003dget\u0027),"},{"line_number":1548,"context_line":"            (\u0027UPDATE\u0027, \u0027/v1/.expiring_objects/...\u0027),"},{"line_number":1549,"context_line":"            (\u0027DELETE\u0027, (\u0027/v1/AUTH_test/deltest/man-all-there\u0027))]))"},{"line_number":1550,"context_line":"        #TODO: check the UPDATE payload"},{"line_number":1551,"context_line":""},{"line_number":1552,"context_line":"    def test_handle_async_delete_non_ascii(self):"},{"line_number":1553,"context_line":"        if six.PY2:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_848559b1","line":1550,"updated":"2020-09-16 17:50:01.000000000","message":"pep8: E265 block comment should start with \u0027# \u0027","commit_id":"16b633eab48fe56ad02653508f4910ba13ff0d27"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"6b81411db24e0ddbfdbabd9b54a7a8f12bf23f1c","unresolved":false,"context_lines":[{"line_number":1555,"context_line":"        else:"},{"line_number":1556,"context_line":"            acct \u003d str_to_wsgi(u\u0027AUTH_test-un\\u00efcode\u0027)"},{"line_number":1557,"context_line":"        req \u003d Request.blank("},{"line_number":1558,"context_line":"            \u0027/v1/%s/deltest/man-all-there?async\u003d1\u0026multipart-manifest\u003ddelete\u0027 % acct,"},{"line_number":1559,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027DELETE\u0027})"},{"line_number":1560,"context_line":"        status, _, body \u003d self.call_slo(req)"},{"line_number":1561,"context_line":"        self.assertEqual(\u0027200 OK\u0027, status)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_6482c5a7","line":1558,"updated":"2020-09-16 17:50:01.000000000","message":"pep8: E501 line too long (84 \u003e 79 characters)","commit_id":"16b633eab48fe56ad02653508f4910ba13ff0d27"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"6b81411db24e0ddbfdbabd9b54a7a8f12bf23f1c","unresolved":false,"context_lines":[{"line_number":1576,"context_line":"            (\u0027DELETE\u0027, \u0027/v1/%s/deltest/c_3\u0027 % acct),"},{"line_number":1577,"context_line":"            (\u0027DELETE\u0027, (\u0027/v1/%s/deltest/man-all-there\u0027 % acct))]))"},{"line_number":1578,"context_line":""},{"line_number":1579,"context_line":"    def test_handle_multipart_delete_nested(self):"},{"line_number":1580,"context_line":"        req \u003d Request.blank("},{"line_number":1581,"context_line":"            \u0027/v1/AUTH_test/deltest/manifest-with-submanifest\u0027 +"},{"line_number":1582,"context_line":"            \u0027?async\u003don\u0026multipart-manifest\u003ddelete\u0027,"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_c48f51cb","line":1579,"updated":"2020-09-16 17:50:01.000000000","message":"pep8: F811 redefinition of unused \u0027test_handle_multipart_delete_nested\u0027 from line 1359","commit_id":"16b633eab48fe56ad02653508f4910ba13ff0d27"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"a9f4e36107e5a07c1a41b0f81669d47483e4d0e8","unresolved":false,"context_lines":[{"line_number":28,"context_line":"from swift.common import swob, utils"},{"line_number":29,"context_line":"from swift.common.header_key_dict import HeaderKeyDict"},{"line_number":30,"context_line":"from swift.common.middleware import slo"},{"line_number":31,"context_line":"from swift.common.swob import Request, HTTPException, str_to_wsgi, bytes_to_wsgi"},{"line_number":32,"context_line":"from swift.common.utils import quote, closing_if_possible, close_if_possible, \\"},{"line_number":33,"context_line":"    parse_content_type, iter_multipart_mime_documents, parse_mime_headers, \\"},{"line_number":34,"context_line":"    Timestamp"}],"source_content_type":"text/x-python","patch_set":6,"id":"9f560f44_1af6a25e","line":31,"updated":"2020-09-17 21:51:02.000000000","message":"pep8: E501 line too long (80 \u003e 79 characters)","commit_id":"e18cb01e02f7196e9e3314fd02e03c9138c8f501"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"a9f4e36107e5a07c1a41b0f81669d47483e4d0e8","unresolved":false,"context_lines":[{"line_number":1605,"context_line":""},{"line_number":1606,"context_line":"        self.assertEqual(self.app.calls, ["},{"line_number":1607,"context_line":"            (\u0027GET\u0027,"},{"line_number":1608,"context_line":"             \u0027/v1/%s/deltest/man-all-there?multipart-manifest\u003dget\u0027 % wsgi_acct),"},{"line_number":1609,"context_line":"            (\u0027UPDATE\u0027, \u0027/v1/.expiring_objects/%d\u0027"},{"line_number":1610,"context_line":"                       \u0027?async\u003d1\u0026heartbeat\u003d1\u0026multipart-manifest\u003ddelete\u0027 % int(now)),"},{"line_number":1611,"context_line":"            (\u0027DELETE\u0027, \u0027/v1/%s/deltest/man-all-there\u0027"}],"source_content_type":"text/x-python","patch_set":6,"id":"9f560f44_7a923efe","line":1608,"updated":"2020-09-17 21:51:02.000000000","message":"pep8: E501 line too long (80 \u003e 79 characters)","commit_id":"e18cb01e02f7196e9e3314fd02e03c9138c8f501"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"a9f4e36107e5a07c1a41b0f81669d47483e4d0e8","unresolved":false,"context_lines":[{"line_number":1607,"context_line":"            (\u0027GET\u0027,"},{"line_number":1608,"context_line":"             \u0027/v1/%s/deltest/man-all-there?multipart-manifest\u003dget\u0027 % wsgi_acct),"},{"line_number":1609,"context_line":"            (\u0027UPDATE\u0027, \u0027/v1/.expiring_objects/%d\u0027"},{"line_number":1610,"context_line":"                       \u0027?async\u003d1\u0026heartbeat\u003d1\u0026multipart-manifest\u003ddelete\u0027 % int(now)),"},{"line_number":1611,"context_line":"            (\u0027DELETE\u0027, \u0027/v1/%s/deltest/man-all-there\u0027"},{"line_number":1612,"context_line":"                       \u0027?async\u003d1\u0026heartbeat\u003d1\u0026multipart-manifest\u003ddelete\u0027 % wsgi_acct),"},{"line_number":1613,"context_line":"        ])"}],"source_content_type":"text/x-python","patch_set":6,"id":"9f560f44_5a95bae2","line":1610,"updated":"2020-09-17 21:51:02.000000000","message":"pep8: E501 line too long (84 \u003e 79 characters)","commit_id":"e18cb01e02f7196e9e3314fd02e03c9138c8f501"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"a9f4e36107e5a07c1a41b0f81669d47483e4d0e8","unresolved":false,"context_lines":[{"line_number":1609,"context_line":"            (\u0027UPDATE\u0027, \u0027/v1/.expiring_objects/%d\u0027"},{"line_number":1610,"context_line":"                       \u0027?async\u003d1\u0026heartbeat\u003d1\u0026multipart-manifest\u003ddelete\u0027 % int(now)),"},{"line_number":1611,"context_line":"            (\u0027DELETE\u0027, \u0027/v1/%s/deltest/man-all-there\u0027"},{"line_number":1612,"context_line":"                       \u0027?async\u003d1\u0026heartbeat\u003d1\u0026multipart-manifest\u003ddelete\u0027 % wsgi_acct),"},{"line_number":1613,"context_line":"        ])"},{"line_number":1614,"context_line":""},{"line_number":1615,"context_line":"        for header, expected in ("}],"source_content_type":"text/x-python","patch_set":6,"id":"9f560f44_ba9cd60e","line":1612,"updated":"2020-09-17 21:51:02.000000000","message":"pep8: E501 line too long (85 \u003e 79 characters)","commit_id":"e18cb01e02f7196e9e3314fd02e03c9138c8f501"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"bee389013936ed55f5ef3c70fe2768a916b6b679","unresolved":false,"context_lines":[{"line_number":1781,"context_line":"        self.assertEqual(self.app.calls, ["},{"line_number":1782,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/deltest/\u0027 +"},{"line_number":1783,"context_line":"             \u0027manifest-with-submanifest?multipart-manifest\u003dget\u0027)])"},{"line_number":1784,"context_line":""},{"line_number":1785,"context_line":""},{"line_number":1786,"context_line":"class TestSloHeadOldManifest(SloTestCase):"},{"line_number":1787,"context_line":"    slo_etag \u003d md5hex(\"seg01-hashseg02-hash\")"}],"source_content_type":"text/x-python","patch_set":11,"id":"9f560f44_873996a4","line":1784,"updated":"2020-10-07 06:14:33.000000000","message":"One of the no no\u0027s was to not be able to async deletes where segments came from more then 1 container, do we have a test for that? or maybe I just missed it.","commit_id":"049c5c2be5434725d3c2362c81e7ef5f42fb7b2f"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4c046bcce6f1a16def007e4454b38e28bd970d4f","unresolved":false,"context_lines":[{"line_number":1781,"context_line":"        self.assertEqual(self.app.calls, ["},{"line_number":1782,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/deltest/\u0027 +"},{"line_number":1783,"context_line":"             \u0027manifest-with-submanifest?multipart-manifest\u003dget\u0027)])"},{"line_number":1784,"context_line":""},{"line_number":1785,"context_line":""},{"line_number":1786,"context_line":"class TestSloHeadOldManifest(SloTestCase):"},{"line_number":1787,"context_line":"    slo_etag \u003d md5hex(\"seg01-hashseg02-hash\")"}],"source_content_type":"text/x-python","patch_set":11,"id":"9f560f44_06b9e814","line":1784,"in_reply_to":"9f560f44_873996a4","updated":"2020-10-08 19:33:59.000000000","message":"Done","commit_id":"049c5c2be5434725d3c2362c81e7ef5f42fb7b2f"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"03a449efe0d6eb5770c1b58eb13f68579885e9d1","unresolved":false,"context_lines":[{"line_number":1216,"context_line":"        self.assertEqual("},{"line_number":1217,"context_line":"            utils.normalize_delete_at_timestamp(\u002771253327593.67890\u0027),"},{"line_number":1218,"context_line":"            \u00279999999999\u0027)"},{"line_number":1219,"context_line":"        self.assertRaises(ValueError, utils.normalize_timestamp, \u0027\u0027)"},{"line_number":1220,"context_line":"        self.assertRaises(ValueError, utils.normalize_timestamp, \u0027abc\u0027)"},{"line_number":1221,"context_line":""},{"line_number":1222,"context_line":"    def test_last_modified_date_to_timestamp(self):"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff570b3c_1903b20e","side":"PARENT","line":1219,"range":{"start_line":1219,"start_character":44,"end_line":1219,"end_character":63},"updated":"2020-06-06 04:21:24.000000000","message":"Hey, wait, that wasn\u0027t what we were supposed to be testing!","commit_id":"4f440ad44d16fcc51dd060ca7040e3ed5c7b7483"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":1265,"context_line":"        with self.assertRaises(ValueError):"},{"line_number":1266,"context_line":"            utils.normalize_delete_at_timestamp(\u0027\u0027, True)"},{"line_number":1267,"context_line":"        with self.assertRaises(ValueError):"},{"line_number":1268,"context_line":"            utils.normalize_delete_at_timestamp(\u0027abc\u0027, True)"},{"line_number":1269,"context_line":""},{"line_number":1270,"context_line":"    def test_last_modified_date_to_timestamp(self):"},{"line_number":1271,"context_line":"        expectations \u003d {"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_983b1fe9","line":1268,"updated":"2020-09-29 15:49:21.000000000","message":"quite nice","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"}],"test/unit/obj/test_expirer.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"4e2f5d1298abe2c38cd4e63493f9f46bd57c3d7c","unresolved":false,"context_lines":[{"line_number":1013,"context_line":"        ts \u003d Timestamp(next(self.ts), delta\u003d1234)"},{"line_number":1014,"context_line":"        a \u003d u\u0027\\N{SNOWMAN}\u0027"},{"line_number":1015,"context_line":"        c \u003d u\u0027\\N{SNOWFLAKE}\u0027"},{"line_number":1016,"context_line":"        o \u003d u\u0027\\N{PALM TREE}\u0027"},{"line_number":1017,"context_line":"        args \u003d (ts, a, c, o)"},{"line_number":1018,"context_line":"        self.assertNotEqual(args, expirer.parse_task_obj("},{"line_number":1019,"context_line":"            expirer.build_task_obj(ts, a, c, o)))"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff570b3c_99d8627f","line":1016,"updated":"2020-06-06 05:08:12.000000000","message":"pep8: E999 SyntaxError: (unicode error) \u0027unicodeescape\u0027 codec can\u0027t decode bytes in position 0-12: unknown Unicode character name","commit_id":"cc18bf2b53ac984410477eec98f163ab2033de07"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a2e86b349bf6041f6de06d0daabfbf17b772a937","unresolved":false,"context_lines":[{"line_number":1013,"context_line":"        ts \u003d Timestamp(next(self.ts), delta\u003d1234)"},{"line_number":1014,"context_line":"        a \u003d u\u0027\\N{SNOWMAN}\u0027"},{"line_number":1015,"context_line":"        c \u003d u\u0027\\N{SNOWFLAKE}\u0027"},{"line_number":1016,"context_line":"        o \u003d u\u0027\\N{PALM TREE}\u0027"},{"line_number":1017,"context_line":"        args \u003d (ts, a, c, o)"},{"line_number":1018,"context_line":"        self.assertNotEqual(args, expirer.parse_task_obj("},{"line_number":1019,"context_line":"            expirer.build_task_obj(ts, a, c, o)))"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f560f44_da73ab15","line":1016,"in_reply_to":"ff570b3c_99d8627f","updated":"2020-09-16 15:13:20.000000000","message":"Done","commit_id":"cc18bf2b53ac984410477eec98f163ab2033de07"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05350a1afb6318f6ca7d56646e53651cec01f99a","unresolved":false,"context_lines":[{"line_number":1018,"context_line":"        self.assertNotEqual(args, expirer.parse_task_obj("},{"line_number":1019,"context_line":"            expirer.build_task_obj(ts, a, c, o)))"},{"line_number":1020,"context_line":"        self.assertEqual(args, expirer.parse_task_obj("},{"line_number":1021,"context_line":"            expirer.build_task_obj(ts, a, c, o, high_precision\u003dTrue)))"},{"line_number":1022,"context_line":""},{"line_number":1023,"context_line":""},{"line_number":1024,"context_line":"if __name__ \u003d\u003d \u0027__main__\u0027:"}],"source_content_type":"text/x-python","patch_set":10,"id":"9f560f44_581a277c","line":1021,"updated":"2020-09-29 15:49:21.000000000","message":"i love these little tests for the util changes; thank you","commit_id":"493e7465fffe8ae33a3bdd108cec241b65bcd886"}]}
