)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"1f3ab8f006c898a48b7133e6b651a2ef4cfe5b7c","unresolved":true,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"We want to 405 on a HEAD request with query-parms?multipart-manifest\u003dget\u0026format\u003draw instead of giving a 500 InternalError"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Change-Id: I741db43c6e02276d58be4261f0e46677b6bb534a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"3646c045_d351ab9e","line":11,"updated":"2023-08-01 21:28:15.000000000","message":"we\u0027ll want to update the commit to include Closes-Bug: #2029174","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"34549bdcbc9ecb5a71d0560b9b2d03740ac6a23d","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"We want to 405 on a HEAD request with query-parms?multipart-manifest\u003dget\u0026format\u003draw instead of giving a 500 InternalError"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Change-Id: I741db43c6e02276d58be4261f0e46677b6bb534a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"31510a2a_27f9503a","line":11,"in_reply_to":"17a2796a_7e5a11e7","updated":"2023-08-18 22:05:22.000000000","message":"Done","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"We want to 405 on a HEAD request with query-parms?multipart-manifest\u003dget\u0026format\u003draw instead of giving a 500 InternalError"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Change-Id: I741db43c6e02276d58be4261f0e46677b6bb534a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"aefd8d27_e2ad541e","line":11,"in_reply_to":"17a2796a_7e5a11e7","updated":"2023-08-21 14:20:07.000000000","message":"Done","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"1355c2173febca3b1c662489f19d0561147a58d0","unresolved":true,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"We want to 405 on a HEAD request with query-parms?multipart-manifest\u003dget\u0026format\u003draw instead of giving a 500 InternalError"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Change-Id: I741db43c6e02276d58be4261f0e46677b6bb534a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"17a2796a_7e5a11e7","line":11,"in_reply_to":"3646c045_d351ab9e","updated":"2023-08-18 17:54:34.000000000","message":"i did\u0027nt do this yet","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"96e8243ad004abbe36a480c5deec83555860abc4","unresolved":true,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"fix head request on multipart-manifest raw format"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"We want to 405 on a HEAD request with query-parms?multipart-manifest\u003dget\u0026format\u003draw instead of giving a 500 InternalError"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Change-Id: I741db43c6e02276d58be4261f0e46677b6bb534a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"9fc19a97_5987a5a7","line":9,"updated":"2023-08-04 22:00:49.000000000","message":"Hey, it\u0027s not even the only way I can make `format\u003draw` trip a 500!\n```\nvagrant@saio:/vagrant/swift$ curl http://saio:8090/v1/AUTH_test/c/tox.ini?multipart-manifest\u003dget -H Range:bytes\u003d2-7 ; echo\n\"name\"\nvagrant@saio:/vagrant/swift$ curl http://saio:8090/v1/AUTH_test/c/tox.ini?multipart-manifest\u003dget\\\u0026format\u003draw -H Range:bytes\u003d2-7 ; echo\nAn error occurred\nvagrant@saio:/vagrant/swift$ tail /var/log/syslog | sed \u0027/raceback/!d;s/#012/\\n/g\u0027\nAug  4 21:40:53 saio proxy-server: Error: An error occurred: \nTraceback (most recent call last):\n  File \"/vagrant/swift/swift/common/middleware/catch_errors.py\", line 75, in handle_request\n    resp \u003d self._app_call(env)\n  File \"/vagrant/swift/swift/common/wsgi.py\", line 1112, in _app_call\n    resp \u003d self.app(env, self._start_response)\n  File \"/vagrant/swift/swift/common/middleware/gatekeeper.py\", line 129, in __call__\n    return self.app(env, gatekeeper_response)\n  File \"/vagrant/swift/swift/common/middleware/healthcheck.py\", line 52, in __call__\n    return self.app(env, start_response)\n  File \"/vagrant/swift/swift/common/middleware/proxy_logging.py\", line 458, in __call__\n    iterable \u003d self.app(env, my_start_response)\n  File \"/vagrant/swift/swift/common/middleware/copy.py\", line 253, in __call__\n    return self.app(env, start_response)\n  File \"/vagrant/swift/swift/common/middleware/memcache.py\", line 32, in __call__\n    return self.app(env, start_response)\n  File \"/vagrant/swift/swift/common/middleware/listing_formats.py\", line 157, in __call__\n    return self.app(env, start_response)\n  File \"/vagrant/swift/swift/common/middleware/list_endpoints.py\", line 200, in __call__\n    return self.app(env, start_response)\n  File \"/vagrant/swift/swift/common/swob.py\", line 1576, in _wsgify\n    return func(*new_args)(env, start_response)\n  File \"/vagrant/swift/swift/common/middleware/tempurl.py\", line 502, in __call__\n    return self.app(env, start_response)\n  File \"/vagrant/swift/swift/common/middleware/slo.py\", line 1711, in __call__\n    return self.handle_multipart_get_or_head(req, start_response)\n  File \"/vagrant/swift/swift/common/middleware/slo.py\", line 1154, in handle_multipart_get_or_head\n    return SloGetContext(self).handle_slo_get_or_head(req, start_response)\n  File \"/vagrant/swift/swift/common/middleware/slo.py\", line 816, in handle_slo_get_or_head\n    resp_iter \u003d self.convert_segment_listing(\n  File \"/vagrant/swift/swift/common/middleware/slo.py\", line 914, in convert_segment_listing\n    seg_dict.pop(\u0027content_type\u0027, None)\nAttributeError: \u0027str\u0027 object has no attribute \u0027pop\u0027 (txn: txd56e968a26a4452a9c5f4-0064cd7065) (client_ip: 127.0.0.1)\n```","commit_id":"9c7ae6b98df4d6cd15ff21d52cf32f05db6f4756"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"1355c2173febca3b1c662489f19d0561147a58d0","unresolved":true,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"fix head request on multipart-manifest raw format"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"We want to 405 on a HEAD request with query-parms?multipart-manifest\u003dget\u0026format\u003draw instead of giving a 500 InternalError"},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Change-Id: I741db43c6e02276d58be4261f0e46677b6bb534a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"9b9dcef3_7955a50b","line":9,"in_reply_to":"9fc19a97_5987a5a7","updated":"2023-08-18 17:54:34.000000000","message":"oh, that might be worth another func test!?","commit_id":"9c7ae6b98df4d6cd15ff21d52cf32f05db6f4756"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"1f3ab8f006c898a48b7133e6b651a2ef4cfe5b7c","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"3f70a7a5_42237f70","updated":"2023-08-01 21:28:15.000000000","message":"isn\u0027t there some unittests that do GET ?format\u003draw, you could also add a HEAD ?format\u003draw unittest; then it would make more sense stacked on top of your FakeSwift change.","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"96e8243ad004abbe36a480c5deec83555860abc4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"150c521e_4283fe0c","updated":"2023-08-04 22:00:49.000000000","message":"py2 func test failures are legit. I\u0027m not sold on the 405; it\u0027s not clear to me why we would do that instead of just 204 and drop some headers (all the while questioning why anyone would make this request, instead of doing the HEAD without the `format\u003draw`).","commit_id":"9c7ae6b98df4d6cd15ff21d52cf32f05db6f4756"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3103e1fdf98e37dfa279e4eb4f3b6db7dcc438b7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"e73f667e_30e32a4c","updated":"2023-08-18 19:03:10.000000000","message":"#willfix","commit_id":"495fa24dce43108b5f49416e873dedc4ee04a307"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8d563af5f537b6692999c01d9167d2b10bb47a8f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"108f8af6_f7693965","updated":"2023-08-21 12:06:12.000000000","message":"I think this makes sense, but I\u0027m unclear whether there\u0027s actually another bug being fixed as a side-effect. Also not clear if all the negative comments/concerns have been addressed. So just +1 for now.","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"45c01937_ed14526a","updated":"2023-08-21 14:20:07.000000000","message":"I\u0027m not to emotionally attached to this change; I was interested in the \"refetch_manifest\" behavior because we\u0027re going to need it for part-number queries\n\ndepending on how far we want to go on fixing these bugs and writing tests we may end up squashing in the accept-ranges: bytes fixes for completeness and sanity\n\nBesides accidently fixing another undiscovered issue I\u0027m not sure (yet) if this change is incomplete on it\u0027s own - I think it DOES close the associated 500 bug and may not make it significantly harder to continue to improve swift (the now incomplete comment in _need_to_refetch_manifest might be reason enough to respin)","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d45a9b34c6ae7b75d70e303d7ea09f1d89e4c975","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"05045133_463ba81d","updated":"2023-08-21 20:20:47.000000000","message":"`_refetch_manifest` should do more to ensure that what was refetched really *is* a manifest -- we\u0027re by no means guaranteed that it will be.","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":11,"id":"7707d3bb_06d741aa","updated":"2023-08-31 18:30:43.000000000","message":"I definatley have a better understanding of the SLO behaviors having gone through this, but I\u0027m not feeling 100% done with this refactor.\n\nI also think we should pull as much of the refactoring and polish out ahead of the HEAD?format\u003draw fix, even tho the \"conslidate all _refetch to one place\" may not seem as obviously valuable until we have to add the new \"HEAD \u0026 format\u003draw\" case.","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"}],"swift/common/middleware/slo.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"1f3ab8f006c898a48b7133e6b651a2ef4cfe5b7c","unresolved":true,"context_lines":[{"line_number":815,"context_line":"            if req.params.get(\u0027format\u0027) \u003d\u003d \u0027raw\u0027:"},{"line_number":816,"context_line":"                if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":817,"context_line":"                    raise HTTPMethodNotAllowed(\u0027Multipart Manifest on raw \u0027"},{"line_number":818,"context_line":"                                               \u0027formats can only be GETs\u0027)"},{"line_number":819,"context_line":"                resp_iter \u003d self.convert_segment_listing("},{"line_number":820,"context_line":"                    self._response_headers, resp_iter)"},{"line_number":821,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":2,"id":"bbcb01de_56d7e5e9","line":818,"updated":"2023-08-01 21:28:15.000000000","message":"I don\u0027t remember the HTTP semantics exactly, 405 might mean you can\u0027t do that method on this resource AT ALL not just you can\u0027t do that method with on this path with those query params.  Some kind of 4xx is good, if we just said \"invalid arg: format\u003draw\" that\u0027s not clear that it would work on GET either.\n\nit\u0027s tricky designing APIs, see if you can get some feedback from Tim","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3103e1fdf98e37dfa279e4eb4f3b6db7dcc438b7","unresolved":true,"context_lines":[{"line_number":815,"context_line":"            if req.params.get(\u0027format\u0027) \u003d\u003d \u0027raw\u0027:"},{"line_number":816,"context_line":"                if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":817,"context_line":"                    raise HTTPMethodNotAllowed(\u0027Multipart Manifest on raw \u0027"},{"line_number":818,"context_line":"                                               \u0027formats can only be GETs\u0027)"},{"line_number":819,"context_line":"                resp_iter \u003d self.convert_segment_listing("},{"line_number":820,"context_line":"                    self._response_headers, resp_iter)"},{"line_number":821,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":2,"id":"db644d8d_9d8a6d31","line":818,"in_reply_to":"25ab58b0_7a323963","updated":"2023-08-18 19:03:10.000000000","message":"oh, I missed this - are you *opposed* to doing the reGET?  we need to reGET on HEAD ?part-num\u003dX, well... \"need\" might be a little strong, s3api may find it easier to stay consistent with s3 responses if SLO always returns the same stuff.","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":false,"context_lines":[{"line_number":815,"context_line":"            if req.params.get(\u0027format\u0027) \u003d\u003d \u0027raw\u0027:"},{"line_number":816,"context_line":"                if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":817,"context_line":"                    raise HTTPMethodNotAllowed(\u0027Multipart Manifest on raw \u0027"},{"line_number":818,"context_line":"                                               \u0027formats can only be GETs\u0027)"},{"line_number":819,"context_line":"                resp_iter \u003d self.convert_segment_listing("},{"line_number":820,"context_line":"                    self._response_headers, resp_iter)"},{"line_number":821,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":2,"id":"c8826acf_9f544641","line":818,"in_reply_to":"320b4ac1_d0d36e48","updated":"2023-08-31 18:30:43.000000000","message":"Done","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"96e8243ad004abbe36a480c5deec83555860abc4","unresolved":true,"context_lines":[{"line_number":815,"context_line":"            if req.params.get(\u0027format\u0027) \u003d\u003d \u0027raw\u0027:"},{"line_number":816,"context_line":"                if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":817,"context_line":"                    raise HTTPMethodNotAllowed(\u0027Multipart Manifest on raw \u0027"},{"line_number":818,"context_line":"                                               \u0027formats can only be GETs\u0027)"},{"line_number":819,"context_line":"                resp_iter \u003d self.convert_segment_listing("},{"line_number":820,"context_line":"                    self._response_headers, resp_iter)"},{"line_number":821,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":2,"id":"25ab58b0_7a323963","line":818,"in_reply_to":"bbcb01de_56d7e5e9","updated":"2023-08-04 22:00:49.000000000","message":"I\u0027d be partial towards filtering out `Content-Length` and `ETag` from `self._response_headers` (i.e., just omitting the headers we update in `convert_segment_listing`) and responding 204.\n\nLooking at the specs more, I wonder if we\u0027d also want to filter out `Content-Range`. From https://datatracker.ietf.org/doc/html/rfc7231#section-4.3.2:\n\n\u003e The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 3.3) MAY be omitted.\n\nThen from https://datatracker.ietf.org/doc/html/rfc7231#section-3.3:\n\n\u003e Header fields that specifically describe the payload, rather than the associated representation, are referred to as \"payload header fields\".  Payload header fields are defined in other parts of this specification, due to their impact on message parsing.\n```\n   +-------------------+----------------------------+\n   | Header Field Name | Defined in...              |\n   +-------------------+----------------------------+\n   | Content-Length    | Section 3.3.2 of [RFC7230] |\n   | Content-Range     | Section 4.2 of [RFC7233]   |\n   | Trailer           | Section 4.4 of [RFC7230]   |\n   | Transfer-Encoding | Section 3.3.1 of [RFC7230] |\n   +-------------------+----------------------------+\n```\n\n(`Tranfer-Encoding` isn\u0027t really our domain, as a WSGI application rather than server, and we don\u0027t do `Trailer`s.)\n\nSo -- dropping `Content-Length` is *definitely* reasonable, and I\u0027d argue that in the absence of being able to determine the `ETag` we\u0027d send as part of a `GET`, we can lean on that `SHOULD` to just drop it. We don\u0027t actually _have_ to return the same headers, and we\u0027ll have made a good-faith effort to return what we _can_ know.","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d45a9b34c6ae7b75d70e303d7ea09f1d89e4c975","unresolved":true,"context_lines":[{"line_number":815,"context_line":"            if req.params.get(\u0027format\u0027) \u003d\u003d \u0027raw\u0027:"},{"line_number":816,"context_line":"                if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":817,"context_line":"                    raise HTTPMethodNotAllowed(\u0027Multipart Manifest on raw \u0027"},{"line_number":818,"context_line":"                                               \u0027formats can only be GETs\u0027)"},{"line_number":819,"context_line":"                resp_iter \u003d self.convert_segment_listing("},{"line_number":820,"context_line":"                    self._response_headers, resp_iter)"},{"line_number":821,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":2,"id":"320b4ac1_d0d36e48","line":818,"in_reply_to":"db644d8d_9d8a6d31","updated":"2023-08-21 20:20:47.000000000","message":"Oh, no no -- I\u0027d say the `HEAD` w/ `format\u003draw` is a rare enough call that refetching is unlikely to be an issue. I was more highlighting that I\u0027d prefer the 204 that\u0027s missing information over some 4xx.\n\nFor *sure* we\u0027ll need to do a refetch when doing a `HEAD` w/ `part-number`","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"96e8243ad004abbe36a480c5deec83555860abc4","unresolved":true,"context_lines":[{"line_number":783,"context_line":"            update_etag_is_at_header(req, SYSMETA_SLO_ETAG)"},{"line_number":784,"context_line":"            # Tell the object server that if it\u0027s a manifest,"},{"line_number":785,"context_line":"            # we want the whole thing"},{"line_number":786,"context_line":"            update_ignore_range_header(req, \u0027X-Static-Large-Object\u0027)"},{"line_number":787,"context_line":"        resp_iter \u003d self._app_call(req.environ)"},{"line_number":788,"context_line":""},{"line_number":789,"context_line":"        # make sure this response is for a static large object manifest"}],"source_content_type":"text/x-python","patch_set":3,"id":"6b222c18_891785c2","line":786,"updated":"2023-08-04 22:00:49.000000000","message":"Maybe off-topic? We still want to include this for `format\u003draw` requests.","commit_id":"9c7ae6b98df4d6cd15ff21d52cf32f05db6f4756"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"026f7258554615b3c7fece312869b4beb9bd6e83","unresolved":true,"context_lines":[{"line_number":783,"context_line":"            update_etag_is_at_header(req, SYSMETA_SLO_ETAG)"},{"line_number":784,"context_line":"            # Tell the object server that if it\u0027s a manifest,"},{"line_number":785,"context_line":"            # we want the whole thing"},{"line_number":786,"context_line":"            update_ignore_range_header(req, \u0027X-Static-Large-Object\u0027)"},{"line_number":787,"context_line":"        resp_iter \u003d self._app_call(req.environ)"},{"line_number":788,"context_line":""},{"line_number":789,"context_line":"        # make sure this response is for a static large object manifest"}],"source_content_type":"text/x-python","patch_set":3,"id":"9e27529e_6e5706f8","line":786,"in_reply_to":"114a1ac8_10f80f90","updated":"2023-08-31 18:55:24.000000000","message":"it sounds like this could still use some additional tests.","commit_id":"9c7ae6b98df4d6cd15ff21d52cf32f05db6f4756"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":true,"context_lines":[{"line_number":783,"context_line":"            update_etag_is_at_header(req, SYSMETA_SLO_ETAG)"},{"line_number":784,"context_line":"            # Tell the object server that if it\u0027s a manifest,"},{"line_number":785,"context_line":"            # we want the whole thing"},{"line_number":786,"context_line":"            update_ignore_range_header(req, \u0027X-Static-Large-Object\u0027)"},{"line_number":787,"context_line":"        resp_iter \u003d self._app_call(req.environ)"},{"line_number":788,"context_line":""},{"line_number":789,"context_line":"        # make sure this response is for a static large object manifest"}],"source_content_type":"text/x-python","patch_set":3,"id":"114a1ac8_10f80f90","line":786,"in_reply_to":"6b222c18_891785c2","updated":"2023-08-21 14:20:07.000000000","message":"Al, this is why (I thought) a ranged GET w/ format\u003draw both A) does not blow up with invalid json (range header is ignored by object server on GET to large object unless the user has specifically asked for the manifest) and B) does not respond to Range headers and should not return Accept-Ranges: bytes headers in responses (see follow-up, minor existing issue unrelated to fixing 500 response)\n\nI think it may have been another existing bug, but at least not a 500 - definately fixed it on accident","commit_id":"9c7ae6b98df4d6cd15ff21d52cf32f05db6f4756"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d45a9b34c6ae7b75d70e303d7ea09f1d89e4c975","unresolved":true,"context_lines":[{"line_number":890,"context_line":"                    close_if_possible(resp_iter)"},{"line_number":891,"context_line":"                    raise HTTPServiceUnavailable(request\u003dreq)"},{"line_number":892,"context_line":"            # NB: we might have gotten an out-of-date manifest -- that\u0027s OK;"},{"line_number":893,"context_line":"            # we\u0027ll just try to serve the old data"},{"line_number":894,"context_line":""},{"line_number":895,"context_line":"        # Any Content-Range from a manifest is almost certainly wrong for the"},{"line_number":896,"context_line":"        # full large object."}],"source_content_type":"text/x-python","patch_set":7,"id":"99f609b5_61158a0e","line":893,"updated":"2023-08-21 20:20:47.000000000","message":"All (or at least a lot) of this sanity-checking seems like it should go in `_refetch_manifest`","commit_id":"d3b852a3ecf45a974b65a155df26df5a4ceace9b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"026f7258554615b3c7fece312869b4beb9bd6e83","unresolved":false,"context_lines":[{"line_number":890,"context_line":"                    close_if_possible(resp_iter)"},{"line_number":891,"context_line":"                    raise HTTPServiceUnavailable(request\u003dreq)"},{"line_number":892,"context_line":"            # NB: we might have gotten an out-of-date manifest -- that\u0027s OK;"},{"line_number":893,"context_line":"            # we\u0027ll just try to serve the old data"},{"line_number":894,"context_line":""},{"line_number":895,"context_line":"        # Any Content-Range from a manifest is almost certainly wrong for the"},{"line_number":896,"context_line":"        # full large object."}],"source_content_type":"text/x-python","patch_set":7,"id":"1096a5db_e5fc6afb","line":893,"in_reply_to":"99f609b5_61158a0e","updated":"2023-08-31 18:55:24.000000000","message":"Done","commit_id":"d3b852a3ecf45a974b65a155df26df5a4ceace9b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8d563af5f537b6692999c01d9167d2b10bb47a8f","unresolved":true,"context_lines":[{"line_number":730,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":731,"context_line":"            # We\u0027ve already looked for SYSMETA_SLO_ETAG/SIZE in the response"},{"line_number":732,"context_line":"            # and didn\u0027t find them. We have to fetch the whole manifest and"},{"line_number":733,"context_line":"            # recompute."},{"line_number":734,"context_line":"            return True"},{"line_number":735,"context_line":""},{"line_number":736,"context_line":"        response_status \u003d int(self._response_status[:3])"}],"source_content_type":"text/x-python","patch_set":9,"id":"bd2c88b0_484fc6d9","line":733,"updated":"2023-08-21 12:06:12.000000000","message":"I think this comment is no longer accurate: in the format\u003draw/HEAD case, we may have found SYSMETA_SLO_ETAG/SIZE in the response, but we need to refetch to get the actual body.\n\nI\u0027m always wary of making statement within methods about why the method was called (that\u0027s the caller\u0027s concern), but perhaps in this case we could keep a comment such as:\n\n```\nEither SYSMETA_SLO_ETAG/SIZE in the response wasn\u0027t in the HEAD response, or we need to recompute their values for a format\u003draw request. We therefore have to fetch the whole manifest.\n```","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"026f7258554615b3c7fece312869b4beb9bd6e83","unresolved":true,"context_lines":[{"line_number":730,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":731,"context_line":"            # We\u0027ve already looked for SYSMETA_SLO_ETAG/SIZE in the response"},{"line_number":732,"context_line":"            # and didn\u0027t find them. We have to fetch the whole manifest and"},{"line_number":733,"context_line":"            # recompute."},{"line_number":734,"context_line":"            return True"},{"line_number":735,"context_line":""},{"line_number":736,"context_line":"        response_status \u003d int(self._response_status[:3])"}],"source_content_type":"text/x-python","patch_set":9,"id":"6133c84a_168d56d3","line":733,"in_reply_to":"10885e59_efbe83f3","updated":"2023-08-31 18:55:24.000000000","message":"i tried to do a _fetch_manifest_if_needed, but it didn\u0027t me away from from wanting a _need_to_refetch_manifest method that can do various checks and return True before finally saying \"ok fine, I guess return False\"","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d45a9b34c6ae7b75d70e303d7ea09f1d89e4c975","unresolved":true,"context_lines":[{"line_number":730,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":731,"context_line":"            # We\u0027ve already looked for SYSMETA_SLO_ETAG/SIZE in the response"},{"line_number":732,"context_line":"            # and didn\u0027t find them. We have to fetch the whole manifest and"},{"line_number":733,"context_line":"            # recompute."},{"line_number":734,"context_line":"            return True"},{"line_number":735,"context_line":""},{"line_number":736,"context_line":"        response_status \u003d int(self._response_status[:3])"}],"source_content_type":"text/x-python","patch_set":9,"id":"10885e59_efbe83f3","line":733,"in_reply_to":"3676e4a1_988532cc","updated":"2023-08-21 20:20:47.000000000","message":"I was about to leave a similar comment about wanting to just say\n```\nresp_iter \u003d self._refetch_manifest_if_needed(req, resp_iter)\n```","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":true,"context_lines":[{"line_number":730,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":731,"context_line":"            # We\u0027ve already looked for SYSMETA_SLO_ETAG/SIZE in the response"},{"line_number":732,"context_line":"            # and didn\u0027t find them. We have to fetch the whole manifest and"},{"line_number":733,"context_line":"            # recompute."},{"line_number":734,"context_line":"            return True"},{"line_number":735,"context_line":""},{"line_number":736,"context_line":"        response_status \u003d int(self._response_status[:3])"}],"source_content_type":"text/x-python","patch_set":9,"id":"3676e4a1_988532cc","line":733,"in_reply_to":"bd2c88b0_484fc6d9","updated":"2023-08-21 14:20:07.000000000","message":"Stale comments are pretty annoying.  Your read on the new use-case is accurate, and think the `if _need_to_refetch_manifest: _refetch_manifest()` now looks kind of dumb.  It might be better to have a `_refetch_manifest_if_needed` to encapsulate all the logic and behavior in one place.","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":true,"context_lines":[{"line_number":744,"context_line":"                not is_success(response_status)):"},{"line_number":745,"context_line":"            return True"},{"line_number":746,"context_line":""},{"line_number":747,"context_line":"        if req.range and response_status in (206, 416):"},{"line_number":748,"context_line":"            content_range \u003d \u0027\u0027"},{"line_number":749,"context_line":"            for header, value in self._response_headers:"},{"line_number":750,"context_line":"                if header.lower() \u003d\u003d \u0027content-range\u0027:"}],"source_content_type":"text/x-python","patch_set":9,"id":"ce55aa3f_e2d2bb9b","line":747,"updated":"2023-08-21 14:20:07.000000000","message":"well there you go!","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"026f7258554615b3c7fece312869b4beb9bd6e83","unresolved":false,"context_lines":[{"line_number":744,"context_line":"                not is_success(response_status)):"},{"line_number":745,"context_line":"            return True"},{"line_number":746,"context_line":""},{"line_number":747,"context_line":"        if req.range and response_status in (206, 416):"},{"line_number":748,"context_line":"            content_range \u003d \u0027\u0027"},{"line_number":749,"context_line":"            for header, value in self._response_headers:"},{"line_number":750,"context_line":"                if header.lower() \u003d\u003d \u0027content-range\u0027:"}],"source_content_type":"text/x-python","patch_set":9,"id":"3b7fac69_dd87a07b","line":747,"in_reply_to":"ce55aa3f_e2d2bb9b","updated":"2023-08-31 18:55:24.000000000","message":"Ack","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8d563af5f537b6692999c01d9167d2b10bb47a8f","unresolved":true,"context_lines":[{"line_number":909,"context_line":"        :param resp_headers: response headers"},{"line_number":910,"context_line":"        :param resp_iter: a response iterable"},{"line_number":911,"context_line":"        \"\"\""},{"line_number":912,"context_line":"        if self._need_to_refetch_manifest(req):"},{"line_number":913,"context_line":"            resp_iter \u003d self._refetch_manifest(req, resp_iter)"},{"line_number":914,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":915,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"85f38da3_d15bcef9","line":912,"updated":"2023-08-21 12:06:12.000000000","message":"why was this not already necessary for a GET with format\u003draw? Have we just fixed also another bug* ... and https://review.opendev.org/c/openstack/swift/+/892040 is clarifying that?\n\n* The other bug being \"GET?multipart-manifest\u003dget\u0026format\u003draw with Range returns empty list\"","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"026f7258554615b3c7fece312869b4beb9bd6e83","unresolved":false,"context_lines":[{"line_number":909,"context_line":"        :param resp_headers: response headers"},{"line_number":910,"context_line":"        :param resp_iter: a response iterable"},{"line_number":911,"context_line":"        \"\"\""},{"line_number":912,"context_line":"        if self._need_to_refetch_manifest(req):"},{"line_number":913,"context_line":"            resp_iter \u003d self._refetch_manifest(req, resp_iter)"},{"line_number":914,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":915,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"c1959c12_bd8f75e3","line":912,"in_reply_to":"383c4494_06bb261a","updated":"2023-08-31 18:55:24.000000000","message":"Done","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":true,"context_lines":[{"line_number":909,"context_line":"        :param resp_headers: response headers"},{"line_number":910,"context_line":"        :param resp_iter: a response iterable"},{"line_number":911,"context_line":"        \"\"\""},{"line_number":912,"context_line":"        if self._need_to_refetch_manifest(req):"},{"line_number":913,"context_line":"            resp_iter \u003d self._refetch_manifest(req, resp_iter)"},{"line_number":914,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":915,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"b23ccba3_9831c2a9","line":912,"in_reply_to":"85f38da3_d15bcef9","updated":"2023-08-21 14:20:07.000000000","message":"not an existing bug ...oh, but format\u003draw was also multipart-manifest\u003dget so maybe it didn\u0027t ignore range headers ... maybe _need_to_refetch does more than I realized.","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d45a9b34c6ae7b75d70e303d7ea09f1d89e4c975","unresolved":true,"context_lines":[{"line_number":909,"context_line":"        :param resp_headers: response headers"},{"line_number":910,"context_line":"        :param resp_iter: a response iterable"},{"line_number":911,"context_line":"        \"\"\""},{"line_number":912,"context_line":"        if self._need_to_refetch_manifest(req):"},{"line_number":913,"context_line":"            resp_iter \u003d self._refetch_manifest(req, resp_iter)"},{"line_number":914,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":915,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"383c4494_06bb261a","line":912,"in_reply_to":"b23ccba3_9831c2a9","updated":"2023-08-21 20:20:47.000000000","message":"It wouldn\u0027t *always* get you an empty list -- sometimes you could get a 500. That\u0027s what I was getting at with https://review.opendev.org/c/openstack/swift/+/890246/3..9//COMMIT_MSG#b9\n\nThis is definitely the crux of the issue, though: if we\u0027re going to go converting the segment list, we need to make sure we\u0027ve got the whole manifest.","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8d563af5f537b6692999c01d9167d2b10bb47a8f","unresolved":true,"context_lines":[{"line_number":910,"context_line":"        :param resp_iter: a response iterable"},{"line_number":911,"context_line":"        \"\"\""},{"line_number":912,"context_line":"        if self._need_to_refetch_manifest(req):"},{"line_number":913,"context_line":"            resp_iter \u003d self._refetch_manifest(req, resp_iter)"},{"line_number":914,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":915,"context_line":""},{"line_number":916,"context_line":"        for seg_dict in segments:"}],"source_content_type":"text/x-python","patch_set":9,"id":"14797786_47cf7a21","line":913,"updated":"2023-08-21 12:06:12.000000000","message":"OK, this change gets the correct etag (i.e. same as a GET response) by doing a GET and calculating the md5 of the transformed response body json.\n\nreverting here and the func test fails:\n\n```\nE       AssertionError: {\u0027content_type\u0027: \u0027application/octet-stream\u0027, \u0027conte[107 chars]b9\"\u0027} !\u003d {\u0027content_length\u0027: 2, \u0027content_type\u0027: \u0027application/[105 chars]ce\"\u0027}\nE       - {\u0027content_length\u0027: 240,\nE       ?                     --\nE\nE       + {\u0027content_length\u0027: 2,\nE          \u0027content_type\u0027: \u0027application/octet-stream\u0027,\nE       -  \u0027etag\u0027: \u0027\"9f93b62d9894ec16f04ae12ec8265bb9\"\u0027,\nE       +  \u0027etag\u0027: \u0027\"d751713988987e9331980363e24189ce\"\u0027,\nE          \u0027last_modified\u0027: \u0027Mon, 21 Aug 2023 10:53:31 GMT\u0027}\n```","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":false,"context_lines":[{"line_number":910,"context_line":"        :param resp_iter: a response iterable"},{"line_number":911,"context_line":"        \"\"\""},{"line_number":912,"context_line":"        if self._need_to_refetch_manifest(req):"},{"line_number":913,"context_line":"            resp_iter \u003d self._refetch_manifest(req, resp_iter)"},{"line_number":914,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":915,"context_line":""},{"line_number":916,"context_line":"        for seg_dict in segments:"}],"source_content_type":"text/x-python","patch_set":9,"id":"649ac030_752b2ecb","line":913,"in_reply_to":"14797786_47cf7a21","updated":"2023-08-21 14:20:07.000000000","message":"Ack","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8d563af5f537b6692999c01d9167d2b10bb47a8f","unresolved":true,"context_lines":[{"line_number":943,"context_line":"            body \u003d b\u0027\u0027"},{"line_number":944,"context_line":"        else:"},{"line_number":945,"context_line":"            body \u003d json_data"},{"line_number":946,"context_line":"        return [body]"},{"line_number":947,"context_line":""},{"line_number":948,"context_line":"    def _get_manifest_read(self, resp_iter):"},{"line_number":949,"context_line":"        with closing_if_possible(resp_iter):"}],"source_content_type":"text/x-python","patch_set":9,"id":"27f6a3b4_a039c472","line":946,"updated":"2023-08-21 12:06:12.000000000","message":"OK. this change prevents the byte enforcer blowing up, reverting this causes the func test to fail:\n\n```\nE           test.functional.swift_test_client.ResponseError: 500: \u0027Internal Error\u0027 (\u0027HEAD\u0027 \u0027/v1/AUTH_test/0b408cf20f10452b9f6f1e4dedbd1397/manifest-db\u0027) txid\u003dtx7e3c710f461c4eb0acc43-0064e3453e\n\ntest/functional/swift_test_client.py:951: ResponseError\n```","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":false,"context_lines":[{"line_number":943,"context_line":"            body \u003d b\u0027\u0027"},{"line_number":944,"context_line":"        else:"},{"line_number":945,"context_line":"            body \u003d json_data"},{"line_number":946,"context_line":"        return [body]"},{"line_number":947,"context_line":""},{"line_number":948,"context_line":"    def _get_manifest_read(self, resp_iter):"},{"line_number":949,"context_line":"        with closing_if_possible(resp_iter):"}],"source_content_type":"text/x-python","patch_set":9,"id":"87da83ac_aae8ae98","line":946,"in_reply_to":"27f6a3b4_a039c472","updated":"2023-08-21 14:20:07.000000000","message":"Ack","commit_id":"c82f8565a8ba70bf1d1d0a963b1095efacd98a36"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"026f7258554615b3c7fece312869b4beb9bd6e83","unresolved":true,"context_lines":[{"line_number":619,"context_line":"        # calculations, we would be unable to make this optimization."},{"line_number":620,"context_line":"        total_length \u003d sum(self._segment_length(seg) for seg in segments)"},{"line_number":621,"context_line":"        if not byteranges:"},{"line_number":622,"context_line":"            byteranges \u003d [(0, total_length - 1)]"},{"line_number":623,"context_line":""},{"line_number":624,"context_line":"        # Cache segments from sub-SLOs in case more than one byterange"},{"line_number":625,"context_line":"        # includes data from a particular sub-SLO. We only cache a few sets"}],"source_content_type":"text/x-python","patch_set":11,"id":"d2832a30_7b60859b","side":"PARENT","line":622,"updated":"2023-08-31 18:55:24.000000000","message":"these are consistently done is pre-processing _calculate_slo_attributes","commit_id":"719dec69254c940ab7d6ecc278ca6e96dc7de6bc"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"87c65028312aaddad5173054edcc51173bfe1e18","unresolved":false,"context_lines":[{"line_number":619,"context_line":"        # calculations, we would be unable to make this optimization."},{"line_number":620,"context_line":"        total_length \u003d sum(self._segment_length(seg) for seg in segments)"},{"line_number":621,"context_line":"        if not byteranges:"},{"line_number":622,"context_line":"            byteranges \u003d [(0, total_length - 1)]"},{"line_number":623,"context_line":""},{"line_number":624,"context_line":"        # Cache segments from sub-SLOs in case more than one byterange"},{"line_number":625,"context_line":"        # includes data from a particular sub-SLO. We only cache a few sets"}],"source_content_type":"text/x-python","patch_set":11,"id":"007e5b5f_73b194cf","side":"PARENT","line":622,"in_reply_to":"d2832a30_7b60859b","updated":"2023-10-11 16:38:45.000000000","message":"Ack","commit_id":"719dec69254c940ab7d6ecc278ca6e96dc7de6bc"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":true,"context_lines":[{"line_number":600,"context_line":"        try:"},{"line_number":601,"context_line":"            return self._calculate_slo_attributes("},{"line_number":602,"context_line":"                sub_resp.app_iter, slo_attrs)"},{"line_number":603,"context_line":"        except HTTPException as err:"},{"line_number":604,"context_line":"            raise ListingIterError("},{"line_number":605,"context_line":"                \u0027while fetching %s, JSON-decoding of submanifest %s \u0027"},{"line_number":606,"context_line":"                \u0027failed with %s\u0027 % (req.path, sub_req.path, err))"}],"source_content_type":"text/x-python","patch_set":11,"id":"dc8d49b6_13330d56","line":603,"updated":"2023-08-31 18:30:43.000000000","message":"previously this code didn\u0027t ues _get_manifest_read, but now SegmentedIterable expects seg dicts to have been pre-processed with [\u0027segment_length\u0027] annotations","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":true,"context_lines":[{"line_number":764,"context_line":""},{"line_number":765,"context_line":"        # for manifest pass through, we only need the body for raw"},{"line_number":766,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 and multipart_manifest \u003d\u003d \u0027get\u0027:"},{"line_number":767,"context_line":"            return format_param \u003d\u003d \u0027raw\u0027"},{"line_number":768,"context_line":""},{"line_number":769,"context_line":"        # The response shows that this resp is a SLO manifest, but does not"},{"line_number":770,"context_line":"        # mean that resp_iter contains the entire SLO manifest. If it doesn\u0027t,"}],"source_content_type":"text/x-python","patch_set":11,"id":"dcb171e8_976e74f8","line":767,"updated":"2023-08-31 18:30:43.000000000","message":"I think this will end up being the whole HEAD?format\u003draw fix","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":true,"context_lines":[{"line_number":769,"context_line":"        # The response shows that this resp is a SLO manifest, but does not"},{"line_number":770,"context_line":"        # mean that resp_iter contains the entire SLO manifest. If it doesn\u0027t,"},{"line_number":771,"context_line":"        # we may need to make a second request to actually get the whole thing."},{"line_number":772,"context_line":"        status_int \u003d self._get_status_int()"},{"line_number":773,"context_line":""},{"line_number":774,"context_line":"        # a \"legacy manifest\" didn\u0027t get etag and size sysmeta"},{"line_number":775,"context_line":"        is_legacy_manifest \u003d not all(slo_attrs[k] for k in (\u0027etag\u0027, \u0027size\u0027))"}],"source_content_type":"text/x-python","patch_set":11,"id":"b829ac01_e4cfbd92","line":772,"updated":"2023-08-31 18:30:43.000000000","message":"status_int is un-used, it was here before I added self._response_status_int","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"026f7258554615b3c7fece312869b4beb9bd6e83","unresolved":true,"context_lines":[{"line_number":842,"context_line":"        from manifest sysmeta."},{"line_number":843,"context_line":"        \"\"\""},{"line_number":844,"context_line":"        calculated_size \u003d 0"},{"line_number":845,"context_line":"        calculated_etag \u003d md5(usedforsecurity\u003dFalse)"},{"line_number":846,"context_line":""},{"line_number":847,"context_line":"        for seg_dict in segments:"},{"line_number":848,"context_line":"            # Decode any inlined data; it\u0027s important that we do this *before*"}],"source_content_type":"text/x-python","patch_set":11,"id":"c7720c5f_4810959a","line":845,"updated":"2023-08-31 18:55:24.000000000","message":"there may be justification to only do this hashing if slo_attrs doesn\u0027t already the etag from sysmeta; but I opted for the getting the simple thing working first.","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"87c65028312aaddad5173054edcc51173bfe1e18","unresolved":false,"context_lines":[{"line_number":842,"context_line":"        from manifest sysmeta."},{"line_number":843,"context_line":"        \"\"\""},{"line_number":844,"context_line":"        calculated_size \u003d 0"},{"line_number":845,"context_line":"        calculated_etag \u003d md5(usedforsecurity\u003dFalse)"},{"line_number":846,"context_line":""},{"line_number":847,"context_line":"        for seg_dict in segments:"},{"line_number":848,"context_line":"            # Decode any inlined data; it\u0027s important that we do this *before*"}],"source_content_type":"text/x-python","patch_set":11,"id":"cffe4bbb_57610041","line":845,"in_reply_to":"c7720c5f_4810959a","updated":"2023-10-11 16:38:45.000000000","message":"Ack","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"026f7258554615b3c7fece312869b4beb9bd6e83","unresolved":true,"context_lines":[{"line_number":869,"context_line":"        slo_attrs[\u0027size\u0027] \u003d calculated_size"},{"line_number":870,"context_line":"        slo_attrs[\u0027etag\u0027] \u003d calculated_etag.hexdigest()"},{"line_number":871,"context_line":""},{"line_number":872,"context_line":"    def _calculate_slo_attributes(self, resp_iter, slo_attrs):"},{"line_number":873,"context_line":"        \"\"\""},{"line_number":874,"context_line":"        Read the manifest body and parse segments."},{"line_number":875,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"cd8f8028_3b9307b8","line":872,"updated":"2023-08-31 18:55:24.000000000","message":"this function could be named better - it\u0027s primary purpose is to take a resp_iter and turn it into a segments list\n\nthe updating of the slo_attrs is more of a side-effect","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":true,"context_lines":[{"line_number":894,"context_line":"                \u0027conditional_response\u0027: True,"},{"line_number":895,"context_line":"            }"},{"line_number":896,"context_line":"        else:"},{"line_number":897,"context_line":"            conditional_kwargs \u003d {}"},{"line_number":898,"context_line":"        resp \u003d Response("},{"line_number":899,"context_line":"            status\u003dself._response_status,"},{"line_number":900,"context_line":"            headers\u003dself._response_headers,"}],"source_content_type":"text/x-python","patch_set":11,"id":"76c61048_4ffba1dc","line":897,"updated":"2023-08-31 18:30:43.000000000","message":"I was excited about consolidating all responses into a single method - which we only bail out to from handle_slo_get_or_head in two places:\n\n1) we\u0027re not an SLO\n2) we ARE an SLO\n\nI think maybe case #1 might look better as a stock `start_response(); return resp_iter` and we only get into swob responses if we need to do the conditional stuff\n\nBut somehow swob doesn\u0027t seem to like the conditional kwargs if it\u0027s not a conditional response?  I don\u0027t think I understand that yet.","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":true,"context_lines":[{"line_number":941,"context_line":"        else:"},{"line_number":942,"context_line":"            refetched \u003d False"},{"line_number":943,"context_line":""},{"line_number":944,"context_line":"        if not slo_attrs[\u0027is_slo\u0027]:"},{"line_number":945,"context_line":"            # Not a static large object manifest. Just pass it through."},{"line_number":946,"context_line":"            return self._return_response(req, start_response, resp_iter)"},{"line_number":947,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"454ad297_6fe3759d","line":944,"updated":"2023-08-31 18:30:43.000000000","message":"i punted this until after the \"maybe refetch\" so the exit path when the refetch isn\u0027t a manifest is shared with the exit path when the *original* request wasn\u0027t a manifest","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":true,"context_lines":[{"line_number":954,"context_line":"                # we\u0027re going to return the manifest as-is"},{"line_number":955,"context_line":"                replace_headers \u003d {"},{"line_number":956,"context_line":"                    \u0027Content-Type\u0027: \u0027application/json; charset\u003dutf-8\u0027,"},{"line_number":957,"context_line":"                }"},{"line_number":958,"context_line":"        else:"},{"line_number":959,"context_line":"            if (req.method \u003d\u003d \u0027GET\u0027 or refetched) and ("},{"line_number":960,"context_line":"                    self._response_status_int not in (304, 412, 416)):"}],"source_content_type":"text/x-python","patch_set":11,"id":"993f774a_811a7a91","line":957,"updated":"2023-08-31 18:30:43.000000000","message":"the main jist of this block is a) we are dealing with an SLO response, but depending on how we want to respond response we\u0027ll have a different resp_iter, replace_headers pair (mainly beause the replace_headers etag depends on SLO/manifest response)\n\nit\u0027s not terrible - but not super obvious yet either.","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":true,"context_lines":[{"line_number":962,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027 and ("},{"line_number":963,"context_line":"                    self._response_status_int not in (304, 412, 416)):"},{"line_number":964,"context_line":"                # don\u0027t validate_first_segement on HEAD?"},{"line_number":965,"context_line":"                resp_iter \u003d self._build_resp_iter(req, segments, slo_attrs)"},{"line_number":966,"context_line":"            replace_headers \u003d {"},{"line_number":967,"context_line":"                \u0027Etag\u0027: \u0027\"%s\"\u0027 % slo_attrs[\u0027etag\u0027],"},{"line_number":968,"context_line":"                \u0027X-Manifest-Etag\u0027: self._response_header_value(\u0027etag\u0027),"}],"source_content_type":"text/x-python","patch_set":11,"id":"86509336_b862b484","line":965,"updated":"2023-08-31 18:30:43.000000000","message":"this part is SO gross - and tells me the refactor isn\u0027t done yet.\n\nbasically we need to parse the segments if we\u0027re going to build_resp_iter and we need to _calculate_slo_attributes for legacy-manifest\n\nbut for new manifests we have all the slo_attrs and our resp_iter is the object server (304, 412, 416) response, but that\u0027s ok because we don\u0027t need a segmented iterable.\n\nThere has to be a way to make this more obvious.","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":true,"context_lines":[{"line_number":1013,"context_line":"        except ValueError:"},{"line_number":1014,"context_line":"            msg \u003d \u0027Unable to load SLO manifest\u0027"},{"line_number":1015,"context_line":"            self.slo.logger.exception(msg)"},{"line_number":1016,"context_line":"            raise HTTPServerError(msg)"},{"line_number":1017,"context_line":"        return segments"},{"line_number":1018,"context_line":""},{"line_number":1019,"context_line":"    def _build_resp_iter(self, req, segments, slo_attrs):"}],"source_content_type":"text/x-python","patch_set":11,"id":"967c0362_af1d6cf3","line":1016,"updated":"2023-08-31 18:30:43.000000000","message":"I\u0027m 100% sure returning the empty segments list is wrong see https://review.opendev.org/c/openstack/swift/+/887230\n\n... but I\u0027m not sure raising the HTTP exception is pefect either\n\nSince we may encouter a json.decode error on a manifest EITHER when responding to a GET for a SLO or while streaming a SLO response with a sub-slo, it might make sense to let the JSONDecodeError bubble out and let the caller decide what to do with it.","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"}],"swift/common/wsgi.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":true,"context_lines":[{"line_number":1112,"context_line":"        Uses the same semantics as the usual WSGI start_response."},{"line_number":1113,"context_line":"        \"\"\""},{"line_number":1114,"context_line":"        self._response_status \u003d status"},{"line_number":1115,"context_line":"        self._response_status_int \u003d self._get_status_int()"},{"line_number":1116,"context_line":"        self._response_headers \u003d \\"},{"line_number":1117,"context_line":"            headers if isinstance(headers, list) else list(headers)"},{"line_number":1118,"context_line":"        self._response_exc_info \u003d exc_info"}],"source_content_type":"text/x-python","patch_set":11,"id":"67b73c24_de857d3e","line":1115,"updated":"2023-08-31 18:30:43.000000000","message":"I don\u0027t know why this wasn\u0027t here before; but it probably deserves it\u0027s own tests","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"}],"test/functional/test_slo.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"1f3ab8f006c898a48b7133e6b651a2ef4cfe5b7c","unresolved":true,"context_lines":[{"line_number":1179,"context_line":"            got_info \u003d manifest.info(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027,"},{"line_number":1180,"context_line":"                                            \u0027format\u0027: \u0027raw\u0027})"},{"line_number":1181,"context_line":"        except ResponseError:"},{"line_number":1182,"context_line":"            msg \u003d \u0027Method Not Allowed\u0027"},{"line_number":1183,"context_line":""},{"line_number":1184,"context_line":"        self.assertIsNone(got_info)"},{"line_number":1185,"context_line":"        self.assertEqual(self.env.conn.response.code, 405)"}],"source_content_type":"text/x-python","patch_set":2,"id":"63f1b5b8_82c1f8d0","line":1182,"updated":"2023-08-01 21:28:15.000000000","message":"maybe with.assertRaises can help here, I\u0027m not sure if the ResponseError object has any useful properties you could assert on.","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"96e8243ad004abbe36a480c5deec83555860abc4","unresolved":true,"context_lines":[{"line_number":1179,"context_line":"            got_info \u003d manifest.info(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027,"},{"line_number":1180,"context_line":"                                            \u0027format\u0027: \u0027raw\u0027})"},{"line_number":1181,"context_line":"        except ResponseError:"},{"line_number":1182,"context_line":"            msg \u003d \u0027Method Not Allowed\u0027"},{"line_number":1183,"context_line":""},{"line_number":1184,"context_line":"        self.assertIsNone(got_info)"},{"line_number":1185,"context_line":"        self.assertEqual(self.env.conn.response.code, 405)"}],"source_content_type":"text/x-python","patch_set":2,"id":"de3e950b_11e55dbf","line":1182,"in_reply_to":"63f1b5b8_82c1f8d0","updated":"2023-08-04 22:00:49.000000000","message":"Seconding something like `with self.assertRaises(ResponseError) as caught` -- then we can make assertions on `caught.exception.status` and `caught.exception.reason` and not need to dig down to `self.env.conn` in the test.","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":false,"context_lines":[{"line_number":1179,"context_line":"            got_info \u003d manifest.info(parms\u003d{\u0027multipart-manifest\u0027: \u0027get\u0027,"},{"line_number":1180,"context_line":"                                            \u0027format\u0027: \u0027raw\u0027})"},{"line_number":1181,"context_line":"        except ResponseError:"},{"line_number":1182,"context_line":"            msg \u003d \u0027Method Not Allowed\u0027"},{"line_number":1183,"context_line":""},{"line_number":1184,"context_line":"        self.assertIsNone(got_info)"},{"line_number":1185,"context_line":"        self.assertEqual(self.env.conn.response.code, 405)"}],"source_content_type":"text/x-python","patch_set":2,"id":"12764152_d12a4d89","line":1182,"in_reply_to":"de3e950b_11e55dbf","updated":"2023-08-21 14:20:07.000000000","message":"Done","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"1f3ab8f006c898a48b7133e6b651a2ef4cfe5b7c","unresolved":true,"context_lines":[{"line_number":1182,"context_line":"            msg \u003d \u0027Method Not Allowed\u0027"},{"line_number":1183,"context_line":""},{"line_number":1184,"context_line":"        self.assertIsNone(got_info)"},{"line_number":1185,"context_line":"        self.assertEqual(self.env.conn.response.code, 405)"},{"line_number":1186,"context_line":"        self.assertEqual(self.env.conn.response.reason, msg)"},{"line_number":1187,"context_line":""},{"line_number":1188,"context_line":"    def test_slo_if_match_get(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"ac4ec48d_c904f707","line":1185,"updated":"2023-08-01 21:28:15.000000000","message":"i\u0027m guessing if you roll back this change we\u0027d get a assert failure here 500 !\u003d 405","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":false,"context_lines":[{"line_number":1182,"context_line":"            msg \u003d \u0027Method Not Allowed\u0027"},{"line_number":1183,"context_line":""},{"line_number":1184,"context_line":"        self.assertIsNone(got_info)"},{"line_number":1185,"context_line":"        self.assertEqual(self.env.conn.response.code, 405)"},{"line_number":1186,"context_line":"        self.assertEqual(self.env.conn.response.reason, msg)"},{"line_number":1187,"context_line":""},{"line_number":1188,"context_line":"    def test_slo_if_match_get(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"307c6f1c_74f0113c","line":1185,"in_reply_to":"ac4ec48d_c904f707","updated":"2023-08-21 14:20:07.000000000","message":"Done","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"1f3ab8f006c898a48b7133e6b651a2ef4cfe5b7c","unresolved":true,"context_lines":[{"line_number":1183,"context_line":""},{"line_number":1184,"context_line":"        self.assertIsNone(got_info)"},{"line_number":1185,"context_line":"        self.assertEqual(self.env.conn.response.code, 405)"},{"line_number":1186,"context_line":"        self.assertEqual(self.env.conn.response.reason, msg)"},{"line_number":1187,"context_line":""},{"line_number":1188,"context_line":"    def test_slo_if_match_get(self):"},{"line_number":1189,"context_line":"        manifest \u003d self.env.container.file(\"manifest-abcde\")"}],"source_content_type":"text/x-python","patch_set":2,"id":"fb6862b5_9865f933","line":1186,"updated":"2023-08-01 21:28:15.000000000","message":"there\u0027s two lineages of functional tests in swift\u0027s code base and I find these self.env ones very confusing; but I think this is a pretty strong assert.","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":false,"context_lines":[{"line_number":1183,"context_line":""},{"line_number":1184,"context_line":"        self.assertIsNone(got_info)"},{"line_number":1185,"context_line":"        self.assertEqual(self.env.conn.response.code, 405)"},{"line_number":1186,"context_line":"        self.assertEqual(self.env.conn.response.reason, msg)"},{"line_number":1187,"context_line":""},{"line_number":1188,"context_line":"    def test_slo_if_match_get(self):"},{"line_number":1189,"context_line":"        manifest \u003d self.env.container.file(\"manifest-abcde\")"}],"source_content_type":"text/x-python","patch_set":2,"id":"57de9a9d_f1c7f71f","line":1186,"in_reply_to":"fb6862b5_9865f933","updated":"2023-08-21 14:20:07.000000000","message":"Done","commit_id":"f1efcad08aecef4ce3c4f8ffc9c302c7cb600a71"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3103e1fdf98e37dfa279e4eb4f3b6db7dcc438b7","unresolved":true,"context_lines":[{"line_number":1184,"context_line":"            \u0027content_type\u0027: \u0027application/octet-stream\u0027,"},{"line_number":1185,"context_line":"            \u0027content_length\u0027: int(raw_get_headers[\u0027content-length\u0027]),"},{"line_number":1186,"context_line":"            \u0027last_modified\u0027: raw_get_headers[\u0027last-modified\u0027],"},{"line_number":1187,"context_line":"            \u0027etag\u0027: \u0027\"%s\"\u0027 % raw_hex_digest,"},{"line_number":1188,"context_line":"        }"},{"line_number":1189,"context_line":"        self.assertEqual(expected, got_info)"},{"line_number":1190,"context_line":"        headers \u003d dict("}],"source_content_type":"text/x-python","patch_set":6,"id":"5dc50c0a_ef9e3004","line":1187,"updated":"2023-08-18 19:03:10.000000000","message":"the quoting here on \"expected etag\" might have to be conditional on `tf.cluster_info.get(\u0027etag_quoter\u0027, {}).get(\u0027enable_by_default\u0027)`","commit_id":"495fa24dce43108b5f49416e873dedc4ee04a307"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":false,"context_lines":[{"line_number":1184,"context_line":"            \u0027content_type\u0027: \u0027application/octet-stream\u0027,"},{"line_number":1185,"context_line":"            \u0027content_length\u0027: int(raw_get_headers[\u0027content-length\u0027]),"},{"line_number":1186,"context_line":"            \u0027last_modified\u0027: raw_get_headers[\u0027last-modified\u0027],"},{"line_number":1187,"context_line":"            \u0027etag\u0027: \u0027\"%s\"\u0027 % raw_hex_digest,"},{"line_number":1188,"context_line":"        }"},{"line_number":1189,"context_line":"        self.assertEqual(expected, got_info)"},{"line_number":1190,"context_line":"        headers \u003d dict("}],"source_content_type":"text/x-python","patch_set":6,"id":"9d7cb244_09c388ba","line":1187,"in_reply_to":"5dc50c0a_ef9e3004","updated":"2023-08-21 14:20:07.000000000","message":"Done","commit_id":"495fa24dce43108b5f49416e873dedc4ee04a307"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3103e1fdf98e37dfa279e4eb4f3b6db7dcc438b7","unresolved":true,"context_lines":[{"line_number":1186,"context_line":"            \u0027last_modified\u0027: raw_get_headers[\u0027last-modified\u0027],"},{"line_number":1187,"context_line":"            \u0027etag\u0027: \u0027\"%s\"\u0027 % raw_hex_digest,"},{"line_number":1188,"context_line":"        }"},{"line_number":1189,"context_line":"        self.assertEqual(expected, got_info)"},{"line_number":1190,"context_line":"        headers \u003d dict("},{"line_number":1191,"context_line":"            (h.lower(), v)"},{"line_number":1192,"context_line":"            for h, v in manifest.conn.response.getheaders()"}],"source_content_type":"text/x-python","patch_set":6,"id":"55735ff2_81550258","line":1189,"updated":"2023-08-18 19:03:10.000000000","message":"-  \u0027etag\u0027: \u0027\"fbe4c6c260483c2088d77e7515659b90\"\u0027,\n    ?           -                                -\n    \n    +  \u0027etag\u0027: \u0027fbe4c6c260483c2088d77e7515659b90\u0027,","commit_id":"495fa24dce43108b5f49416e873dedc4ee04a307"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":false,"context_lines":[{"line_number":1186,"context_line":"            \u0027last_modified\u0027: raw_get_headers[\u0027last-modified\u0027],"},{"line_number":1187,"context_line":"            \u0027etag\u0027: \u0027\"%s\"\u0027 % raw_hex_digest,"},{"line_number":1188,"context_line":"        }"},{"line_number":1189,"context_line":"        self.assertEqual(expected, got_info)"},{"line_number":1190,"context_line":"        headers \u003d dict("},{"line_number":1191,"context_line":"            (h.lower(), v)"},{"line_number":1192,"context_line":"            for h, v in manifest.conn.response.getheaders()"}],"source_content_type":"text/x-python","patch_set":6,"id":"117d9ec5_76829ceb","line":1189,"in_reply_to":"55735ff2_81550258","updated":"2023-08-21 14:20:07.000000000","message":"Done","commit_id":"495fa24dce43108b5f49416e873dedc4ee04a307"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"22bb0797e7717d50dc9291f0174f69c705506438","unresolved":true,"context_lines":[{"line_number":1197,"context_line":"            for h, v in manifest.conn.response.getheaders()"},{"line_number":1198,"context_line":"            if h.lower() not in ignore_headers)"},{"line_number":1199,"context_line":"        self.maxDiff \u003d None"},{"line_number":1200,"context_line":"        self.assertEqual(raw_get_headers, headers)"},{"line_number":1201,"context_line":""},{"line_number":1202,"context_line":"    def test_slo_head_the_manifest(self):"},{"line_number":1203,"context_line":"        manifest \u003d self.env.container.file(\"manifest-abcde\")"}],"source_content_type":"text/x-python","patch_set":11,"id":"934b4fa3_f75d45b0","line":1200,"updated":"2023-08-31 18:30:43.000000000","message":"these updates are all related to the HEAD?format\u003draw fix","commit_id":"e22a965e70605bf645d80dc4d4da9fc9e67b86d8"}],"test/unit/common/middleware/test_slo.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3103e1fdf98e37dfa279e4eb4f3b6db7dcc438b7","unresolved":true,"context_lines":[{"line_number":2123,"context_line":"        self.assertEqual(\u0027200 OK\u0027, status)"},{"line_number":2124,"context_line":"        self.assertEqual(b\u0027\u0027, body)"},{"line_number":2125,"context_line":"        self.assertTrue((\u0027Etag\u0027, self.expected_etag) in headers, headers)"},{"line_number":2126,"context_line":"        self.assertTrue((\u0027X-Static-Large-Object\u0027, \u0027true\u0027) in headers, headers)"},{"line_number":2127,"context_line":""},{"line_number":2128,"context_line":"    def test_get_raw_manifest_passthrough_with_ranges(self):"},{"line_number":2129,"context_line":"        req \u003d Request.blank("}],"source_content_type":"text/x-python","patch_set":6,"id":"3d66736b_d923acfc","line":2126,"updated":"2023-08-18 19:03:10.000000000","message":"this doesn\u0027t look right, I think I wanted to assert HEAD followed by GET in the observed app calls here too","commit_id":"495fa24dce43108b5f49416e873dedc4ee04a307"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"11415d9fe5eb3dcc2136447111fae51a428c2c22","unresolved":false,"context_lines":[{"line_number":2123,"context_line":"        self.assertEqual(\u0027200 OK\u0027, status)"},{"line_number":2124,"context_line":"        self.assertEqual(b\u0027\u0027, body)"},{"line_number":2125,"context_line":"        self.assertTrue((\u0027Etag\u0027, self.expected_etag) in headers, headers)"},{"line_number":2126,"context_line":"        self.assertTrue((\u0027X-Static-Large-Object\u0027, \u0027true\u0027) in headers, headers)"},{"line_number":2127,"context_line":""},{"line_number":2128,"context_line":"    def test_get_raw_manifest_passthrough_with_ranges(self):"},{"line_number":2129,"context_line":"        req \u003d Request.blank("}],"source_content_type":"text/x-python","patch_set":6,"id":"0293e5c8_3881c80e","line":2126,"in_reply_to":"3d66736b_d923acfc","updated":"2023-08-21 14:20:07.000000000","message":"Done","commit_id":"495fa24dce43108b5f49416e873dedc4ee04a307"}]}
