)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d4e4d7f773724d659a16a5abd7595cb9b08f7623","unresolved":true,"context_lines":[{"line_number":4,"context_line":"Commit:     ASHWIN A NAIR \u003cnairashwin952013@gmail.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2023-09-13 16:36:51 +0000"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"slo: Implement efficient slo object metadata handling"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch introduces a more optimized method for handling metadata"},{"line_number":10,"context_line":"in the slo middleware. By leveraging advanced data structures and algorithmic improvements, we achieve a significant reduction in"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"dc95439a_b17d4f0d","line":7,"updated":"2023-09-17 20:18:06.000000000","message":"how do you mean \"efficient\"???","commit_id":"4a376d73d9fd3543ebde5f170f273320122963a5"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"f34a62e5caafd06f1cc385cb9967acbbe6bfdc11","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     ASHWIN A NAIR \u003cnairashwin952013@gmail.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2023-09-13 16:36:51 +0000"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"slo: Implement efficient slo object metadata handling"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch introduces a more optimized method for handling metadata"},{"line_number":10,"context_line":"in the slo middleware. By leveraging advanced data structures and algorithmic improvements, we achieve a significant reduction in"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"a8ad6d2d_fca5af56","line":7,"in_reply_to":"dc95439a_b17d4f0d","updated":"2023-09-21 03:40:20.000000000","message":"Ahh changed it to \"slo: refactor slo object metadata handling\"","commit_id":"4a376d73d9fd3543ebde5f170f273320122963a5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d4e4d7f773724d659a16a5abd7595cb9b08f7623","unresolved":true,"context_lines":[{"line_number":7,"context_line":"slo: Implement efficient slo object metadata handling"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch introduces a more optimized method for handling metadata"},{"line_number":10,"context_line":"in the slo middleware. By leveraging advanced data structures and algorithmic improvements, we achieve a significant reduction in"},{"line_number":11,"context_line":"metadata lookup times, leading to improved overall performance and"},{"line_number":12,"context_line":"making code more easily readable."},{"line_number":13,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"e9232bbb_12640d15","line":10,"updated":"2023-09-17 20:18:06.000000000","message":"the formatting on this line is bad","commit_id":"4a376d73d9fd3543ebde5f170f273320122963a5"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"f34a62e5caafd06f1cc385cb9967acbbe6bfdc11","unresolved":false,"context_lines":[{"line_number":7,"context_line":"slo: Implement efficient slo object metadata handling"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch introduces a more optimized method for handling metadata"},{"line_number":10,"context_line":"in the slo middleware. By leveraging advanced data structures and algorithmic improvements, we achieve a significant reduction in"},{"line_number":11,"context_line":"metadata lookup times, leading to improved overall performance and"},{"line_number":12,"context_line":"making code more easily readable."},{"line_number":13,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"8a4fc704_7be1b66f","line":10,"in_reply_to":"e9232bbb_12640d15","updated":"2023-09-21 03:40:20.000000000","message":"Done","commit_id":"4a376d73d9fd3543ebde5f170f273320122963a5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d4e4d7f773724d659a16a5abd7595cb9b08f7623","unresolved":true,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch introduces a more optimized method for handling metadata"},{"line_number":10,"context_line":"in the slo middleware. By leveraging advanced data structures and algorithmic improvements, we achieve a significant reduction in"},{"line_number":11,"context_line":"metadata lookup times, leading to improved overall performance and"},{"line_number":12,"context_line":"making code more easily readable."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Change-Id: Idc84e70539fc7480b6ecb86e2f0da904baf2c727"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"eb832f6d_fb7a50df","line":11,"updated":"2023-09-17 20:18:06.000000000","message":"i didn\u0027t really expect any performance changes","commit_id":"4a376d73d9fd3543ebde5f170f273320122963a5"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"f34a62e5caafd06f1cc385cb9967acbbe6bfdc11","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This patch introduces a more optimized method for handling metadata"},{"line_number":10,"context_line":"in the slo middleware. By leveraging advanced data structures and algorithmic improvements, we achieve a significant reduction in"},{"line_number":11,"context_line":"metadata lookup times, leading to improved overall performance and"},{"line_number":12,"context_line":"making code more easily readable."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Change-Id: Idc84e70539fc7480b6ecb86e2f0da904baf2c727"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"dd17ad61_bf599454","line":11,"in_reply_to":"eb832f6d_fb7a50df","updated":"2023-09-21 03:40:20.000000000","message":"Ack","commit_id":"4a376d73d9fd3543ebde5f170f273320122963a5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d4e4d7f773724d659a16a5abd7595cb9b08f7623","unresolved":true,"context_lines":[{"line_number":9,"context_line":"This patch introduces a more optimized method for handling metadata"},{"line_number":10,"context_line":"in the slo middleware. By leveraging advanced data structures and algorithmic improvements, we achieve a significant reduction in"},{"line_number":11,"context_line":"metadata lookup times, leading to improved overall performance and"},{"line_number":12,"context_line":"making code more easily readable."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Change-Id: Idc84e70539fc7480b6ecb86e2f0da904baf2c727"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"2ac03d9f_5dabbd01","line":12,"updated":"2023-09-17 20:18:06.000000000","message":"that\u0027s the hope","commit_id":"4a376d73d9fd3543ebde5f170f273320122963a5"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"f34a62e5caafd06f1cc385cb9967acbbe6bfdc11","unresolved":false,"context_lines":[{"line_number":9,"context_line":"This patch introduces a more optimized method for handling metadata"},{"line_number":10,"context_line":"in the slo middleware. By leveraging advanced data structures and algorithmic improvements, we achieve a significant reduction in"},{"line_number":11,"context_line":"metadata lookup times, leading to improved overall performance and"},{"line_number":12,"context_line":"making code more easily readable."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Change-Id: Idc84e70539fc7480b6ecb86e2f0da904baf2c727"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"3899a3d3_1131e733","line":12,"in_reply_to":"2ac03d9f_5dabbd01","updated":"2023-09-21 03:40:20.000000000","message":"Ack","commit_id":"4a376d73d9fd3543ebde5f170f273320122963a5"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":9,"context_line":"This patch reorganizes the SLO read response handling.  The main goal"},{"line_number":10,"context_line":"was to push the response header replacement for both SLO and"},{"line_number":11,"context_line":"multipart-manifest\u003dget paths into a common return path.  A new SloAttrs"},{"line_number":12,"context_line":"namedtuple primitive is used to carry around some metadata details from"},{"line_number":13,"context_line":"SLO responses.  The author hopes these changes make code more easily"},{"line_number":14,"context_line":"readable and easier to modify."},{"line_number":15,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":31,"id":"83b65a39_65f1af68","line":12,"range":{"start_line":12,"start_character":0,"end_line":12,"end_character":20},"updated":"2023-10-25 14:57:41.000000000","message":"changed to \u0027class\u0027","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":9,"context_line":"This patch reorganizes the SLO read response handling.  The main goal"},{"line_number":10,"context_line":"was to push the response header replacement for both SLO and"},{"line_number":11,"context_line":"multipart-manifest\u003dget paths into a common return path.  A new SloAttrs"},{"line_number":12,"context_line":"namedtuple primitive is used to carry around some metadata details from"},{"line_number":13,"context_line":"SLO responses.  The author hopes these changes make code more easily"},{"line_number":14,"context_line":"readable and easier to modify."},{"line_number":15,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":31,"id":"574c19b5_38389ce0","line":12,"range":{"start_line":12,"start_character":0,"end_line":12,"end_character":20},"in_reply_to":"83b65a39_65f1af68","updated":"2023-10-26 00:15:45.000000000","message":"Done","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3b44a01a4be6d6a7ce391df0ea05dced0a4d772c","unresolved":true,"context_lines":[{"line_number":24,"context_line":"so middleware authors don\u0027t have parse the \"_response_status\" string."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Closes-Bug: #2040178"},{"line_number":27,"context_line":"Co-Authored-By: Alistair Coles \u003calistairncoles@gmail.com\u003e"},{"line_number":28,"context_line":"Related-Change-Id: I54094f3d2098f56b755ec19cc9315d06a6ca8b15"},{"line_number":29,"context_line":"Change-Id: Idc84e70539fc7480b6ecb86e2f0da904baf2c727"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":32,"id":"bc185bb4_33787d3b","line":27,"updated":"2023-10-26 20:05:14.000000000","message":"We\u0027re pulling in some additional SloAttrs functionality and tests from the slo-part-num patch into this one; Ash needs a co-author line!","commit_id":"c7dd1432294078631904191e77a2896e17dae27e"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"8a620523522cd98eb497d9ac326c8cdd0a933f51","unresolved":false,"context_lines":[{"line_number":24,"context_line":"so middleware authors don\u0027t have parse the \"_response_status\" string."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Closes-Bug: #2040178"},{"line_number":27,"context_line":"Co-Authored-By: Alistair Coles \u003calistairncoles@gmail.com\u003e"},{"line_number":28,"context_line":"Related-Change-Id: I54094f3d2098f56b755ec19cc9315d06a6ca8b15"},{"line_number":29,"context_line":"Change-Id: Idc84e70539fc7480b6ecb86e2f0da904baf2c727"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":32,"id":"283c3aff_d85a5d44","line":27,"in_reply_to":"bc185bb4_33787d3b","updated":"2023-10-27 02:10:16.000000000","message":"Haha thanks Clay, i never hesitate in putting my name in a patch.","commit_id":"c7dd1432294078631904191e77a2896e17dae27e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":17,"context_line":"drain empty/error responses more confidently (and use it in swob and"},{"line_number":18,"context_line":"request_helpers)."},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"Closes-Bug: #2040178"},{"line_number":21,"context_line":"Co-Authored-By: Alistair Coles \u003calistairncoles@gmail.com\u003e"},{"line_number":22,"context_line":"Co-Authored-By: Ashwin Nair \u003cnairashwin952013@gmail.com\u003e"},{"line_number":23,"context_line":"Related-Change-Id: I54094f3d2098f56b755ec19cc9315d06a6ca8b15"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":41,"id":"ec1e50e4_a4e4febe","line":20,"updated":"2023-11-03 18:50:26.000000000","message":"Not even called out as a drive-by?","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":17,"context_line":"drain empty/error responses more confidently (and use it in swob and"},{"line_number":18,"context_line":"request_helpers)."},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"Closes-Bug: #2040178"},{"line_number":21,"context_line":"Co-Authored-By: Alistair Coles \u003calistairncoles@gmail.com\u003e"},{"line_number":22,"context_line":"Co-Authored-By: Ashwin Nair \u003cnairashwin952013@gmail.com\u003e"},{"line_number":23,"context_line":"Related-Change-Id: I54094f3d2098f56b755ec19cc9315d06a6ca8b15"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":41,"id":"f22a8fba_81d03feb","line":20,"in_reply_to":"ec1e50e4_a4e4febe","updated":"2023-11-04 00:34:58.000000000","message":"heh, it *is* called out - right here!\n\nHonstly I forget what this bug was about, apparently no one makes conditional requests against SLOs?  Since even *I\u0027d* forgotten, I think mentioning it as a drive-by might make the commit message a little better - I\u0027ll add that!","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"8a3b345e_8cb1c9b8","updated":"2023-09-02 13:30:53.000000000","message":"there\u0027s a bunch of functest failures related to conditional responses, but I was able to easily duplicate them locally.","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c523ec9131b5ebc8248acb7b9453641079096029","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"91d9741b_75a12328","updated":"2023-09-03 14:43:06.000000000","message":"I got at least ONE passing functest run - but there could easily still be some wonky; I want to see what zuul thinks about it.","commit_id":"72af9e231580ba1c150e8fed572219f33a52db5d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c0b5e37e0cd9f9bb3e6523dc6ab176d09fbed1c9","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"a592e318_28fc8b1c","updated":"2023-09-06 15:18:31.000000000","message":"@Clay I think the intent here is great, the code is already more readable. I\u0027ve not finished review but pushing comments I have so far.\n\nThere\u0027s one condition in _need_to_refetch_manifest w.r.t. get_manifest requests that I\u0027m not sure is correct (see inline)","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"823a4d4d4c72b60d3014c07c94d5707f0a7a015a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"bd4f7be0_9ae17166","updated":"2023-09-08 23:32:58.000000000","message":"https://review.opendev.org/c/openstack/swift/+/894403 should give us an in-tree func test that exercises the behavior this breaks.","commit_id":"659703e88701be60d9c6884edaa25af3d76bfe9b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d4e4d7f773724d659a16a5abd7595cb9b08f7623","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"d7828e98_27a78a2e","updated":"2023-09-17 20:18:06.000000000","message":"I think the goal is still to merge https://review.opendev.org/c/openstack/swift/+/894403 and then rebase this on that directly\n\nwe can figure out what to do with https://review.opendev.org/c/openstack/swift/+/894800/ and https://review.opendev.org/c/openstack/swift/+/894830 later","commit_id":"4a376d73d9fd3543ebde5f170f273320122963a5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"33947032_b79bfca4","updated":"2023-09-21 21:46:09.000000000","message":"i think i\u0027m getting closer to happy enought with this.","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9a63c75f301edaf3d5b8651fd7bd2365dbdf1dab","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":13,"id":"d54e224c_fe080c67","updated":"2023-09-25 22:34:11.000000000","message":"I think it makes the most sense to have this stacked on the test refactor\n\nhttps://review.opendev.org/c/openstack/swift/+/896466","commit_id":"868bcfa7fd4225e3a05e712104fcbe19fa56f564"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"a259acca_2b433c91","updated":"2023-09-27 18:21:43.000000000","message":"@Clay posting comments I have so far\n\nThis may (or may not!) be the most substantive comment https://review.opendev.org/c/openstack/swift/+/893578/comment/38bcdc3e_9c7d6b65/","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"3f7180ee_386412be","updated":"2023-09-27 20:44:30.000000000","message":"thanks Al!","commit_id":"b32603e924196c644e289b9c3d758691dd08a180"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"30f5e2df0fd685473bf3da7813c4747f11382087","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":20,"id":"0156e3b3_08608b8b","updated":"2023-09-28 13:28:51.000000000","message":"@Clay I pushed a couple more follow-ons for you to maybe squash including some targeted tests for SloAttrs","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"7d153d7329469806711ff3ef47f0721e2d84329f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":20,"id":"4e11f392_468a9df3","updated":"2023-09-28 14:34:29.000000000","message":"i\u0027ll squash everything in; thanks Al!","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0011184508ee28592fcce43943da0f6637175d1e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"245c36b7_7bc4e4d5","updated":"2023-09-29 04:39:26.000000000","message":"I am quite a bit happier with this latest attempt than those before it - thanks for the HUGE lift up Al!\n\nProbably still some more polish to do - I need to sleep on it.","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"0a6978f2_d0223842","updated":"2023-09-29 14:29:51.000000000","message":"This is really coming together!\n\nThere\u0027s still a few places where I\u0027m struggling to grok subtle changes.\n\nI think that there\u0027s scope for follow up (re-ordering the methods to be called-before-caller, tidy up some comments) but I think that should wait - this patch is already concentrated high-churn as it is - but it\u0027s making the code much more maintainable.","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"c5903d34_487488e8","updated":"2023-09-29 19:52:06.000000000","message":"having discussed with Al, I think there\u0027s some tests we can looking for and add if needed - either the current code works somehow or the existing code was under tested.","commit_id":"2c7502b71247658d9a90dfca106809dec611a975"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"116890ebea9ac6698113d753af315d9a47903370","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":23,"id":"23748867_9c3d0319","updated":"2023-10-05 15:30:57.000000000","message":"@Clay one more to review and squash ? https://review.opendev.org/c/openstack/swift/+/897468","commit_id":"827a727abc30d969721681ce8458529a19d5e34c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f1f377ac72044eb5798014e9e8cda65cd9d2ef64","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":24,"id":"aac40715_dce28a1a","updated":"2023-10-11 00:15:13.000000000","message":"The func test failure seems legit - something about a 416\n\nTomorrow, I\u0027ll try and split up the leak tracking patch to squash the tests changes into the pre-factor and the fixes into here.  I don\u0027t know if I\u0027ll finish the test cleanup or get this change working again before EOD tomorrow.","commit_id":"aca28936e167786996e7095c6a3c7a3c0b8503ac"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0b1d76caf5ef4327b324c7dfe7643f5b57ee0f42","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":28,"id":"9eaa83b6_c9ff060f","updated":"2023-10-23 18:57:56.000000000","message":"i think we\u0027re getting there!","commit_id":"de681ce70103c7d60e02ec8bc7b0b26a4da123ec"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":31,"id":"659d4c52_6aea5c6e","updated":"2023-10-26 00:15:45.000000000","message":"fantastic review brother!  I think I addressed the material issues you noticed wrt the slo_attrs refactor; but there\u0027s probably more debate to be had in the details.  I think you might have been getting tired by the time you got to test_http; or maybe I\u0027m just tired after fighting with all those SloAttrs tests!  Conditional responses and how swob handles them is still tricky; I\u0027ll aim to spend some time looking under the covers at swob a bit more and see if we can do anything there that would make our lives simpler.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":31,"id":"22651c65_eb68210f","updated":"2023-10-25 14:57:41.000000000","message":"this is my first visit back after a break, kudos @Clay for sticking at it!\n\nMost of my remaining uncertainty is around conditional requests (no surprise), I\u0027ll keep staring!\n\nI\u0027d prefer not to have bits of the partnum change appearing prematurely in this patch - it\u0027s busy enough as it is.\n\nI can understand what led to test_http but it seems more like test_swob material.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3b44a01a4be6d6a7ce391df0ea05dced0a4d772c","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":32,"id":"ca3df0ea_8061c285","updated":"2023-10-26 20:05:14.000000000","message":"I need to update the commit message.\n\nI think it might be useful to renamed is_conditional_error to is_conditional_failure - lean more into the \"is conditional but not success\" side than the 3XX \"error\" debate.\n\nI would like Al to chime in how strongly he feels about pulling out the use of swob to setup context in test_http?  I\u0027m pretty sure I like them how I wrote them, but I could be missing something and almostly definately could be convinced I\u0027d like something else just as much if not better.","commit_id":"c7dd1432294078631904191e77a2896e17dae27e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96235704ef07bcf9f723add0d0358b7085dd4b06","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":33,"id":"76ce5722_e84891f5","updated":"2023-10-28 01:32:43.000000000","message":"definately regretting adding the test_http module; maybe most of the comments as well 😊  OTOH, maybe that means the code itself is in pretty good shape already!?\n\nThanks for the help everyone!  What\u0027s next?","commit_id":"8e316933e76147981b765c981e31f42592e1201c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6422746d841db395a64231fa2dc9968614731861","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":38,"id":"6f51fa92_cd4e27fd","updated":"2023-10-31 16:07:22.000000000","message":"sorry forgot to post this!","commit_id":"63c4d3f6f280fad1ceb8d221f5ab3c5160512c55"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"62162178405ef6b8397eca0d015f2ffcab86d1fc","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":39,"id":"351d5df6_824cffcc","updated":"2023-11-02 15:36:53.000000000","message":"#1 rule of large diffs - no drive-bys!  they\u0027ll get nit picked to death.","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"37105331a48b3933ecc80ebb2f908aca1ed077bd","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":39,"id":"954832c1_d3465002","updated":"2023-11-02 00:04:11.000000000","message":"Consciously *not* looking at SLO right now, but I want you to have comments in your morning.","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"a7d8c2fc64eea9e3cf9bd8860f52c8eb050f9bd2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":39,"id":"4cc53d31_cf9fbdd2","updated":"2023-11-01 23:33:21.000000000","message":"shoot, i forgot to update those comments in swob/slo about 412 draining!","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":41,"id":"00db50ed_199dd84a","updated":"2023-11-04 00:34:58.000000000","message":"wow, thanks Tim - that cleaned up a number of issues; some of your wtfs might require more thought and the sub-slo validation might still be problematic or not well understood.\n\nI\u0027m considering pulling friendly_close and it\u0027s application out into pre-req so there\u0027s no more drive-bys (i guess except the bug fix 😄)\n\nIf you really think test_slo\u0027s handling of 412 and 304 could benifit from helpers in http I wonder if you might consider sharing what you think would be best in a follow-up that I could squash.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":42,"id":"88481968_5aa55d17","updated":"2023-11-07 19:40:36.000000000","message":"I think I might be OK with this once we fix `drain_and_close`","commit_id":"2c71d8f1302d2618f3efd3ee96e52c2a820c0900"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a5ca7fb4a7212517b469a6eca7b2aef29f7422e1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":46,"id":"b10b94f3_dbf04140","updated":"2023-11-09 12:53:46.000000000","message":"Still LGTM, just one query over the renaming for which I\u0027ve made a suggestion here https://review.opendev.org/c/openstack/swift/+/900518 ... BUT I am aware I may have missed some context, so leaving as a possible squash patch rather than pushing over this.","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":46,"id":"8834d5f6_b12b123c","updated":"2023-11-09 23:25:02.000000000","message":"We have GOT to be getting close on the attrs/refetch/listing_needed logic - unfortunately I think we\u0027re running out of fresh eyes and now that half of us have it loaded we\u0027re all like \"yeah w/e, it\u0027s complicated - six one way half a dozen the other\"\n\n... but future us is going to wish we\u0027d figured it out!  Maybe Matt or Jian will know what to do.","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":46,"id":"f1f36502_f928a981","in_reply_to":"b10b94f3_dbf04140","updated":"2023-11-09 23:25:02.000000000","message":"I think the maybe_attrs was ment to ecapsulate the transition from \"not slo_attrs.is_slo\" into something that definately represents an slo object\n\n*particuarlly* across the transisition from:\n\nattrs \u003d first_req()\nif need_to_refetch():\n    attrs \u003d refetch()\n    \nif not attrs.is_slo:\n    ...\n    \n    \n where the overwrite/replace of attrs in refetch is only one line and SO easy to misunderstand when only reading the top level method without understanding how much complexity we baked into need_to_refetch \u0026 refetch.\n \nBut now that we\u0027ve all got it you probalby can\u0027t un-see it; so idk.","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"31cda479eb1467047c09f4f607952d82753286f1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"dc91bbf7_f243ab92","updated":"2023-11-10 21:45:17.000000000","message":"I think Al saved us again in the 11th hour!  Thanks for the last push Tim - I think it made a big difference.  I\u0027m really happy with where this landed.","commit_id":"113d265df0d4c0a0afefce8ed1e813ae71972e96"}],"swift/common/http.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    N.B. \"304 Not Modified\" is an \"implicit redirection to a cached resource\""},{"line_number":73,"context_line":"    for conditional If-None-Match or If-Modified-Since requests that DO match"},{"line_number":74,"context_line":"    (i.e. haven\u0027t been modified); but it\u0027s definately \"not is_success\" so some"},{"line_number":75,"context_line":"    code lumps behavior together with \"412 Precondition Failed\" *errors* for"},{"line_number":76,"context_line":"    conditional If-Match and and If-Unmodified-Since requests."},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"13699a10_24755f68","line":74,"range":{"start_line":74,"start_character":10,"end_line":74,"end_character":31},"updated":"2023-10-25 14:57:41.000000000","message":"But an If-Modified-Since that matches *has* been modified? did you mean \"If-None-Match\" or \"If-Unmodified-Since\"","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    N.B. \"304 Not Modified\" is an \"implicit redirection to a cached resource\""},{"line_number":73,"context_line":"    for conditional If-None-Match or If-Modified-Since requests that DO match"},{"line_number":74,"context_line":"    (i.e. haven\u0027t been modified); but it\u0027s definately \"not is_success\" so some"},{"line_number":75,"context_line":"    code lumps behavior together with \"412 Precondition Failed\" *errors* for"},{"line_number":76,"context_line":"    conditional If-Match and and If-Unmodified-Since requests."},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"4e6b9e1c_c937c94e","line":74,"range":{"start_line":74,"start_character":43,"end_line":74,"end_character":53},"updated":"2023-10-25 14:57:41.000000000","message":"s/definately/definitely/","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    N.B. \"304 Not Modified\" is an \"implicit redirection to a cached resource\""},{"line_number":73,"context_line":"    for conditional If-None-Match or If-Modified-Since requests that DO match"},{"line_number":74,"context_line":"    (i.e. haven\u0027t been modified); but it\u0027s definately \"not is_success\" so some"},{"line_number":75,"context_line":"    code lumps behavior together with \"412 Precondition Failed\" *errors* for"},{"line_number":76,"context_line":"    conditional If-Match and and If-Unmodified-Since requests."},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"685f3961_49cf2ab0","line":74,"range":{"start_line":74,"start_character":54,"end_line":74,"end_character":70},"updated":"2023-10-25 14:57:41.000000000","message":"this seems obvious given the implementation of is_success above (304 is definitely not between 200 and 299, but maybe there\u0027s a subtlety I am missing in this statement?\n\nIs it that \"because it\u0027s not success as defined by is_success some code lumps it with a 412\"?","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":true,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    N.B. \"304 Not Modified\" is an \"implicit redirection to a cached resource\""},{"line_number":73,"context_line":"    for conditional If-None-Match or If-Modified-Since requests that DO match"},{"line_number":74,"context_line":"    (i.e. haven\u0027t been modified); but it\u0027s definately \"not is_success\" so some"},{"line_number":75,"context_line":"    code lumps behavior together with \"412 Precondition Failed\" *errors* for"},{"line_number":76,"context_line":"    conditional If-Match and and If-Unmodified-Since requests."},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"3bcc77b8_360e5a23","line":74,"range":{"start_line":74,"start_character":10,"end_line":74,"end_character":31},"in_reply_to":"13699a10_24755f68","updated":"2023-10-26 00:15:45.000000000","message":"I think the error condition for an \"if-modified-since: x\" request would be that it has NOT been modified-since x ... so that\u0027s why it returns 304?  If I\u0027ve got it wrong you can certainly help me with better tests.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d110631b6c6835cee843e209fde32c6bfefab186","unresolved":true,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    N.B. \"304 Not Modified\" is an \"implicit redirection to a cached resource\""},{"line_number":73,"context_line":"    for conditional If-None-Match or If-Modified-Since requests that DO match"},{"line_number":74,"context_line":"    (i.e. haven\u0027t been modified); but it\u0027s definately \"not is_success\" so some"},{"line_number":75,"context_line":"    code lumps behavior together with \"412 Precondition Failed\" *errors* for"},{"line_number":76,"context_line":"    conditional If-Match and and If-Unmodified-Since requests."},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"bbd12396_d7056c97","line":74,"range":{"start_line":74,"start_character":10,"end_line":74,"end_character":31},"in_reply_to":"3bcc77b8_360e5a23","updated":"2023-10-27 17:44:25.000000000","message":"I also think the error condition for an \"if-modified-since: x\" request would be that it has NOT been modified-since x\n\nBut given:\n\n```\nLast-Modified: 2\nIf-Modified-Since: 1\n```\n\nI\u0027d say the state of the resource matches the condition expressed by the request.\n\nSo the essence of my comment is that I was confused by the use of \"match\" (lower case), because I tend to think of \"match\" as a positive with respect to a condition, synonymous with \"condition is satisfied\", \"condition is true\", \"condition is met\".","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    N.B. \"304 Not Modified\" is an \"implicit redirection to a cached resource\""},{"line_number":73,"context_line":"    for conditional If-None-Match or If-Modified-Since requests that DO match"},{"line_number":74,"context_line":"    (i.e. haven\u0027t been modified); but it\u0027s definately \"not is_success\" so some"},{"line_number":75,"context_line":"    code lumps behavior together with \"412 Precondition Failed\" *errors* for"},{"line_number":76,"context_line":"    conditional If-Match and and If-Unmodified-Since requests."},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"c7a02d55_9a3a1689","line":74,"range":{"start_line":74,"start_character":43,"end_line":74,"end_character":53},"in_reply_to":"4e6b9e1c_c937c94e","updated":"2023-10-26 00:15:45.000000000","message":"Done","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":true,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    N.B. \"304 Not Modified\" is an \"implicit redirection to a cached resource\""},{"line_number":73,"context_line":"    for conditional If-None-Match or If-Modified-Since requests that DO match"},{"line_number":74,"context_line":"    (i.e. haven\u0027t been modified); but it\u0027s definately \"not is_success\" so some"},{"line_number":75,"context_line":"    code lumps behavior together with \"412 Precondition Failed\" *errors* for"},{"line_number":76,"context_line":"    conditional If-Match and and If-Unmodified-Since requests."},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"74ce51f2_3110049b","line":74,"range":{"start_line":74,"start_character":54,"end_line":74,"end_character":70},"in_reply_to":"685f3961_49cf2ab0","updated":"2023-10-26 00:15:45.000000000","message":"I was justifying calling a 3XX response an error - it\u0027s `not is_success and not is_client_error`\n\nI was considering renaming this something like... \"conditional_failure\" to get away from error/success bad/good dicotomy???  Not that someone calling me a \"failure\" would be much better than error - but I\u0027m not that worried about the status codes feeling as much as picking a name for the function people can live with.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d110631b6c6835cee843e209fde32c6bfefab186","unresolved":true,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    N.B. \"304 Not Modified\" is an \"implicit redirection to a cached resource\""},{"line_number":73,"context_line":"    for conditional If-None-Match or If-Modified-Since requests that DO match"},{"line_number":74,"context_line":"    (i.e. haven\u0027t been modified); but it\u0027s definately \"not is_success\" so some"},{"line_number":75,"context_line":"    code lumps behavior together with \"412 Precondition Failed\" *errors* for"},{"line_number":76,"context_line":"    conditional If-Match and and If-Unmodified-Since requests."},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"878d58af_178dcd70","line":74,"range":{"start_line":74,"start_character":54,"end_line":74,"end_character":70},"in_reply_to":"74ce51f2_3110049b","updated":"2023-10-27 17:44:25.000000000","message":"yeah, it\u0027s a tricky one to name, and IDK if I can offer better...\n\nis_condition_not_satisfied\nis_condition_unmet","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96235704ef07bcf9f723add0d0358b7085dd4b06","unresolved":false,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    N.B. \"304 Not Modified\" is an \"implicit redirection to a cached resource\""},{"line_number":73,"context_line":"    for conditional If-None-Match or If-Modified-Since requests that DO match"},{"line_number":74,"context_line":"    (i.e. haven\u0027t been modified); but it\u0027s definately \"not is_success\" so some"},{"line_number":75,"context_line":"    code lumps behavior together with \"412 Precondition Failed\" *errors* for"},{"line_number":76,"context_line":"    conditional If-Match and and If-Unmodified-Since requests."},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"44cd4ab3_6c90d202","line":74,"range":{"start_line":74,"start_character":54,"end_line":74,"end_character":70},"in_reply_to":"878d58af_178dcd70","updated":"2023-10-28 01:32:43.000000000","message":"i like is_unmet_condition!  thank you!","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96235704ef07bcf9f723add0d0358b7085dd4b06","unresolved":false,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    N.B. \"304 Not Modified\" is an \"implicit redirection to a cached resource\""},{"line_number":73,"context_line":"    for conditional If-None-Match or If-Modified-Since requests that DO match"},{"line_number":74,"context_line":"    (i.e. haven\u0027t been modified); but it\u0027s definately \"not is_success\" so some"},{"line_number":75,"context_line":"    code lumps behavior together with \"412 Precondition Failed\" *errors* for"},{"line_number":76,"context_line":"    conditional If-Match and and If-Unmodified-Since requests."},{"line_number":77,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"55b4df62_2365a26f","line":74,"range":{"start_line":74,"start_character":10,"end_line":74,"end_character":31},"in_reply_to":"bbd12396_d7056c97","updated":"2023-10-28 01:32:43.000000000","message":"ohhh kay... so that\u0027s helpful - but a rewording of the comment that you would find BETTER would be MOST helpful.  I\u0027ll try again with that input.  Thank you.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"}],"swift/common/middleware/slo.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":608,"context_line":"        for seg_dict in segments:"},{"line_number":609,"context_line":"            if config_true_value(seg_dict.get(\u0027sub_slo\u0027)):"},{"line_number":610,"context_line":"                override_bytes_from_content_type(seg_dict,"},{"line_number":611,"context_line":"                                                 logger\u003dself.slo.logger)"},{"line_number":612,"context_line":""},{"line_number":613,"context_line":"        # We handle the range stuff here so that we can be smart about"},{"line_number":614,"context_line":"        # skipping unused submanifests. For example, if our first segment is a"}],"source_content_type":"text/x-python","patch_set":1,"id":"5d15537f_b47a9a3a","side":"PARENT","line":611,"updated":"2023-09-02 13:30:53.000000000","message":"it was weird to have this extra iteration over all segments off on it\u0027s own, there\u0027s definatley some utility in bringing this stuff together.","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"50efdb2c7c931fdc29acd91144964927fcff47e3","unresolved":false,"context_lines":[{"line_number":608,"context_line":"        for seg_dict in segments:"},{"line_number":609,"context_line":"            if config_true_value(seg_dict.get(\u0027sub_slo\u0027)):"},{"line_number":610,"context_line":"                override_bytes_from_content_type(seg_dict,"},{"line_number":611,"context_line":"                                                 logger\u003dself.slo.logger)"},{"line_number":612,"context_line":""},{"line_number":613,"context_line":"        # We handle the range stuff here so that we can be smart about"},{"line_number":614,"context_line":"        # skipping unused submanifests. For example, if our first segment is a"}],"source_content_type":"text/x-python","patch_set":1,"id":"f7d4efd1_78bc3546","side":"PARENT","line":611,"in_reply_to":"5d15537f_b47a9a3a","updated":"2023-09-12 16:43:32.000000000","message":"Ack","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":617,"context_line":"        #"},{"line_number":618,"context_line":"        # If we were to make SegmentedIterable handle all the range"},{"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":""}],"source_content_type":"text/x-python","patch_set":1,"id":"95a358bf_91397f1a","side":"PARENT","line":620,"updated":"2023-09-02 13:30:53.000000000","message":"another whole weird extra iteration just for the \u0027if not byteranges\u0027 case, this got moved to caller _build_resp_iter","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"50efdb2c7c931fdc29acd91144964927fcff47e3","unresolved":false,"context_lines":[{"line_number":617,"context_line":"        #"},{"line_number":618,"context_line":"        # If we were to make SegmentedIterable handle all the range"},{"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":""}],"source_content_type":"text/x-python","patch_set":1,"id":"16cb4636_bff3e1f4","side":"PARENT","line":620,"in_reply_to":"95a358bf_91397f1a","updated":"2023-09-12 16:43:32.000000000","message":"Ack","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":649,"context_line":"        last_sub_path \u003d None"},{"line_number":650,"context_line":"        for seg_dict in segments:"},{"line_number":651,"context_line":"            if \u0027data\u0027 in seg_dict:"},{"line_number":652,"context_line":"                seg_dict[\u0027raw_data\u0027] \u003d strict_b64decode(seg_dict.pop(\u0027data\u0027))"},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"            seg_length \u003d self._segment_length(seg_dict)"},{"line_number":655,"context_line":"            if first_byte \u003e\u003d seg_length:"}],"source_content_type":"text/x-python","patch_set":1,"id":"34d1f764_48e67a7b","side":"PARENT","line":652,"updated":"2023-09-02 13:30:53.000000000","message":"I think this is the main reason I had to make sub slo use the common pre-parsing, but OTOH, it felt silly to decode raw_data to calculate segment_length and the decode again here\n\nI could have made this defensive, if \u0027data\u0027 in seg_dict and \u0027raw_data\u0027 not in seg_dict","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":649,"context_line":"        last_sub_path \u003d None"},{"line_number":650,"context_line":"        for seg_dict in segments:"},{"line_number":651,"context_line":"            if \u0027data\u0027 in seg_dict:"},{"line_number":652,"context_line":"                seg_dict[\u0027raw_data\u0027] \u003d strict_b64decode(seg_dict.pop(\u0027data\u0027))"},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"            seg_length \u003d self._segment_length(seg_dict)"},{"line_number":655,"context_line":"            if first_byte \u003e\u003d seg_length:"}],"source_content_type":"text/x-python","patch_set":1,"id":"1241f644_333b9bce","side":"PARENT","line":652,"in_reply_to":"34d1f764_48e67a7b","updated":"2023-09-27 20:44:30.000000000","message":"I now think it\u0027s probably good to conslidate - we should do it more - currently the multipart-manifest\u003dput path seems to decode raw_data twice as well.","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":725,"context_line":"        doesn\u0027t, we need to make a second request to actually get the whole"},{"line_number":726,"context_line":"        thing."},{"line_number":727,"context_line":""},{"line_number":728,"context_line":"        Note: this assumes that X-Static-Large-Object has already been found."},{"line_number":729,"context_line":"        \"\"\""},{"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"}],"source_content_type":"text/x-python","patch_set":1,"id":"f554a478_368acc9c","side":"PARENT","line":728,"updated":"2023-09-02 13:30:53.000000000","message":"I think removing this assumption and having this method handle all cases compleatly was a win","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":725,"context_line":"        doesn\u0027t, we need to make a second request to actually get the whole"},{"line_number":726,"context_line":"        thing."},{"line_number":727,"context_line":""},{"line_number":728,"context_line":"        Note: this assumes that X-Static-Large-Object has already been found."},{"line_number":729,"context_line":"        \"\"\""},{"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"}],"source_content_type":"text/x-python","patch_set":1,"id":"a244018c_a59c012b","side":"PARENT","line":728,"in_reply_to":"f554a478_368acc9c","updated":"2023-09-27 20:44:30.000000000","message":"Ack","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"e63a9009d9e931d781b38dc1ad41a39cb89b75a0","unresolved":false,"context_lines":[{"line_number":725,"context_line":"        doesn\u0027t, we need to make a second request to actually get the whole"},{"line_number":726,"context_line":"        thing."},{"line_number":727,"context_line":""},{"line_number":728,"context_line":"        Note: this assumes that X-Static-Large-Object has already been found."},{"line_number":729,"context_line":"        \"\"\""},{"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"}],"source_content_type":"text/x-python","patch_set":1,"id":"97876e60_7d6de4d3","side":"PARENT","line":728,"in_reply_to":"f554a478_368acc9c","updated":"2023-09-27 23:42:53.000000000","message":"Done","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"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])"},{"line_number":737,"context_line":""},{"line_number":738,"context_line":"        # These are based on etag, and the SLO\u0027s etag is almost certainly not"},{"line_number":739,"context_line":"        # the manifest object\u0027s etag. Still, it\u0027s highly likely that the"}],"source_content_type":"text/x-python","patch_set":1,"id":"75f63fd0_b3808bef","side":"PARENT","line":736,"updated":"2023-09-02 13:30:53.000000000","message":"i feel like I found at least three different ways we (re)calculate _response_status_int - I should hadd an explicit test for the change to common.wsgi","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"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])"},{"line_number":737,"context_line":""},{"line_number":738,"context_line":"        # These are based on etag, and the SLO\u0027s etag is almost certainly not"},{"line_number":739,"context_line":"        # the manifest object\u0027s etag. Still, it\u0027s highly likely that the"}],"source_content_type":"text/x-python","patch_set":1,"id":"9b007a2e_ce23e2b6","side":"PARENT","line":736,"in_reply_to":"75f63fd0_b3808bef","updated":"2023-09-27 20:44:30.000000000","message":"Ack","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":942,"context_line":"        try:"},{"line_number":943,"context_line":"            segments \u003d json.loads(resp_body)"},{"line_number":944,"context_line":"        except ValueError:"},{"line_number":945,"context_line":"            segments \u003d []"},{"line_number":946,"context_line":""},{"line_number":947,"context_line":"        return segments"},{"line_number":948,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"1fa16daa_6cd33726","side":"PARENT","line":945,"updated":"2023-09-02 13:30:53.000000000","message":"I\u0027m trying to merge on of Tim\u0027s change to fix this:\n\n887230: slo: 500 if we can\u0027t load the manifest | https://review.opendev.org/c/openstack/swift/+/887230","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"e63a9009d9e931d781b38dc1ad41a39cb89b75a0","unresolved":false,"context_lines":[{"line_number":942,"context_line":"        try:"},{"line_number":943,"context_line":"            segments \u003d json.loads(resp_body)"},{"line_number":944,"context_line":"        except ValueError:"},{"line_number":945,"context_line":"            segments \u003d []"},{"line_number":946,"context_line":""},{"line_number":947,"context_line":"        return segments"},{"line_number":948,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"b4c6c6f0_08c517c1","side":"PARENT","line":945,"in_reply_to":"1fa16daa_6cd33726","updated":"2023-09-27 23:42:53.000000000","message":"Done","commit_id":"a7a10cd35d97291a70b2a06f2e1066177d4630d1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":564,"context_line":"    Returns the number of bytes that would be fetched for the given segment."},{"line_number":565,"context_line":"    \"\"\""},{"line_number":566,"context_line":"    if \u0027raw_data\u0027 in seg_dict:"},{"line_number":567,"context_line":"        return len(seg_dict[\u0027raw_data\u0027])"},{"line_number":568,"context_line":""},{"line_number":569,"context_line":"    seg_range \u003d seg_dict.get(\u0027range\u0027)"},{"line_number":570,"context_line":"    if seg_range is not None:"}],"source_content_type":"text/x-python","patch_set":1,"id":"af2771f4_6002c033","line":567,"updated":"2023-09-02 13:30:53.000000000","message":"Perhaps it would be better to ecapsulate the raw_data decoding *into* this method","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":564,"context_line":"    Returns the number of bytes that would be fetched for the given segment."},{"line_number":565,"context_line":"    \"\"\""},{"line_number":566,"context_line":"    if \u0027raw_data\u0027 in seg_dict:"},{"line_number":567,"context_line":"        return len(seg_dict[\u0027raw_data\u0027])"},{"line_number":568,"context_line":""},{"line_number":569,"context_line":"    seg_range \u003d seg_dict.get(\u0027range\u0027)"},{"line_number":570,"context_line":"    if seg_range is not None:"}],"source_content_type":"text/x-python","patch_set":1,"id":"e4158011_eb71f845","line":567,"in_reply_to":"af2771f4_6002c033","updated":"2023-09-27 20:44:30.000000000","message":"I guess I said this because this helper doesn\u0027t work if you didn\u0027t base64decode the seg_dict[\u0027data\u0027] into raw data before calling it...\n\nbut this helper is currently only called from _annotate_segment_length which does the decode right before calling into it, and SegmentedIterable wouldn\u0027t work unless you pre-decode raw_data either!","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":575,"context_line":"        range_start, range_end \u003d [int(x) for x in seg_range.split(\u0027-\u0027)]"},{"line_number":576,"context_line":"        return (range_end - range_start) + 1"},{"line_number":577,"context_line":"    else:"},{"line_number":578,"context_line":"        return int(seg_dict[\u0027bytes\u0027])"},{"line_number":579,"context_line":""},{"line_number":580,"context_line":""},{"line_number":581,"context_line":"class SloGetContext(WSGIContext):"}],"source_content_type":"text/x-python","patch_set":1,"id":"e7095c08_73e5d299","line":578,"updated":"2023-09-02 13:30:53.000000000","message":"i love extracting methods to functions when they don\u0027t need self!","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"50efdb2c7c931fdc29acd91144964927fcff47e3","unresolved":false,"context_lines":[{"line_number":575,"context_line":"        range_start, range_end \u003d [int(x) for x in seg_range.split(\u0027-\u0027)]"},{"line_number":576,"context_line":"        return (range_end - range_start) + 1"},{"line_number":577,"context_line":"    else:"},{"line_number":578,"context_line":"        return int(seg_dict[\u0027bytes\u0027])"},{"line_number":579,"context_line":""},{"line_number":580,"context_line":""},{"line_number":581,"context_line":"class SloGetContext(WSGIContext):"}],"source_content_type":"text/x-python","patch_set":1,"id":"adfa368f_63477b9b","line":578,"in_reply_to":"e7095c08_73e5d299","updated":"2023-09-12 16:43:32.000000000","message":"Ack","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":620,"context_line":""},{"line_number":621,"context_line":"        slo_attrs \u003d _check_headers_for_slo_attrs(sub_resp.headers.items())"},{"line_number":622,"context_line":"        try:"},{"line_number":623,"context_line":"            return self._parse_segments(sub_resp.app_iter, slo_attrs)"},{"line_number":624,"context_line":"        except HTTPException as err:"},{"line_number":625,"context_line":"            raise ListingIterError("},{"line_number":626,"context_line":"                \u0027while fetching %s, JSON-decoding of submanifest %s \u0027"}],"source_content_type":"text/x-python","patch_set":1,"id":"77e95f03_5a138e4f","line":623,"updated":"2023-09-02 13:30:53.000000000","message":"consistent parsing of manifests between SLO and sub-slo seems like a good thing and simplifies some duplicated defensiveness in SegmentedIterable\n\n... but in reality it\u0027s possible calculating the legacy slo_attrs is not needed for streaming legacy subslo","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"74de58a3ae58aceac9bd7ae9508506e58211d515","unresolved":false,"context_lines":[{"line_number":620,"context_line":""},{"line_number":621,"context_line":"        slo_attrs \u003d _check_headers_for_slo_attrs(sub_resp.headers.items())"},{"line_number":622,"context_line":"        try:"},{"line_number":623,"context_line":"            return self._parse_segments(sub_resp.app_iter, slo_attrs)"},{"line_number":624,"context_line":"        except HTTPException as err:"},{"line_number":625,"context_line":"            raise ListingIterError("},{"line_number":626,"context_line":"                \u0027while fetching %s, JSON-decoding of submanifest %s \u0027"}],"source_content_type":"text/x-python","patch_set":1,"id":"b3e41f2e_cb6a2478","line":623,"in_reply_to":"77e95f03_5a138e4f","updated":"2023-11-02 15:55:22.000000000","message":"Ack","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":621,"context_line":"        slo_attrs \u003d _check_headers_for_slo_attrs(sub_resp.headers.items())"},{"line_number":622,"context_line":"        try:"},{"line_number":623,"context_line":"            return self._parse_segments(sub_resp.app_iter, slo_attrs)"},{"line_number":624,"context_line":"        except HTTPException as err:"},{"line_number":625,"context_line":"            raise ListingIterError("},{"line_number":626,"context_line":"                \u0027while fetching %s, JSON-decoding of submanifest %s \u0027"},{"line_number":627,"context_line":"                \u0027failed with %s\u0027 % (req.path, sub_req.path, err))"}],"source_content_type":"text/x-python","patch_set":1,"id":"ed2cb76a_b4ec355d","line":624,"updated":"2023-09-02 13:30:53.000000000","message":"it looks a little funky to have a method named \"parse\" raise an HTTPException","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":621,"context_line":"        slo_attrs \u003d _check_headers_for_slo_attrs(sub_resp.headers.items())"},{"line_number":622,"context_line":"        try:"},{"line_number":623,"context_line":"            return self._parse_segments(sub_resp.app_iter, slo_attrs)"},{"line_number":624,"context_line":"        except HTTPException as err:"},{"line_number":625,"context_line":"            raise ListingIterError("},{"line_number":626,"context_line":"                \u0027while fetching %s, JSON-decoding of submanifest %s \u0027"},{"line_number":627,"context_line":"                \u0027failed with %s\u0027 % (req.path, sub_req.path, err))"}],"source_content_type":"text/x-python","patch_set":1,"id":"5e683a94_749b9080","line":624,"in_reply_to":"ed2cb76a_b4ec355d","updated":"2023-09-27 20:44:30.000000000","message":"maybe it\u0027s less broad than the ValueError - the only alternative I can think of is having it raise the ValueError and then translating it to a 503 in the other two places we use it (fetching SLO objects \u0026 and converting manifests\u003dget\u0026format\u003draw responses)","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":false,"context_lines":[{"line_number":684,"context_line":"          sub-segments"},{"line_number":685,"context_line":"        :param recursion_depth: max number of recursive sub_slo calls"},{"line_number":686,"context_line":"        \"\"\""},{"line_number":687,"context_line":""},{"line_number":688,"context_line":"        last_sub_path \u003d None"},{"line_number":689,"context_line":"        for seg_dict in segments:"},{"line_number":690,"context_line":"            seg_length \u003d seg_dict[\u0027segment_length\u0027]"}],"source_content_type":"text/x-python","patch_set":1,"id":"376088f7_160fda38","line":687,"updated":"2023-09-02 13:30:53.000000000","message":"yay doc strings, boo extra newline","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":687,"context_line":""},{"line_number":688,"context_line":"        last_sub_path \u003d None"},{"line_number":689,"context_line":"        for seg_dict in segments:"},{"line_number":690,"context_line":"            seg_length \u003d seg_dict[\u0027segment_length\u0027]"},{"line_number":691,"context_line":"            if first_byte \u003e\u003d seg_length:"},{"line_number":692,"context_line":"                # don\u0027t need any bytes from this segment"},{"line_number":693,"context_line":"                first_byte -\u003d seg_length"}],"source_content_type":"text/x-python","patch_set":1,"id":"9d04c940_696faddb","line":690,"updated":"2023-09-02 13:30:53.000000000","message":"this is the other reason sub-slo needed consistent parsing","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"50efdb2c7c931fdc29acd91144964927fcff47e3","unresolved":false,"context_lines":[{"line_number":687,"context_line":""},{"line_number":688,"context_line":"        last_sub_path \u003d None"},{"line_number":689,"context_line":"        for seg_dict in segments:"},{"line_number":690,"context_line":"            seg_length \u003d seg_dict[\u0027segment_length\u0027]"},{"line_number":691,"context_line":"            if first_byte \u003e\u003d seg_length:"},{"line_number":692,"context_line":"                # don\u0027t need any bytes from this segment"},{"line_number":693,"context_line":"                first_byte -\u003d seg_length"}],"source_content_type":"text/x-python","patch_set":1,"id":"d8816c5c_1b150e88","line":690,"in_reply_to":"9d04c940_696faddb","updated":"2023-09-12 16:43:32.000000000","message":"Ack","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":841,"context_line":"                seg_dict[\u0027raw_data\u0027] \u003d base64.b64decode(seg_dict.pop(\u0027data\u0027))"},{"line_number":842,"context_line":"            if config_true_value(seg_dict.get(\u0027sub_slo\u0027)):"},{"line_number":843,"context_line":"                override_bytes_from_content_type("},{"line_number":844,"context_line":"                    seg_dict, logger\u003dself.slo.logger)"},{"line_number":845,"context_line":"            seg_dict[\u0027segment_length\u0027] \u003d _segment_length(seg_dict)"},{"line_number":846,"context_line":""},{"line_number":847,"context_line":"    def _calculate_slo_attributes(self, segments, slo_attrs):"}],"source_content_type":"text/x-python","patch_set":1,"id":"f306bbaf_6e3ab6a4","line":844,"updated":"2023-09-02 13:30:53.000000000","message":"if I inline raw_data decoding to _segment_length - maybe I should do the override_bytes_from_content_length too (needs a self.slo.logger, tho)","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":841,"context_line":"                seg_dict[\u0027raw_data\u0027] \u003d base64.b64decode(seg_dict.pop(\u0027data\u0027))"},{"line_number":842,"context_line":"            if config_true_value(seg_dict.get(\u0027sub_slo\u0027)):"},{"line_number":843,"context_line":"                override_bytes_from_content_type("},{"line_number":844,"context_line":"                    seg_dict, logger\u003dself.slo.logger)"},{"line_number":845,"context_line":"            seg_dict[\u0027segment_length\u0027] \u003d _segment_length(seg_dict)"},{"line_number":846,"context_line":""},{"line_number":847,"context_line":"    def _calculate_slo_attributes(self, segments, slo_attrs):"}],"source_content_type":"text/x-python","patch_set":1,"id":"01d12ae7_aef53ed1","line":844,"in_reply_to":"f306bbaf_6e3ab6a4","updated":"2023-09-27 20:44:30.000000000","message":"bah more of the same, I think the _segment_length function should just get inlined to this method (or it should all get pulled into a method that passes in (segments, logger)","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":false,"context_lines":[{"line_number":997,"context_line":"        that was put in through ?multipart-manifest\u003dput"},{"line_number":998,"context_line":""},{"line_number":999,"context_line":"        :param resp_headers: response headers"},{"line_number":1000,"context_line":"        :param resp_iter: a response iterable"},{"line_number":1001,"context_line":"        \"\"\""},{"line_number":1002,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":1003,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"7a7b3c46_f5eb0dcf","line":1000,"updated":"2023-09-02 13:30:53.000000000","message":"response_headers is unumsed and it returns the un-encoded raw format data","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":1027,"context_line":"            raise HTTPServerError(msg)"},{"line_number":1028,"context_line":"        return segments"},{"line_number":1029,"context_line":""},{"line_number":1030,"context_line":"    def _build_resp_iter(self, req, segments, slo_attrs):"},{"line_number":1031,"context_line":"        if req.range:"},{"line_number":1032,"context_line":"            byteranges \u003d ["},{"line_number":1033,"context_line":"                # For some reason, swob.Range.ranges_for_length adds 1 to the"}],"source_content_type":"text/x-python","patch_set":1,"id":"909a8edc_97b71908","line":1030,"updated":"2023-09-02 13:30:53.000000000","message":"could use a docstring","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":1027,"context_line":"            raise HTTPServerError(msg)"},{"line_number":1028,"context_line":"        return segments"},{"line_number":1029,"context_line":""},{"line_number":1030,"context_line":"    def _build_resp_iter(self, req, segments, slo_attrs):"},{"line_number":1031,"context_line":"        if req.range:"},{"line_number":1032,"context_line":"            byteranges \u003d ["},{"line_number":1033,"context_line":"                # For some reason, swob.Range.ranges_for_length adds 1 to the"}],"source_content_type":"text/x-python","patch_set":1,"id":"55f6a0ed_e1d29ed1","line":1030,"in_reply_to":"909a8edc_97b71908","updated":"2023-09-27 20:44:30.000000000","message":"Done","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"e63a9009d9e931d781b38dc1ad41a39cb89b75a0","unresolved":false,"context_lines":[{"line_number":1027,"context_line":"            raise HTTPServerError(msg)"},{"line_number":1028,"context_line":"        return segments"},{"line_number":1029,"context_line":""},{"line_number":1030,"context_line":"    def _build_resp_iter(self, req, segments, slo_attrs):"},{"line_number":1031,"context_line":"        if req.range:"},{"line_number":1032,"context_line":"            byteranges \u003d ["},{"line_number":1033,"context_line":"                # For some reason, swob.Range.ranges_for_length adds 1 to the"}],"source_content_type":"text/x-python","patch_set":1,"id":"daf8a4d0_16f5c4df","line":1030,"in_reply_to":"909a8edc_97b71908","updated":"2023-09-27 23:42:53.000000000","message":"Done","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":false,"context_lines":[{"line_number":1036,"context_line":"                in req.range.ranges_for_length(slo_attrs[\u0027size\u0027])]"},{"line_number":1037,"context_line":"        else:"},{"line_number":1038,"context_line":"            total_length \u003d sum(seg[\u0027segment_length\u0027]"},{"line_number":1039,"context_line":"                               for seg in segments)"},{"line_number":1040,"context_line":"            byteranges \u003d [(0, total_length - 1)]"},{"line_number":1041,"context_line":""},{"line_number":1042,"context_line":"        ver, account, _junk \u003d req.split_path(3, 3, rest_with_last\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":1,"id":"f9af2596_af8cfdd5","line":1039,"updated":"2023-09-02 13:30:53.000000000","message":"this should use slo_attrs[\u0027size\u0027]","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"adf28673680ecb1082e348dd76d10f04062e9d17","unresolved":true,"context_lines":[{"line_number":1513,"context_line":"        vrs, account, _junk \u003d req.split_path(2, 3, True)"},{"line_number":1514,"context_line":"        new_env \u003d req.environ.copy()"},{"line_number":1515,"context_line":"        new_env[\u0027REQUEST_METHOD\u0027] \u003d \u0027GET\u0027"},{"line_number":1516,"context_line":"        del new_env[\u0027wsgi.input\u0027]"},{"line_number":1517,"context_line":"        new_env[\u0027QUERY_STRING\u0027] \u003d \u0027multipart-manifest\u003dget\u0027"},{"line_number":1518,"context_line":"        if \u0027version-id\u0027 in req.params:"},{"line_number":1519,"context_line":"            new_env[\u0027QUERY_STRING\u0027] +\u003d \\"}],"source_content_type":"text/x-python","patch_set":1,"id":"d7ab33f9_44e76f54","line":1516,"updated":"2023-09-02 13:30:53.000000000","message":"i\u0027m still trying to get my new editor\u0027s flake8 working happily with swift, but I know least Ash also noticed this and I think everyone agrees it looks better even if swift\u0027s flake8 doesn\u0027t seem to care (why doesn\u0027t it?)","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":false,"context_lines":[{"line_number":1513,"context_line":"        vrs, account, _junk \u003d req.split_path(2, 3, True)"},{"line_number":1514,"context_line":"        new_env \u003d req.environ.copy()"},{"line_number":1515,"context_line":"        new_env[\u0027REQUEST_METHOD\u0027] \u003d \u0027GET\u0027"},{"line_number":1516,"context_line":"        del new_env[\u0027wsgi.input\u0027]"},{"line_number":1517,"context_line":"        new_env[\u0027QUERY_STRING\u0027] \u003d \u0027multipart-manifest\u003dget\u0027"},{"line_number":1518,"context_line":"        if \u0027version-id\u0027 in req.params:"},{"line_number":1519,"context_line":"            new_env[\u0027QUERY_STRING\u0027] +\u003d \\"}],"source_content_type":"text/x-python","patch_set":1,"id":"1f179754_b4dfc01d","line":1516,"in_reply_to":"7c40fe21_433ba645","updated":"2023-09-21 21:46:09.000000000","message":"well, today I switched back to vim which already uses whatever flake8 I have on my command line if you have the one our test-requirements recommends this code is fine so I reverted this part of the diff.\n\nI\u0027m also not that interested in trying to uprev to a new version of hacking.","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"987511a3925ea455df4a9a4589f8d754e30f3b87","unresolved":true,"context_lines":[{"line_number":1513,"context_line":"        vrs, account, _junk \u003d req.split_path(2, 3, True)"},{"line_number":1514,"context_line":"        new_env \u003d req.environ.copy()"},{"line_number":1515,"context_line":"        new_env[\u0027REQUEST_METHOD\u0027] \u003d \u0027GET\u0027"},{"line_number":1516,"context_line":"        del new_env[\u0027wsgi.input\u0027]"},{"line_number":1517,"context_line":"        new_env[\u0027QUERY_STRING\u0027] \u003d \u0027multipart-manifest\u003dget\u0027"},{"line_number":1518,"context_line":"        if \u0027version-id\u0027 in req.params:"},{"line_number":1519,"context_line":"            new_env[\u0027QUERY_STRING\u0027] +\u003d \\"}],"source_content_type":"text/x-python","patch_set":1,"id":"7c40fe21_433ba645","line":1516,"in_reply_to":"d7ab33f9_44e76f54","updated":"2023-09-08 22:34:58.000000000","message":"\u003e swift\u0027s flake8 doesn\u0027t seem to care (why doesn\u0027t it?)\n\nIt\u0027s dated: we\u0027ve got hacking [pretty tightly-constrained](https://github.com/openstack/swift/blob/master/test-requirements.txt#L6), keeping us back on 2.0.0 from 2019, which in turn keeps [flake8 on `\u003c4.0.0,\u003e\u003d3.6.0`](https://github.com/openstack/hacking/blob/2.0.0/requirements.txt#L1), which in turn keeps [pycodestyle on `\u003e\u003d2.7.0,\u003c2.8.0`](https://github.com/PyCQA/flake8/blob/3.9.2/setup.cfg#L45).\n\nMore recent hacking brings [flake8 up to `~\u003d5.0.1`](https://github.com/openstack/hacking/blob/6.0.1/requirements.txt#L1), so we get [pycodestyle up to `\u003e\u003d2.9.0,\u003c2.10.0`](https://github.com/PyCQA/flake8/blob/5.0.4/setup.cfg#L43C16-L43C31) -- apparently `del(` [started tripping warnings in 2.9.0](https://github.com/PyCQA/pycodestyle/pull/1063).\n\nI\u0027m not *opposed* to updating hacking -- just haven\u0027t bothered to do it yet myself.","commit_id":"90f3d9e4c25eafd11bebb9087141702b7668c646"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c523ec9131b5ebc8248acb7b9453641079096029","unresolved":true,"context_lines":[{"line_number":928,"context_line":"            # that turns out NOT to be a manifest then it\u0027s our job to turn"},{"line_number":929,"context_line":"            # the response it back into 206"},{"line_number":930,"context_line":"            conditional_response\u003d(replace_headers or"},{"line_number":931,"context_line":"                                  self._response_status_int \u003d\u003d 200)"},{"line_number":932,"context_line":"        )"},{"line_number":933,"context_line":"        if replace_headers:"},{"line_number":934,"context_line":"            resp.headers.update(replace_headers)"}],"source_content_type":"text/x-python","patch_set":3,"id":"9e94da81_a9f2ce47","line":931,"updated":"2023-09-03 14:43:06.000000000","message":"so swob\u0027s \"condtional_response\" boolean seems to be for turning successful responses in to (if-match)errors (or ranges or range errors), so I don\u0027t understand why it\u0027s always correct to set conditional_response to True for our slo/manifest responses.  But it seems necessary to make tests happy for some of the new-style manifest error responses, which mess with content-length in a way I don\u0027t fully understand.\n\nhttps://github.com/NVIDIA/swift/blob/master/test/unit/common/middleware/test_slo.py#L1940\n\n^ even if that\u0027s a GET request the \u0027Content-Length\u0027 on these 416\u0027s is zero!?","commit_id":"72af9e231580ba1c150e8fed572219f33a52db5d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"74de58a3ae58aceac9bd7ae9508506e58211d515","unresolved":false,"context_lines":[{"line_number":928,"context_line":"            # that turns out NOT to be a manifest then it\u0027s our job to turn"},{"line_number":929,"context_line":"            # the response it back into 206"},{"line_number":930,"context_line":"            conditional_response\u003d(replace_headers or"},{"line_number":931,"context_line":"                                  self._response_status_int \u003d\u003d 200)"},{"line_number":932,"context_line":"        )"},{"line_number":933,"context_line":"        if replace_headers:"},{"line_number":934,"context_line":"            resp.headers.update(replace_headers)"}],"source_content_type":"text/x-python","patch_set":3,"id":"8caeddb4_8ea56cf0","line":931,"in_reply_to":"9e94da81_a9f2ce47","updated":"2023-11-02 15:55:22.000000000","message":"Ack","commit_id":"72af9e231580ba1c150e8fed572219f33a52db5d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c523ec9131b5ebc8248acb7b9453641079096029","unresolved":true,"context_lines":[{"line_number":935,"context_line":"        # I obviously don\u0027t understand how swob\u0027s conditional resp interface is"},{"line_number":936,"context_line":"        # supposed to work"},{"line_number":937,"context_line":"        resp._conditional_etag \u003d resolve_etag_is_at_header("},{"line_number":938,"context_line":"            req, self._response_headers) or resp.headers[\u0027Etag\u0027]"},{"line_number":939,"context_line":"        return resp(req.environ, start_response)"},{"line_number":940,"context_line":""},{"line_number":941,"context_line":"    def handle_slo_get_or_head(self, req, start_response):"}],"source_content_type":"text/x-python","patch_set":3,"id":"245664a3_cc516fed","line":938,"updated":"2023-09-03 14:43:06.000000000","message":"You\u0027d think at this point resp.headers[\u0027Etag\u0027] would be good enough because _return_slo_response already \"fixed\" it in replace_headers, but some unittest sneaks in a custom x-backend-etag-is-at header and I guess that interface supports a list or something so we have to use the resolve helper again.\n\nI could make it work as a kwarg to Response, but I\u0027d have to dig the Etag out of the self._response_headers list for when resolve_etag_is_at returns None\n\nI noticed resolve_etag_is_at_header already converts self._response_headers to a HeaderKeyDict so I tried to just have it return Etag when it doesn\u0027t find an alternative but I think something else broke; I should maybe look into that more closely.","commit_id":"72af9e231580ba1c150e8fed572219f33a52db5d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"74de58a3ae58aceac9bd7ae9508506e58211d515","unresolved":false,"context_lines":[{"line_number":935,"context_line":"        # I obviously don\u0027t understand how swob\u0027s conditional resp interface is"},{"line_number":936,"context_line":"        # supposed to work"},{"line_number":937,"context_line":"        resp._conditional_etag \u003d resolve_etag_is_at_header("},{"line_number":938,"context_line":"            req, self._response_headers) or resp.headers[\u0027Etag\u0027]"},{"line_number":939,"context_line":"        return resp(req.environ, start_response)"},{"line_number":940,"context_line":""},{"line_number":941,"context_line":"    def handle_slo_get_or_head(self, req, start_response):"}],"source_content_type":"text/x-python","patch_set":3,"id":"32aea4f5_fa2cd499","line":938,"in_reply_to":"245664a3_cc516fed","updated":"2023-11-02 15:55:22.000000000","message":"Ack","commit_id":"72af9e231580ba1c150e8fed572219f33a52db5d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c0b5e37e0cd9f9bb3e6523dc6ab176d09fbed1c9","unresolved":true,"context_lines":[{"line_number":811,"context_line":"            return resp_iter"},{"line_number":812,"context_line":""},{"line_number":813,"context_line":"        # Handle pass-through request for the manifest itself"},{"line_number":814,"context_line":"        if req.params.get(\u0027multipart-manifest\u0027) \u003d\u003d \u0027get\u0027:"},{"line_number":815,"context_line":"            if req.params.get(\u0027format\u0027) \u003d\u003d \u0027raw\u0027:"},{"line_number":816,"context_line":"                resp_iter \u003d self.convert_segment_listing("},{"line_number":817,"context_line":"                    self._response_headers, resp_iter)"}],"source_content_type":"text/x-python","patch_set":4,"id":"e229a5b9_895da857","side":"PARENT","line":814,"updated":"2023-09-06 15:18:31.000000000","message":"NB not conditional on the request method","commit_id":"e6f5ec39e631c24c124ca88610c88a838f7c6d11"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":false,"context_lines":[{"line_number":811,"context_line":"            return resp_iter"},{"line_number":812,"context_line":""},{"line_number":813,"context_line":"        # Handle pass-through request for the manifest itself"},{"line_number":814,"context_line":"        if req.params.get(\u0027multipart-manifest\u0027) \u003d\u003d \u0027get\u0027:"},{"line_number":815,"context_line":"            if req.params.get(\u0027format\u0027) \u003d\u003d \u0027raw\u0027:"},{"line_number":816,"context_line":"                resp_iter \u003d self.convert_segment_listing("},{"line_number":817,"context_line":"                    self._response_headers, resp_iter)"}],"source_content_type":"text/x-python","patch_set":4,"id":"a7252b76_180ecb88","side":"PARENT","line":814,"in_reply_to":"e229a5b9_895da857","updated":"2023-09-21 21:46:09.000000000","message":"ACK, I think when we fix lp bug #2029174 we\u0027ll have to fix the logic in _need_to_refetch_manifest","commit_id":"e6f5ec39e631c24c124ca88610c88a838f7c6d11"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c0b5e37e0cd9f9bb3e6523dc6ab176d09fbed1c9","unresolved":true,"context_lines":[{"line_number":762,"context_line":"        # mean that resp_iter contains the entire SLO manifest. If it doesn\u0027t,"},{"line_number":763,"context_line":"        # we may need to make a second request to actually get the whole thing."},{"line_number":764,"context_line":""},{"line_number":765,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 and is_manifest_get:"},{"line_number":766,"context_line":"            return False"},{"line_number":767,"context_line":""},{"line_number":768,"context_line":"        # These are based on etag, and the SLO\u0027s etag is almost certainly not"}],"source_content_type":"text/x-python","patch_set":4,"id":"82289c38_43eb0853","line":765,"updated":"2023-09-06 15:18:31.000000000","message":"IIUC on master we never even got to _need_to_refetch_manifest when manifest_get is true, for HEAD or GET - i.e. manifest was never refetched for a GET with manifest_get (which I think made sense: we only refetch in case the first request got just a Range of the manifest, but with manifest_get that\u0027s all we\u0027d want to return to the client)","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":false,"context_lines":[{"line_number":762,"context_line":"        # mean that resp_iter contains the entire SLO manifest. If it doesn\u0027t,"},{"line_number":763,"context_line":"        # we may need to make a second request to actually get the whole thing."},{"line_number":764,"context_line":""},{"line_number":765,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 and is_manifest_get:"},{"line_number":766,"context_line":"            return False"},{"line_number":767,"context_line":""},{"line_number":768,"context_line":"        # These are based on etag, and the SLO\u0027s etag is almost certainly not"}],"source_content_type":"text/x-python","patch_set":4,"id":"0aac518a_2c16eecb","line":765,"in_reply_to":"82289c38_43eb0853","updated":"2023-09-21 21:46:09.000000000","message":"Done","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c0b5e37e0cd9f9bb3e6523dc6ab176d09fbed1c9","unresolved":true,"context_lines":[{"line_number":771,"context_line":"        # we can avoid re-fetching the manifest if we got a successful"},{"line_number":772,"context_line":"        # response."},{"line_number":773,"context_line":"        is_conditional \u003d self._response_status_int in (304, 412)"},{"line_number":774,"context_line":"        if slo_attrs[\u0027is_legacy\u0027] and (req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional):"},{"line_number":775,"context_line":"            return True"},{"line_number":776,"context_line":""},{"line_number":777,"context_line":"        # new-sytle maifest metadata allows object server to ignore range"}],"source_content_type":"text/x-python","patch_set":4,"id":"dbac7790_6b5c9db1","line":774,"updated":"2023-09-06 15:18:31.000000000","message":"ok, \n\nlegacy but not manifest_get, HEAD - we have to refetch to get the etag and \n\nlegacy and conditional - we have to refetch","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":false,"context_lines":[{"line_number":771,"context_line":"        # we can avoid re-fetching the manifest if we got a successful"},{"line_number":772,"context_line":"        # response."},{"line_number":773,"context_line":"        is_conditional \u003d self._response_status_int in (304, 412)"},{"line_number":774,"context_line":"        if slo_attrs[\u0027is_legacy\u0027] and (req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional):"},{"line_number":775,"context_line":"            return True"},{"line_number":776,"context_line":""},{"line_number":777,"context_line":"        # new-sytle maifest metadata allows object server to ignore range"}],"source_content_type":"text/x-python","patch_set":4,"id":"df925e9f_a6b7f594","line":774,"in_reply_to":"dbac7790_6b5c9db1","updated":"2023-09-21 21:46:09.000000000","message":"Ack","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c0b5e37e0cd9f9bb3e6523dc6ab176d09fbed1c9","unresolved":true,"context_lines":[{"line_number":772,"context_line":"        # response."},{"line_number":773,"context_line":"        is_conditional \u003d self._response_status_int in (304, 412)"},{"line_number":774,"context_line":"        if slo_attrs[\u0027is_legacy\u0027] and (req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional):"},{"line_number":775,"context_line":"            return True"},{"line_number":776,"context_line":""},{"line_number":777,"context_line":"        # new-sytle maifest metadata allows object server to ignore range"},{"line_number":778,"context_line":"        is_range_response \u003d self._response_status_int in (206, 416)"}],"source_content_type":"text/x-python","patch_set":4,"id":"4881995c_933c2f09","line":775,"updated":"2023-09-06 15:18:31.000000000","message":"perhaps be more explicit about HEADs:\n\n```\nif req.method \u003d\u003d \u0027HEAD\u0027:\n    return slo_attrs[\u0027is_legacy\u0027]\n\nif is_conditional and slo_attrs[\u0027is_legacy\u0027]:\n    return True\n# else: it\u0027s a GET, do we have the full body?...\n```\n\nhmmm, but what about a non-legacy conditional HEAD? A: that\u0027s OK, no refetch for a modern HEAD, period: we have all the headers we need.","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":false,"context_lines":[{"line_number":772,"context_line":"        # response."},{"line_number":773,"context_line":"        is_conditional \u003d self._response_status_int in (304, 412)"},{"line_number":774,"context_line":"        if slo_attrs[\u0027is_legacy\u0027] and (req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional):"},{"line_number":775,"context_line":"            return True"},{"line_number":776,"context_line":""},{"line_number":777,"context_line":"        # new-sytle maifest metadata allows object server to ignore range"},{"line_number":778,"context_line":"        is_range_response \u003d self._response_status_int in (206, 416)"}],"source_content_type":"text/x-python","patch_set":4,"id":"8cba4de1_7fcbaca0","line":775,"in_reply_to":"4881995c_933c2f09","updated":"2023-09-21 21:46:09.000000000","message":"There\u0027s some conditions coming around the corner where a HEAD request even on a mondern manifest will have to refetch, so I like that better.  #willfix","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c0b5e37e0cd9f9bb3e6523dc6ab176d09fbed1c9","unresolved":true,"context_lines":[{"line_number":774,"context_line":"        if slo_attrs[\u0027is_legacy\u0027] and (req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional):"},{"line_number":775,"context_line":"            return True"},{"line_number":776,"context_line":""},{"line_number":777,"context_line":"        # new-sytle maifest metadata allows object server to ignore range"},{"line_number":778,"context_line":"        is_range_response \u003d self._response_status_int in (206, 416)"},{"line_number":779,"context_line":"        if is_range_response:"},{"line_number":780,"context_line":"            content_range \u003d \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"5d0138e1_5e6bc875","line":777,"range":{"start_line":777,"start_character":10,"end_line":777,"end_character":28},"updated":"2023-09-06 15:18:31.000000000","message":"nit: typos","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":false,"context_lines":[{"line_number":774,"context_line":"        if slo_attrs[\u0027is_legacy\u0027] and (req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional):"},{"line_number":775,"context_line":"            return True"},{"line_number":776,"context_line":""},{"line_number":777,"context_line":"        # new-sytle maifest metadata allows object server to ignore range"},{"line_number":778,"context_line":"        is_range_response \u003d self._response_status_int in (206, 416)"},{"line_number":779,"context_line":"        if is_range_response:"},{"line_number":780,"context_line":"            content_range \u003d \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"965be321_5527806f","line":777,"range":{"start_line":777,"start_character":10,"end_line":777,"end_character":28},"in_reply_to":"48e0df04_1b8f7587","updated":"2023-09-21 21:46:09.000000000","message":"iwc, did you mean to Ack this comment w/o fixing the typo?","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"50efdb2c7c931fdc29acd91144964927fcff47e3","unresolved":false,"context_lines":[{"line_number":774,"context_line":"        if slo_attrs[\u0027is_legacy\u0027] and (req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional):"},{"line_number":775,"context_line":"            return True"},{"line_number":776,"context_line":""},{"line_number":777,"context_line":"        # new-sytle maifest metadata allows object server to ignore range"},{"line_number":778,"context_line":"        is_range_response \u003d self._response_status_int in (206, 416)"},{"line_number":779,"context_line":"        if is_range_response:"},{"line_number":780,"context_line":"            content_range \u003d \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"48e0df04_1b8f7587","line":777,"range":{"start_line":777,"start_character":10,"end_line":777,"end_character":28},"in_reply_to":"5d0138e1_5e6bc875","updated":"2023-09-12 16:43:32.000000000","message":"Ack","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c0b5e37e0cd9f9bb3e6523dc6ab176d09fbed1c9","unresolved":true,"context_lines":[{"line_number":961,"context_line":"            update_ignore_range_header(req, \u0027X-Static-Large-Object\u0027)"},{"line_number":962,"context_line":""},{"line_number":963,"context_line":"        # process request and ensure response is from a SLO manifest"},{"line_number":964,"context_line":"        resp_iter \u003d self._app_call(req.environ)"},{"line_number":965,"context_line":"        slo_attrs \u003d _check_headers_for_slo_attrs(self._response_headers)"},{"line_number":966,"context_line":"        if self._need_to_refetch_manifest(req, slo_attrs, is_manifest_get):"},{"line_number":967,"context_line":"            slo_attrs, resp_iter \u003d self._refetch_manifest("}],"source_content_type":"text/x-python","patch_set":4,"id":"21d35b42_48e18eec","line":964,"updated":"2023-09-06 15:18:31.000000000","message":"it\u0027s a little odd that resp_iter is passed back from _app_call but the status and headers are set as instance variables - it would be more consistent if _app_call also set self._resp_iter","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":false,"context_lines":[{"line_number":961,"context_line":"            update_ignore_range_header(req, \u0027X-Static-Large-Object\u0027)"},{"line_number":962,"context_line":""},{"line_number":963,"context_line":"        # process request and ensure response is from a SLO manifest"},{"line_number":964,"context_line":"        resp_iter \u003d self._app_call(req.environ)"},{"line_number":965,"context_line":"        slo_attrs \u003d _check_headers_for_slo_attrs(self._response_headers)"},{"line_number":966,"context_line":"        if self._need_to_refetch_manifest(req, slo_attrs, is_manifest_get):"},{"line_number":967,"context_line":"            slo_attrs, resp_iter \u003d self._refetch_manifest("}],"source_content_type":"text/x-python","patch_set":4,"id":"6354c870_99c7d710","line":964,"in_reply_to":"21d35b42_48e18eec","updated":"2023-09-21 21:46:09.000000000","message":"I think it\u0027s trying to take on some wsgi start_reponse/resp_iter like pattern.  I would actually prefer it go the other way and return everything - like a swob.Response!  Having it overwrite the state from the last reques is weird.\n\nBut regardless the WSGIContext is a pre-existing common primative and refactoring it would be well out of scope.","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c0b5e37e0cd9f9bb3e6523dc6ab176d09fbed1c9","unresolved":true,"context_lines":[{"line_number":962,"context_line":""},{"line_number":963,"context_line":"        # process request and ensure response is from a SLO manifest"},{"line_number":964,"context_line":"        resp_iter \u003d self._app_call(req.environ)"},{"line_number":965,"context_line":"        slo_attrs \u003d _check_headers_for_slo_attrs(self._response_headers)"},{"line_number":966,"context_line":"        if self._need_to_refetch_manifest(req, slo_attrs, is_manifest_get):"},{"line_number":967,"context_line":"            slo_attrs, resp_iter \u003d self._refetch_manifest("},{"line_number":968,"context_line":"                req, resp_iter, slo_attrs)"}],"source_content_type":"text/x-python","patch_set":4,"id":"39cf37dc_8435af25","line":965,"updated":"2023-09-06 15:18:31.000000000","message":"I like moving the header processing out to a function - cleans up the main execution thread.\n\nBut \u0027check\u0027 implies (to me) some validation is happening, which I don\u0027t see...maybe `_extract_slo_attrs` ? (The docstring says \"Inspect response headers and extract any slo_attrs we can find\").\n\nAlso, this is called immediately after both times _app_call() is called. The headers could be extracted in _start_response and there could be instance variables like is_slo etc instead of passing round a dict.","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":false,"context_lines":[{"line_number":962,"context_line":""},{"line_number":963,"context_line":"        # process request and ensure response is from a SLO manifest"},{"line_number":964,"context_line":"        resp_iter \u003d self._app_call(req.environ)"},{"line_number":965,"context_line":"        slo_attrs \u003d _check_headers_for_slo_attrs(self._response_headers)"},{"line_number":966,"context_line":"        if self._need_to_refetch_manifest(req, slo_attrs, is_manifest_get):"},{"line_number":967,"context_line":"            slo_attrs, resp_iter \u003d self._refetch_manifest("},{"line_number":968,"context_line":"                req, resp_iter, slo_attrs)"}],"source_content_type":"text/x-python","patch_set":4,"id":"6b2c0077_19e2443a","line":965,"in_reply_to":"39cf37dc_8435af25","updated":"2023-09-21 21:46:09.000000000","message":"#willfix\n\nI think we use _app_call in lots of contexts, and I makes the most sense to check for slo_attrs when we expect them.  Having a PUT response set is_legacy \u003d False would be strange.\n\nI also don\u0027t like adding MORE instance variables, but can understand some folks IDE workflows prefer attributes to dictionary keys.","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c0b5e37e0cd9f9bb3e6523dc6ab176d09fbed1c9","unresolved":true,"context_lines":[{"line_number":967,"context_line":"            slo_attrs, resp_iter \u003d self._refetch_manifest("},{"line_number":968,"context_line":"                req, resp_iter, slo_attrs)"},{"line_number":969,"context_line":""},{"line_number":970,"context_line":"        if not slo_attrs[\u0027is_slo\u0027]:"},{"line_number":971,"context_line":"            # original or refetched object might not be SLO manifest"},{"line_number":972,"context_line":"            return self._return_response(req, start_response, resp_iter)"},{"line_number":973,"context_line":"        elif is_manifest_get:"}],"source_content_type":"text/x-python","patch_set":4,"id":"26135762_825e7f0f","line":970,"updated":"2023-09-06 15:18:31.000000000","message":"see above - can we just define the attrs as instance vars and write ``if not self.is_slo``? or at least use a NamedTuple for slo_attrs?","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":false,"context_lines":[{"line_number":967,"context_line":"            slo_attrs, resp_iter \u003d self._refetch_manifest("},{"line_number":968,"context_line":"                req, resp_iter, slo_attrs)"},{"line_number":969,"context_line":""},{"line_number":970,"context_line":"        if not slo_attrs[\u0027is_slo\u0027]:"},{"line_number":971,"context_line":"            # original or refetched object might not be SLO manifest"},{"line_number":972,"context_line":"            return self._return_response(req, start_response, resp_iter)"},{"line_number":973,"context_line":"        elif is_manifest_get:"}],"source_content_type":"text/x-python","patch_set":4,"id":"f143495b_786f68ec","line":970,"in_reply_to":"26135762_825e7f0f","updated":"2023-09-21 21:46:09.000000000","message":"NamedTuple seems like a reasonable compromise to me.  #willfix","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c0b5e37e0cd9f9bb3e6523dc6ab176d09fbed1c9","unresolved":true,"context_lines":[{"line_number":969,"context_line":""},{"line_number":970,"context_line":"        if not slo_attrs[\u0027is_slo\u0027]:"},{"line_number":971,"context_line":"            # original or refetched object might not be SLO manifest"},{"line_number":972,"context_line":"            return self._return_response(req, start_response, resp_iter)"},{"line_number":973,"context_line":"        elif is_manifest_get:"},{"line_number":974,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"},{"line_number":975,"context_line":"            return self._return_manifest_response(req, start_response,"}],"source_content_type":"text/x-python","patch_set":4,"id":"1023a1ce_1263af96","line":972,"updated":"2023-09-06 15:18:31.000000000","message":"there\u0027s a lot more going on in _return_response than we had on master ... I\u0027m not sure I yet understand the implications - but we may have already re-fetched manifest, which is different from master.","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":true,"context_lines":[{"line_number":969,"context_line":""},{"line_number":970,"context_line":"        if not slo_attrs[\u0027is_slo\u0027]:"},{"line_number":971,"context_line":"            # original or refetched object might not be SLO manifest"},{"line_number":972,"context_line":"            return self._return_response(req, start_response, resp_iter)"},{"line_number":973,"context_line":"        elif is_manifest_get:"},{"line_number":974,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"},{"line_number":975,"context_line":"            return self._return_manifest_response(req, start_response,"}],"source_content_type":"text/x-python","patch_set":4,"id":"5a898751_631e512b","line":972,"in_reply_to":"1023a1ce_1263af96","updated":"2023-09-21 21:46:09.000000000","message":"yes!  I think this needs additional consideratoin!\n\nI tried to split this out to _return_raw_response, but it\u0027s still a little wonky cause this code path covers a edge case where a refetched manifest turns out to be a non-slo but if the client sent range headers we expect swob to convert it.","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0011184508ee28592fcce43943da0f6637175d1e","unresolved":false,"context_lines":[{"line_number":969,"context_line":""},{"line_number":970,"context_line":"        if not slo_attrs[\u0027is_slo\u0027]:"},{"line_number":971,"context_line":"            # original or refetched object might not be SLO manifest"},{"line_number":972,"context_line":"            return self._return_response(req, start_response, resp_iter)"},{"line_number":973,"context_line":"        elif is_manifest_get:"},{"line_number":974,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"},{"line_number":975,"context_line":"            return self._return_manifest_response(req, start_response,"}],"source_content_type":"text/x-python","patch_set":4,"id":"7c389bcf_e81663c7","line":972,"in_reply_to":"5a898751_631e512b","updated":"2023-09-29 04:39:26.000000000","message":"Done","commit_id":"39aa4d013d8e5653c9a1812d6998585c293b7002"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"50efdb2c7c931fdc29acd91144964927fcff47e3","unresolved":false,"context_lines":[{"line_number":531,"context_line":"    return parsed_data"},{"line_number":532,"context_line":""},{"line_number":533,"context_line":""},{"line_number":534,"context_line":"def _check_headers_for_slo_attrs(response_headers):"},{"line_number":535,"context_line":"    \"\"\""},{"line_number":536,"context_line":"    Inspect response headers and extract any slo_attrs we can find."},{"line_number":537,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":5,"id":"247779eb_499c2f58","line":534,"updated":"2023-09-12 16:43:32.000000000","message":"This is a more correct position for this helper method, thanks for moving it out.","commit_id":"5e361f3a8a58e7b630ed8e1e88feb62ce38fe3fa"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c6d6f11c0aa8140a2c9071edb475d7003e009658","unresolved":true,"context_lines":[{"line_number":550,"context_line":"            slo_attrs[\u0027etag\u0027] \u003d value"},{"line_number":551,"context_line":"        elif header \u003d\u003d SYSMETA_SLO_SIZE:"},{"line_number":552,"context_line":"            # it\u0027s from sysmeta, so we don\u0027t worry about non-integer"},{"line_number":553,"context_line":"            # values here"},{"line_number":554,"context_line":"            slo_attrs[\u0027size\u0027] \u003d int(value)"},{"line_number":555,"context_line":"        elif header \u003d\u003d \u0027x-backend-timestamp\u0027:"},{"line_number":556,"context_line":"            slo_attrs[\u0027timestamp\u0027] \u003d value"}],"source_content_type":"text/x-python","patch_set":6,"id":"5529863c_40e4b2c7","line":553,"updated":"2023-09-08 22:52:30.000000000","message":"Ah! There were more logs, they just went to `stderr` and didn\u0027t have a txn id!\n```\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/utils/__init__.py\", line 3111, in _run_func\n    self._responses.put(func(*args, **kwargs))\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/middleware/slo.py\", line 1224, in do_head\n    return obj_name, sub_req.get_response(self)\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/swob.py\", line 1165, in get_response\n    status, headers, app_iter \u003d self.call_application(application)\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/swob.py\", line 1149, in call_application\n    app_iter \u003d application(self.environ, start_response)\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/middleware/slo.py\", line 1717, in __call__\n    if req.method \u003d\u003d \u0027GET\u0027 or req.method \u003d\u003d \u0027HEAD\u0027:\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/middleware/slo.py\", line 1160, in handle_multipart_get_or_head\n    return SloGetContext(self).handle_slo_get_or_head(req, start_response)\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/middleware/slo.py\", line 965, in handle_slo_get_or_head\n    slo_attrs \u003d _check_headers_for_slo_attrs(self._response_headers)\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/middleware/slo.py\", line 554, in _check_headers_for_slo_attrs\n    slo_attrs[\u0027size\u0027] \u003d int(value)\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/utils/__init__.py\", line 3111, in _run_func\n    self._responses.put(func(*args, **kwargs))\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/middleware/slo.py\", line 1224, in do_head\n    return obj_name, sub_req.get_response(self)\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/swob.py\", line 1165, in get_response\n    status, headers, app_iter \u003d self.call_application(application)\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/swob.py\", line 1149, in call_application\n    app_iter \u003d application(self.environ, start_response)\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/middleware/slo.py\", line 1717, in __call__\n    if req.method \u003d\u003d \u0027GET\u0027 or req.method \u003d\u003d \u0027HEAD\u0027:\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/middleware/slo.py\", line 1160, in handle_multipart_get_or_head\n    return SloGetContext(self).handle_slo_get_or_head(req, start_response)\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/middleware/slo.py\", line 965, in handle_slo_get_or_head\n    slo_attrs \u003d _check_headers_for_slo_attrs(self._response_headers)\nSep  8 22:36:15 saio proxy-server: STDERR: File \"/vagrant/swift/swift/common/middleware/slo.py\", line 554, in _check_headers_for_slo_attrs\n    slo_attrs[\u0027size\u0027] \u003d int(value)\n```\nLooks like we need to tolerate an empty value from https://github.com/openstack/swift/blob/master/swift/common/middleware/s3api/controllers/multi_upload.py#L234 -- maybe do something like this?\n```\ndiff --git a/swift/common/middleware/slo.py b/swift/common/middleware/slo.py\nindex 029d567c2..5c8608be1 100644\n--- a/swift/common/middleware/slo.py\n+++ b/swift/common/middleware/slo.py\n@@ -544,7 +544,9 @@ def _check_headers_for_slo_attrs(response_headers):\n     }\n     for header, value in response_headers:\n         header \u003d header.lower()\n-        if header \u003d\u003d \u0027x-static-large-object\u0027:\n+        if not value:\n+            continue\n+        elif header \u003d\u003d \u0027x-static-large-object\u0027:\n             slo_attrs[\u0027is_slo\u0027] \u003d config_true_value(value)\n         elif header \u003d\u003d SYSMETA_SLO_ETAG:\n             slo_attrs[\u0027etag\u0027] \u003d value\n```","commit_id":"659703e88701be60d9c6884edaa25af3d76bfe9b"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"50efdb2c7c931fdc29acd91144964927fcff47e3","unresolved":false,"context_lines":[{"line_number":550,"context_line":"            slo_attrs[\u0027etag\u0027] \u003d value"},{"line_number":551,"context_line":"        elif header \u003d\u003d SYSMETA_SLO_SIZE:"},{"line_number":552,"context_line":"            # it\u0027s from sysmeta, so we don\u0027t worry about non-integer"},{"line_number":553,"context_line":"            # values here"},{"line_number":554,"context_line":"            slo_attrs[\u0027size\u0027] \u003d int(value)"},{"line_number":555,"context_line":"        elif header \u003d\u003d \u0027x-backend-timestamp\u0027:"},{"line_number":556,"context_line":"            slo_attrs[\u0027timestamp\u0027] \u003d value"}],"source_content_type":"text/x-python","patch_set":6,"id":"c32c8e0a_5f8908f2","line":553,"in_reply_to":"5529863c_40e4b2c7","updated":"2023-09-12 16:43:32.000000000","message":"Done","commit_id":"659703e88701be60d9c6884edaa25af3d76bfe9b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"987511a3925ea455df4a9a4589f8d754e30f3b87","unresolved":true,"context_lines":[{"line_number":1358,"context_line":""},{"line_number":1359,"context_line":"            slo_etag \u003d md5(usedforsecurity\u003dFalse)"},{"line_number":1360,"context_line":"            for seg_data in data_for_storage:"},{"line_number":1361,"context_line":"                if \u0027data\u0027 in seg_data:"},{"line_number":1362,"context_line":"                    raw_data \u003d base64.b64decode(seg_data[\u0027data\u0027])"},{"line_number":1363,"context_line":"                    r \u003d md5(raw_data, usedforsecurity\u003dFalse).hexdigest()"},{"line_number":1364,"context_line":"                elif seg_data.get(\u0027range\u0027):"}],"source_content_type":"text/x-python","patch_set":6,"id":"9714e700_bbe7b5ae","line":1361,"updated":"2023-09-08 22:34:58.000000000","message":"I saw some `TypeError: argument of type \u0027NoneType\u0027 is not iterable` here while running the ceph tests with `ansible-playbook tools/playbooks/ceph-s3tests/run.yaml` ... so I guess `seg_data` was unexpectedly `None`? Still not seeing _how_, though... so I\u0027ll keep digging...\n\nRegardless, seems like we ought to give some credence to those ceph test failures.","commit_id":"659703e88701be60d9c6884edaa25af3d76bfe9b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":false,"context_lines":[{"line_number":1358,"context_line":""},{"line_number":1359,"context_line":"            slo_etag \u003d md5(usedforsecurity\u003dFalse)"},{"line_number":1360,"context_line":"            for seg_data in data_for_storage:"},{"line_number":1361,"context_line":"                if \u0027data\u0027 in seg_data:"},{"line_number":1362,"context_line":"                    raw_data \u003d base64.b64decode(seg_data[\u0027data\u0027])"},{"line_number":1363,"context_line":"                    r \u003d md5(raw_data, usedforsecurity\u003dFalse).hexdigest()"},{"line_number":1364,"context_line":"                elif seg_data.get(\u0027range\u0027):"}],"source_content_type":"text/x-python","patch_set":6,"id":"e18b0265_dc0121fe","line":1361,"in_reply_to":"9714e700_bbe7b5ae","updated":"2023-09-21 21:46:09.000000000","message":"Tim tracked this down to some weak header parsing in the refactoed code that got tripped on an ceph test that was doing s3api copy-part testing better than our suite; so we added some tests which have merged and this new implementation works better with the empty metadata values:\n\nhttps://review.opendev.org/c/openstack/swift/+/894403/","commit_id":"659703e88701be60d9c6884edaa25af3d76bfe9b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0ed95df8729bd159c7c5c9c6c93b18d6dec8c2e9","unresolved":false,"context_lines":[{"line_number":1358,"context_line":""},{"line_number":1359,"context_line":"            slo_etag \u003d md5(usedforsecurity\u003dFalse)"},{"line_number":1360,"context_line":"            for seg_data in data_for_storage:"},{"line_number":1361,"context_line":"                if \u0027data\u0027 in seg_data:"},{"line_number":1362,"context_line":"                    raw_data \u003d base64.b64decode(seg_data[\u0027data\u0027])"},{"line_number":1363,"context_line":"                    r \u003d md5(raw_data, usedforsecurity\u003dFalse).hexdigest()"},{"line_number":1364,"context_line":"                elif seg_data.get(\u0027range\u0027):"}],"source_content_type":"text/x-python","patch_set":6,"id":"754a2665_e99f1f2a","line":1361,"in_reply_to":"9714e700_bbe7b5ae","updated":"2023-09-21 22:50:35.000000000","message":"Yeah, this should be addressed now.","commit_id":"659703e88701be60d9c6884edaa25af3d76bfe9b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d85eb76f958330a44caf1c741505a964a1f2a254","unresolved":true,"context_lines":[{"line_number":867,"context_line":"            calculated_etag.update(r.encode(\u0027ascii\u0027))"},{"line_number":868,"context_line":""},{"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 _parse_segments(self, resp_iter, slo_attrs):"},{"line_number":873,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":11,"id":"565d2e52_ebf4e8c8","line":870,"updated":"2023-09-21 21:46:09.000000000","message":"FWIW this made it annoying to use a namedtuple, but ultimately being clear about (possible) mutation isn\u0027t such a bad thing; so I\u0027m not really *complaining* complaining.","commit_id":"e2346ecaa4dbe4797e6a70f3181fcf3005dbb30a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0011184508ee28592fcce43943da0f6637175d1e","unresolved":false,"context_lines":[{"line_number":867,"context_line":"            calculated_etag.update(r.encode(\u0027ascii\u0027))"},{"line_number":868,"context_line":""},{"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 _parse_segments(self, resp_iter, slo_attrs):"},{"line_number":873,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":11,"id":"7a80a896_30fcd563","line":870,"in_reply_to":"565d2e52_ebf4e8c8","updated":"2023-09-29 04:39:26.000000000","message":"Done","commit_id":"e2346ecaa4dbe4797e6a70f3181fcf3005dbb30a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0ed95df8729bd159c7c5c9c6c93b18d6dec8c2e9","unresolved":true,"context_lines":[{"line_number":532,"context_line":"    return parsed_data"},{"line_number":533,"context_line":""},{"line_number":534,"context_line":""},{"line_number":535,"context_line":"SloAttrs \u003d namedtuple(\u0027SloAttrs\u0027, \u0027is_slo is_legacy etag size timestamp\u0027)"},{"line_number":536,"context_line":""},{"line_number":537,"context_line":""},{"line_number":538,"context_line":"def _extract_slo_attrs_from_headers(response_headers):"}],"source_content_type":"text/x-python","patch_set":12,"id":"143f3b91_82c8ce33","line":535,"range":{"start_line":535,"start_character":11,"end_line":535,"end_character":21},"updated":"2023-09-21 22:50:35.000000000","message":"I wonder -- in a year or two (hopefully shorter! 🤞), would we want `namedtuple`, or `dataclass`?\n\nAlso: what do you think of constructions like this?\n```\nclass SloAttrs(namedtuple(\u0027SloAttrs\u0027, \u0027is_slo etag size timestamp\u0027)):\n    \"\"\"\n    A collection of SLO attributes\n\n    ``is_slo``\n       Boolean, taken from ``X-Static-Large-Object``. All SLOs will have\n       this as True going back to SLO\u0027s introduction in 1.8.0\n    ``etag``\n       String, taken from ``X-Object-Sysmeta-Slo-Etag``. SLOs written by\n       Swift 2.12.0 and later will include this.\n    ``size``\n       Integer, taken from ``X-Object-Sysmeta-Slo-Size``. SLOs written by\n       Swift 2.12.0 and later will include this.\n    ``timestamp``\n       String, taken from ``X-Backend-Timestamp``.\n    \"\"\"\n    @property\n    def is_legacy(self):\n        \"\"\"\n        Boolean; true for manifests written prior to Swift 2.12.0\n        \"\"\"\n        return not all((self.etag, self.size))\n\n    @classmethod\n    def from_headers(cls, response_headers):\n        \"\"\"\n        Inspect response headers and extract any slo_attrs we can find.\n        \"\"\"\n        is_slo \u003d False\n        etag \u003d None\n        size \u003d None\n        timestamp \u003d Timestamp(0)\n        for header, value in response_headers:\n            header \u003d header.lower()\n            if header \u003d\u003d \u0027x-static-large-object\u0027:\n                is_slo \u003d config_true_value(value)\n            elif header \u003d\u003d SYSMETA_SLO_ETAG:\n                etag \u003d value\n            elif header \u003d\u003d SYSMETA_SLO_SIZE:\n                # it\u0027s from sysmeta, so we don\u0027t worry about non-integer\n                # values here\n                try:\n                    size \u003d int(value)\n                except ValueError:\n                    continue\n            elif header \u003d\u003d \u0027x-backend-timestamp\u0027:\n                timestamp \u003d value\n        return cls(is_slo, etag, size, timestamp)\n```\nI kinda like it, since\n1. we can hang docstrings off it\n2. we can add properties (that `is_legacy` felt a little awkward)\n3. we can add classmethods","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":532,"context_line":"    return parsed_data"},{"line_number":533,"context_line":""},{"line_number":534,"context_line":""},{"line_number":535,"context_line":"SloAttrs \u003d namedtuple(\u0027SloAttrs\u0027, \u0027is_slo is_legacy etag size timestamp\u0027)"},{"line_number":536,"context_line":""},{"line_number":537,"context_line":""},{"line_number":538,"context_line":"def _extract_slo_attrs_from_headers(response_headers):"}],"source_content_type":"text/x-python","patch_set":12,"id":"80a59963_05fa065d","line":535,"range":{"start_line":535,"start_character":11,"end_line":535,"end_character":21},"in_reply_to":"143f3b91_82c8ce33","updated":"2023-09-27 20:44:30.000000000","message":"i used this mostly as-is; I don\u0027t want to couple the discovered is_legacy with the etag/size attributes that may get filled in from manifest parsing.","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0ed95df8729bd159c7c5c9c6c93b18d6dec8c2e9","unresolved":true,"context_lines":[{"line_number":876,"context_line":"                r \u003d seg_dict[\u0027hash\u0027]"},{"line_number":877,"context_line":"            calculated_etag.update(r.encode(\u0027ascii\u0027))"},{"line_number":878,"context_line":""},{"line_number":879,"context_line":"        return slo_attrs._replace("},{"line_number":880,"context_line":"            size\u003dcalculated_size,"},{"line_number":881,"context_line":"            etag\u003dcalculated_etag.hexdigest())"},{"line_number":882,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"9ab4dcdd_584224d6","line":879,"range":{"start_line":879,"start_character":25,"end_line":879,"end_character":33},"updated":"2023-09-21 22:50:35.000000000","message":"I wonder if it might be better to hang this off `SloAttrs` -- we never actually use `self` here...","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":876,"context_line":"                r \u003d seg_dict[\u0027hash\u0027]"},{"line_number":877,"context_line":"            calculated_etag.update(r.encode(\u0027ascii\u0027))"},{"line_number":878,"context_line":""},{"line_number":879,"context_line":"        return slo_attrs._replace("},{"line_number":880,"context_line":"            size\u003dcalculated_size,"},{"line_number":881,"context_line":"            etag\u003dcalculated_etag.hexdigest())"},{"line_number":882,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"ff3a6b4a_71b5824e","line":879,"range":{"start_line":879,"start_character":25,"end_line":879,"end_character":33},"in_reply_to":"3fa7ea89_12f9f0db","updated":"2023-09-27 20:44:30.000000000","message":"slo_attrs \u003d slo_attrs.update_from_segments(segments)\n\nI\u0027m starting to think this new class needs some targeted testing for all the behaviors we\u0027re hanging on it ;)","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":876,"context_line":"                r \u003d seg_dict[\u0027hash\u0027]"},{"line_number":877,"context_line":"            calculated_etag.update(r.encode(\u0027ascii\u0027))"},{"line_number":878,"context_line":""},{"line_number":879,"context_line":"        return slo_attrs._replace("},{"line_number":880,"context_line":"            size\u003dcalculated_size,"},{"line_number":881,"context_line":"            etag\u003dcalculated_etag.hexdigest())"},{"line_number":882,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"3fa7ea89_12f9f0db","line":879,"range":{"start_line":879,"start_character":25,"end_line":879,"end_character":33},"in_reply_to":"9ab4dcdd_584224d6","updated":"2023-09-27 18:21:43.000000000","message":"+1 it seems inconsistent to have this be a class method and _extract_slo_attrs_from_headers be a module function.","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"0ed95df8729bd159c7c5c9c6c93b18d6dec8c2e9","unresolved":true,"context_lines":[{"line_number":884,"context_line":"        \"\"\""},{"line_number":885,"context_line":"        Read the manifest body and parse segments."},{"line_number":886,"context_line":""},{"line_number":887,"context_line":"        :returns: a tuple of (slo_attrs, segments)"},{"line_number":888,"context_line":"        :raises: HTTPServerError"},{"line_number":889,"context_line":"        \"\"\""},{"line_number":890,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"}],"source_content_type":"text/x-python","patch_set":12,"id":"24b52ff2_02720916","line":887,"range":{"start_line":887,"start_character":30,"end_line":887,"end_character":39},"updated":"2023-09-21 22:50:35.000000000","message":"I feel like this docstring ought to say something about how the `slo_attrs` returned will be non-legacy.","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"e63a9009d9e931d781b38dc1ad41a39cb89b75a0","unresolved":false,"context_lines":[{"line_number":884,"context_line":"        \"\"\""},{"line_number":885,"context_line":"        Read the manifest body and parse segments."},{"line_number":886,"context_line":""},{"line_number":887,"context_line":"        :returns: a tuple of (slo_attrs, segments)"},{"line_number":888,"context_line":"        :raises: HTTPServerError"},{"line_number":889,"context_line":"        \"\"\""},{"line_number":890,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"}],"source_content_type":"text/x-python","patch_set":12,"id":"ecf76c2f_a95d019e","line":887,"range":{"start_line":887,"start_character":30,"end_line":887,"end_character":39},"in_reply_to":"24b52ff2_02720916","updated":"2023-09-27 23:42:53.000000000","message":"Ack","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":884,"context_line":"        \"\"\""},{"line_number":885,"context_line":"        Read the manifest body and parse segments."},{"line_number":886,"context_line":""},{"line_number":887,"context_line":"        :returns: a tuple of (slo_attrs, segments)"},{"line_number":888,"context_line":"        :raises: HTTPServerError"},{"line_number":889,"context_line":"        \"\"\""},{"line_number":890,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"}],"source_content_type":"text/x-python","patch_set":12,"id":"75ef56d6_b2daaa3b","line":887,"range":{"start_line":887,"start_character":30,"end_line":887,"end_character":39},"in_reply_to":"24b52ff2_02720916","updated":"2023-09-27 20:44:30.000000000","message":"i guess Al fixed this, i updated the doc string","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9a63c75f301edaf3d5b8651fd7bd2365dbdf1dab","unresolved":true,"context_lines":[{"line_number":1002,"context_line":"        if req.method \u003d\u003d \u0027GET\u0027 or slo_attrs.is_legacy:"},{"line_number":1003,"context_line":"            slo_attrs, segments \u003d self._parse_segments(resp_iter, slo_attrs)"},{"line_number":1004,"context_line":"        if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1005,"context_line":"            # don\u0027t validate_first_segement on HEAD?"},{"line_number":1006,"context_line":"            resp_iter \u003d self._build_resp_iter(req, segments, slo_attrs)"},{"line_number":1007,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1008,"context_line":"                                         slo_attrs)"}],"source_content_type":"text/x-python","patch_set":12,"id":"a9067f6c_1f6c0163","line":1005,"updated":"2023-09-25 22:34:11.000000000","message":"these two if req.method \u003d\u003d GET right in a row still bug me, the first one is something closer to \"if we have the manifest body in resp_iter\" and the second want is \"if the user wants a an slo body\"\n\nN.B. the coupling of refetch/need-to-process gets worse in the follow-up\n\nhttps://review.opendev.org/c/openstack/swift/+/894570","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"7d153d7329469806711ff3ef47f0721e2d84329f","unresolved":true,"context_lines":[{"line_number":1002,"context_line":"        if req.method \u003d\u003d \u0027GET\u0027 or slo_attrs.is_legacy:"},{"line_number":1003,"context_line":"            slo_attrs, segments \u003d self._parse_segments(resp_iter, slo_attrs)"},{"line_number":1004,"context_line":"        if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1005,"context_line":"            # don\u0027t validate_first_segement on HEAD?"},{"line_number":1006,"context_line":"            resp_iter \u003d self._build_resp_iter(req, segments, slo_attrs)"},{"line_number":1007,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1008,"context_line":"                                         slo_attrs)"}],"source_content_type":"text/x-python","patch_set":12,"id":"93ba0d87_1047a8cc","line":1005,"in_reply_to":"6cbe049f_c7671d3a","updated":"2023-09-28 14:34:29.000000000","message":"YES!  you\u0027ve cracked it.  This can be better.","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0011184508ee28592fcce43943da0f6637175d1e","unresolved":false,"context_lines":[{"line_number":1002,"context_line":"        if req.method \u003d\u003d \u0027GET\u0027 or slo_attrs.is_legacy:"},{"line_number":1003,"context_line":"            slo_attrs, segments \u003d self._parse_segments(resp_iter, slo_attrs)"},{"line_number":1004,"context_line":"        if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1005,"context_line":"            # don\u0027t validate_first_segement on HEAD?"},{"line_number":1006,"context_line":"            resp_iter \u003d self._build_resp_iter(req, segments, slo_attrs)"},{"line_number":1007,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1008,"context_line":"                                         slo_attrs)"}],"source_content_type":"text/x-python","patch_set":12,"id":"830e8a95_cc223729","line":1005,"in_reply_to":"93ba0d87_1047a8cc","updated":"2023-09-29 04:39:26.000000000","message":"Done","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"30f5e2df0fd685473bf3da7813c4747f11382087","unresolved":true,"context_lines":[{"line_number":1002,"context_line":"        if req.method \u003d\u003d \u0027GET\u0027 or slo_attrs.is_legacy:"},{"line_number":1003,"context_line":"            slo_attrs, segments \u003d self._parse_segments(resp_iter, slo_attrs)"},{"line_number":1004,"context_line":"        if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1005,"context_line":"            # don\u0027t validate_first_segement on HEAD?"},{"line_number":1006,"context_line":"            resp_iter \u003d self._build_resp_iter(req, segments, slo_attrs)"},{"line_number":1007,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1008,"context_line":"                                         slo_attrs)"}],"source_content_type":"text/x-python","patch_set":12,"id":"6cbe049f_c7671d3a","line":1005,"in_reply_to":"a9067f6c_1f6c0163","updated":"2023-09-28 13:28:51.000000000","message":"Maybe separate \"is manifest needed\" from \"is refetch needed\". Line 997 then becomes \"if manifest_needed:\"\n\nsee https://review.opendev.org/c/openstack/swift/+/896792","commit_id":"bdaebde9a18848d5939161b3e29a2fd638bf76b5"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":535,"context_line":"SloAttrs \u003d namedtuple(\u0027SloAttrs\u0027, \u0027is_slo is_legacy etag size timestamp\u0027)"},{"line_number":536,"context_line":""},{"line_number":537,"context_line":""},{"line_number":538,"context_line":"def _extract_slo_attrs_from_headers(response_headers):"},{"line_number":539,"context_line":"    \"\"\""},{"line_number":540,"context_line":"    Inspect response headers and extract any slo_attrs we can find."},{"line_number":541,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":14,"id":"433b7af9_dde83025","line":538,"updated":"2023-09-27 18:21:43.000000000","message":"Stylistically I\u0027d prefer a class with a class method `from_headers` (or even pass header to the constructor) but maybe there is some performance gain from namedtuple.","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":535,"context_line":"SloAttrs \u003d namedtuple(\u0027SloAttrs\u0027, \u0027is_slo is_legacy etag size timestamp\u0027)"},{"line_number":536,"context_line":""},{"line_number":537,"context_line":""},{"line_number":538,"context_line":"def _extract_slo_attrs_from_headers(response_headers):"},{"line_number":539,"context_line":"    \"\"\""},{"line_number":540,"context_line":"    Inspect response headers and extract any slo_attrs we can find."},{"line_number":541,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":14,"id":"643eef93_bbeb78d8","line":538,"in_reply_to":"433b7af9_dde83025","updated":"2023-09-27 20:44:30.000000000","message":"classmethod sounds reasonable to me\n\n    slo_attr \u003d SloAttrs.from_headers(resp_headers)","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":540,"context_line":"    Inspect response headers and extract any slo_attrs we can find."},{"line_number":541,"context_line":"    \"\"\""},{"line_number":542,"context_line":"    is_slo \u003d False"},{"line_number":543,"context_line":"    is_legacy \u003d True"},{"line_number":544,"context_line":"    etag \u003d None"},{"line_number":545,"context_line":"    size \u003d None"},{"line_number":546,"context_line":"    timestamp \u003d Timestamp(0)"}],"source_content_type":"text/x-python","patch_set":14,"id":"2aa3bbb7_4a4519bf","line":543,"updated":"2023-09-27 18:21:43.000000000","message":"this declaration isn\u0027t used","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":540,"context_line":"    Inspect response headers and extract any slo_attrs we can find."},{"line_number":541,"context_line":"    \"\"\""},{"line_number":542,"context_line":"    is_slo \u003d False"},{"line_number":543,"context_line":"    is_legacy \u003d True"},{"line_number":544,"context_line":"    etag \u003d None"},{"line_number":545,"context_line":"    size \u003d None"},{"line_number":546,"context_line":"    timestamp \u003d Timestamp(0)"}],"source_content_type":"text/x-python","patch_set":14,"id":"13dbd575_d124ecfe","line":543,"in_reply_to":"2aa3bbb7_4a4519bf","updated":"2023-09-27 20:44:30.000000000","message":"Done","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":553,"context_line":"        elif header \u003d\u003d SYSMETA_SLO_SIZE:"},{"line_number":554,"context_line":"            # it\u0027s from sysmeta, so we don\u0027t worry about non-integer"},{"line_number":555,"context_line":"            # values here"},{"line_number":556,"context_line":"            try:"},{"line_number":557,"context_line":"                size \u003d int(value)"},{"line_number":558,"context_line":"            except ValueError:"},{"line_number":559,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":14,"id":"706c3e22_82521e90","line":556,"updated":"2023-09-27 18:21:43.000000000","message":"the try/catch is new - was there a case when it\u0027s non-integer?","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":553,"context_line":"        elif header \u003d\u003d SYSMETA_SLO_SIZE:"},{"line_number":554,"context_line":"            # it\u0027s from sysmeta, so we don\u0027t worry about non-integer"},{"line_number":555,"context_line":"            # values here"},{"line_number":556,"context_line":"            try:"},{"line_number":557,"context_line":"                size \u003d int(value)"},{"line_number":558,"context_line":"            except ValueError:"},{"line_number":559,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":14,"id":"6652ec94_be43ec51","line":556,"in_reply_to":"706c3e22_82521e90","updated":"2023-09-27 20:44:30.000000000","message":"yes!  https://review.opendev.org/c/openstack/swift/+/894403\n\n#willfix the comment","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":553,"context_line":"        elif header \u003d\u003d SYSMETA_SLO_SIZE:"},{"line_number":554,"context_line":"            # it\u0027s from sysmeta, so we don\u0027t worry about non-integer"},{"line_number":555,"context_line":"            # values here"},{"line_number":556,"context_line":"            try:"},{"line_number":557,"context_line":"                size \u003d int(value)"},{"line_number":558,"context_line":"            except ValueError:"},{"line_number":559,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a351906_fafa3e92","line":556,"in_reply_to":"706c3e22_82521e90","updated":"2023-09-27 20:44:30.000000000","message":"yes, see Ic6f04a5a6af8a3e65b226cff2ed6c9fce8ce1fa2\n\n... and that comment is stale!","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":560,"context_line":"        elif header \u003d\u003d \u0027x-backend-timestamp\u0027:"},{"line_number":561,"context_line":"            timestamp \u003d value"},{"line_number":562,"context_line":"    # a \"legacy manifest\" didn\u0027t get etag and size sysmeta"},{"line_number":563,"context_line":"    is_legacy \u003d not all((etag, size))"},{"line_number":564,"context_line":"    return SloAttrs(is_slo, is_legacy, etag, size, timestamp)"},{"line_number":565,"context_line":""},{"line_number":566,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"38bcdc3e_9c7d6b65","line":563,"range":{"start_line":563,"start_character":4,"end_line":563,"end_character":13},"updated":"2023-09-27 18:21:43.000000000","message":"looking ahead to the part_num patch, I wonder if is_legacy is too specific: what we want to carry around in this \u0027context\u0027 is whether the full manifest is needed or not:\n\nImagine adding a body_required\u003dFalse kwarg to this function:\n\n```is_legacy \u003d body_required or not all((etag, size))```\n\nthen in future calling with \n\n```_extract_slo_attrs_from_headers(response_headers, is_part_num)```\n\nMaybe the SloAttrs now encapsulates enough for fewer changes in handle_slo_get_or_head to accommodate part_num??\n\n(obviously is_legacy is no longer a good name, and SloAttrs may also not be the best name)","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":true,"context_lines":[{"line_number":560,"context_line":"        elif header \u003d\u003d \u0027x-backend-timestamp\u0027:"},{"line_number":561,"context_line":"            timestamp \u003d value"},{"line_number":562,"context_line":"    # a \"legacy manifest\" didn\u0027t get etag and size sysmeta"},{"line_number":563,"context_line":"    is_legacy \u003d not all((etag, size))"},{"line_number":564,"context_line":"    return SloAttrs(is_slo, is_legacy, etag, size, timestamp)"},{"line_number":565,"context_line":""},{"line_number":566,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"ec86e0e6_186be9b0","line":563,"range":{"start_line":563,"start_character":4,"end_line":563,"end_character":13},"in_reply_to":"38bcdc3e_9c7d6b65","updated":"2023-09-27 20:44:30.000000000","message":"is_legacy is a THING - it\u0027s a concept that\u0027s made explicit in tests and something anyone working on SLO needs to be aware of\n\nIt\u0027s probably not *sufficient* as a concept when deciding body_required; but I\u0027m not sure that should be a property of SloAttrs - if the \"body_required\" concept is something we need to pass around in addition to slo_attrs maybe that\u0027s just highlighting that we have a sufficient amount of state in the SloContext that we shouldn\u0027t be passing around little bags of crap like slo_attrs","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0011184508ee28592fcce43943da0f6637175d1e","unresolved":false,"context_lines":[{"line_number":560,"context_line":"        elif header \u003d\u003d \u0027x-backend-timestamp\u0027:"},{"line_number":561,"context_line":"            timestamp \u003d value"},{"line_number":562,"context_line":"    # a \"legacy manifest\" didn\u0027t get etag and size sysmeta"},{"line_number":563,"context_line":"    is_legacy \u003d not all((etag, size))"},{"line_number":564,"context_line":"    return SloAttrs(is_slo, is_legacy, etag, size, timestamp)"},{"line_number":565,"context_line":""},{"line_number":566,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"b61058ed_03e76078","line":563,"range":{"start_line":563,"start_character":4,"end_line":563,"end_character":13},"in_reply_to":"ec86e0e6_186be9b0","updated":"2023-09-29 04:39:26.000000000","message":"Done","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":561,"context_line":"            timestamp \u003d value"},{"line_number":562,"context_line":"    # a \"legacy manifest\" didn\u0027t get etag and size sysmeta"},{"line_number":563,"context_line":"    is_legacy \u003d not all((etag, size))"},{"line_number":564,"context_line":"    return SloAttrs(is_slo, is_legacy, etag, size, timestamp)"},{"line_number":565,"context_line":""},{"line_number":566,"context_line":""},{"line_number":567,"context_line":"def _segment_length(seg_dict):"}],"source_content_type":"text/x-python","patch_set":14,"id":"aeed6a36_c5a822e6","line":564,"updated":"2023-09-27 18:21:43.000000000","message":"ok, this function is faithful to the original code","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":561,"context_line":"            timestamp \u003d value"},{"line_number":562,"context_line":"    # a \"legacy manifest\" didn\u0027t get etag and size sysmeta"},{"line_number":563,"context_line":"    is_legacy \u003d not all((etag, size))"},{"line_number":564,"context_line":"    return SloAttrs(is_slo, is_legacy, etag, size, timestamp)"},{"line_number":565,"context_line":""},{"line_number":566,"context_line":""},{"line_number":567,"context_line":"def _segment_length(seg_dict):"}],"source_content_type":"text/x-python","patch_set":14,"id":"69a2718f_a36a1a36","line":564,"in_reply_to":"aeed6a36_c5a822e6","updated":"2023-09-27 20:44:30.000000000","message":"Ack","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":625,"context_line":""},{"line_number":626,"context_line":"        slo_attrs \u003d _extract_slo_attrs_from_headers(sub_resp.headers.items())"},{"line_number":627,"context_line":"        try:"},{"line_number":628,"context_line":"            _, segments \u003d self._parse_segments(sub_resp.app_iter, slo_attrs)"},{"line_number":629,"context_line":"            return segments"},{"line_number":630,"context_line":"        except HTTPException as err:"},{"line_number":631,"context_line":"            raise ListingIterError("}],"source_content_type":"text/x-python","patch_set":14,"id":"c627b386_aa2a4b90","line":628,"updated":"2023-09-27 18:21:43.000000000","message":"seems odd to extract slo_attrs, fix them up in _parse_segments, only to ignore the result\n\nSee https://review.opendev.org/c/openstack/swift/+/896696 for an alternative idea","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"30f5e2df0fd685473bf3da7813c4747f11382087","unresolved":false,"context_lines":[{"line_number":625,"context_line":""},{"line_number":626,"context_line":"        slo_attrs \u003d _extract_slo_attrs_from_headers(sub_resp.headers.items())"},{"line_number":627,"context_line":"        try:"},{"line_number":628,"context_line":"            _, segments \u003d self._parse_segments(sub_resp.app_iter, slo_attrs)"},{"line_number":629,"context_line":"            return segments"},{"line_number":630,"context_line":"        except HTTPException as err:"},{"line_number":631,"context_line":"            raise ListingIterError("}],"source_content_type":"text/x-python","patch_set":14,"id":"3e4a9cc5_b9646eeb","line":628,"in_reply_to":"c627b386_aa2a4b90","updated":"2023-09-28 13:28:51.000000000","message":"Done","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":766,"context_line":""},{"line_number":767,"context_line":"        # The response shows that this resp is a SLO manifest, but does not"},{"line_number":768,"context_line":"        # mean that resp_iter contains the entire SLO manifest. If it doesn\u0027t,"},{"line_number":769,"context_line":"        # we may need to make a second request to actually get the whole thing."},{"line_number":770,"context_line":""},{"line_number":771,"context_line":"        if is_manifest_get:"},{"line_number":772,"context_line":"            return False"}],"source_content_type":"text/x-python","patch_set":14,"id":"9b5f84a6_df4ad932","line":769,"updated":"2023-09-27 18:21:43.000000000","message":"nit: I find some of the comment (content and position) confusing - e.g. this method is called for HEADs when the resp_iter is irrelevant","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":true,"context_lines":[{"line_number":766,"context_line":""},{"line_number":767,"context_line":"        # The response shows that this resp is a SLO manifest, but does not"},{"line_number":768,"context_line":"        # mean that resp_iter contains the entire SLO manifest. If it doesn\u0027t,"},{"line_number":769,"context_line":"        # we may need to make a second request to actually get the whole thing."},{"line_number":770,"context_line":""},{"line_number":771,"context_line":"        if is_manifest_get:"},{"line_number":772,"context_line":"            return False"}],"source_content_type":"text/x-python","patch_set":14,"id":"add2d019_bf01f37e","line":769,"in_reply_to":"9b5f84a6_df4ad932","updated":"2023-09-27 20:44:30.000000000","message":"I was carrying forward the prose from the doc-string; I think my intention was to move the this after the \"not is_slo\" check (which the original doc-string called out)\n\nI\u0027d be open to dumping it or repharsing - do you have a specific suggestion - it doesn\u0027t really bother me the way I did it, but I\u0027m happy to change it.","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0011184508ee28592fcce43943da0f6637175d1e","unresolved":false,"context_lines":[{"line_number":766,"context_line":""},{"line_number":767,"context_line":"        # The response shows that this resp is a SLO manifest, but does not"},{"line_number":768,"context_line":"        # mean that resp_iter contains the entire SLO manifest. If it doesn\u0027t,"},{"line_number":769,"context_line":"        # we may need to make a second request to actually get the whole thing."},{"line_number":770,"context_line":""},{"line_number":771,"context_line":"        if is_manifest_get:"},{"line_number":772,"context_line":"            return False"}],"source_content_type":"text/x-python","patch_set":14,"id":"f74b1c62_86fd3741","line":769,"in_reply_to":"add2d019_bf01f37e","updated":"2023-09-29 04:39:26.000000000","message":"Done","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":781,"context_line":"        # submitted If-None-Match won\u0027t match the manifest object\u0027s etag, so"},{"line_number":782,"context_line":"        # we can avoid re-fetching the manifest if we got a successful"},{"line_number":783,"context_line":"        # response."},{"line_number":784,"context_line":"        is_conditional \u003d self._response_status_int in (304, 412)"},{"line_number":785,"context_line":"        if is_conditional and slo_attrs.is_legacy:"},{"line_number":786,"context_line":"            return True"},{"line_number":787,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"62d6348d_393478dc","line":784,"updated":"2023-09-27 18:21:43.000000000","message":"does this change to how the condition is evaluated actually result in any behavioural change in any req/response scenario?","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":true,"context_lines":[{"line_number":781,"context_line":"        # submitted If-None-Match won\u0027t match the manifest object\u0027s etag, so"},{"line_number":782,"context_line":"        # we can avoid re-fetching the manifest if we got a successful"},{"line_number":783,"context_line":"        # response."},{"line_number":784,"context_line":"        is_conditional \u003d self._response_status_int in (304, 412)"},{"line_number":785,"context_line":"        if is_conditional and slo_attrs.is_legacy:"},{"line_number":786,"context_line":"            return True"},{"line_number":787,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"6648d9de_d60c2252","line":784,"in_reply_to":"62d6348d_393478dc","updated":"2023-09-27 20:44:30.000000000","message":"umm... yes and no\n\nlike yes THIS method is different, but no there shouldn\u0027t be a client percieveable change if we\u0027ve done our job right.\n\nThe previous code would have a conditional HEAD response on new-sytle manifests bail out before we even got to this method; whereas we\u0027re trying to let things flow through a more common code path so we can consolidate header manipulation.\n\nSo the previous condition was insufficient and this one is more explicit - we\u0027ve simply conslidated ALL the \"need_to_refetch\" logic into one method; instead of having a couple of need_to_refetch \u003d False bail out early (e.g. not slo_attr.is_slo), and then only have the other half in this super method.\n\nNow it\u0027s ALL in here, but we should come up with the same behavior.","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0011184508ee28592fcce43943da0f6637175d1e","unresolved":false,"context_lines":[{"line_number":781,"context_line":"        # submitted If-None-Match won\u0027t match the manifest object\u0027s etag, so"},{"line_number":782,"context_line":"        # we can avoid re-fetching the manifest if we got a successful"},{"line_number":783,"context_line":"        # response."},{"line_number":784,"context_line":"        is_conditional \u003d self._response_status_int in (304, 412)"},{"line_number":785,"context_line":"        if is_conditional and slo_attrs.is_legacy:"},{"line_number":786,"context_line":"            return True"},{"line_number":787,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"6f68a823_5b983d29","line":784,"in_reply_to":"6648d9de_d60c2252","updated":"2023-09-29 04:39:26.000000000","message":"Done","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":836,"context_line":"        # we\u0027ll just try to serve the old data"},{"line_number":837,"context_line":"        return new_slo_attrs, resp_iter"},{"line_number":838,"context_line":""},{"line_number":839,"context_line":"    def _annotate_segments_length(self, segments):"},{"line_number":840,"context_line":"        \"\"\""},{"line_number":841,"context_line":"        Annotate segment dicts in segments list with \u0027segment_length\u0027 (raw_data"},{"line_number":842,"context_line":"        and range segments don\u0027t have a bytes key, and sub_slo segments will"}],"source_content_type":"text/x-python","patch_set":14,"id":"45234f97_3f4f2221","line":839,"updated":"2023-09-27 18:21:43.000000000","message":"this method seems to do more than the name suggests (maybe decode data, update bytes) - could be \u0027_annotate_segments\u0027","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"context_lines":[{"line_number":836,"context_line":"        # we\u0027ll just try to serve the old data"},{"line_number":837,"context_line":"        return new_slo_attrs, resp_iter"},{"line_number":838,"context_line":""},{"line_number":839,"context_line":"    def _annotate_segments_length(self, segments):"},{"line_number":840,"context_line":"        \"\"\""},{"line_number":841,"context_line":"        Annotate segment dicts in segments list with \u0027segment_length\u0027 (raw_data"},{"line_number":842,"context_line":"        and range segments don\u0027t have a bytes key, and sub_slo segments will"}],"source_content_type":"text/x-python","patch_set":14,"id":"e913d11c_2f6fd48c","line":839,"in_reply_to":"45234f97_3f4f2221","updated":"2023-09-27 20:44:30.000000000","message":"yes, I noticed that too - and the raw_data decode is needed for SegmentedIterable","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":890,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":891,"context_line":"        self._annotate_segments_length(segments)"},{"line_number":892,"context_line":"        if slo_attrs.is_legacy:"},{"line_number":893,"context_line":"            slo_attrs \u003d self._calculate_slo_attributes(segments, slo_attrs)"},{"line_number":894,"context_line":"        return slo_attrs, segments"},{"line_number":895,"context_line":""},{"line_number":896,"context_line":"    def _return_manifest_response(self, req, start_response, resp_iter,"}],"source_content_type":"text/x-python","patch_set":14,"id":"5e77c2c6_1c4242e0","line":893,"updated":"2023-09-27 18:21:43.000000000","message":"I wonder if it would be helpful to separate the need to calculate etag etc for legacy manifests vs annotations that are made for *every* GET","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"30f5e2df0fd685473bf3da7813c4747f11382087","unresolved":false,"context_lines":[{"line_number":890,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":891,"context_line":"        self._annotate_segments_length(segments)"},{"line_number":892,"context_line":"        if slo_attrs.is_legacy:"},{"line_number":893,"context_line":"            slo_attrs \u003d self._calculate_slo_attributes(segments, slo_attrs)"},{"line_number":894,"context_line":"        return slo_attrs, segments"},{"line_number":895,"context_line":""},{"line_number":896,"context_line":"    def _return_manifest_response(self, req, start_response, resp_iter,"}],"source_content_type":"text/x-python","patch_set":14,"id":"f2c28d8b_c35c1b6b","line":893,"in_reply_to":"5e77c2c6_1c4242e0","updated":"2023-09-28 13:28:51.000000000","message":"Done","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":985,"context_line":"                req, resp_iter, slo_attrs)"},{"line_number":986,"context_line":""},{"line_number":987,"context_line":"        if not slo_attrs.is_slo:"},{"line_number":988,"context_line":"            # original or refetched object might not be SLO manifest"},{"line_number":989,"context_line":"            return self._return_raw_response(req, start_response, resp_iter)"},{"line_number":990,"context_line":"        elif is_manifest_get:"},{"line_number":991,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"}],"source_content_type":"text/x-python","patch_set":14,"id":"f27393b5_f606587e","line":988,"updated":"2023-09-27 18:21:43.000000000","message":"it can\u0027t have been refetched if not is_slo?","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"30f5e2df0fd685473bf3da7813c4747f11382087","unresolved":false,"context_lines":[{"line_number":985,"context_line":"                req, resp_iter, slo_attrs)"},{"line_number":986,"context_line":""},{"line_number":987,"context_line":"        if not slo_attrs.is_slo:"},{"line_number":988,"context_line":"            # original or refetched object might not be SLO manifest"},{"line_number":989,"context_line":"            return self._return_raw_response(req, start_response, resp_iter)"},{"line_number":990,"context_line":"        elif is_manifest_get:"},{"line_number":991,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"}],"source_content_type":"text/x-python","patch_set":14,"id":"ac6ab64b_970f2741","line":988,"in_reply_to":"a3e460c6_8d7d3ceb","updated":"2023-09-28 13:28:51.000000000","message":"sorry, on my first reading I missed that slo_attrs is replaced in _refetch_manifest. This now makes sense to me.\n\n(I was mistakenly thinking \"wait, the origin is not an slo so we didn\u0027t refetch\")","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":true,"context_lines":[{"line_number":985,"context_line":"                req, resp_iter, slo_attrs)"},{"line_number":986,"context_line":""},{"line_number":987,"context_line":"        if not slo_attrs.is_slo:"},{"line_number":988,"context_line":"            # original or refetched object might not be SLO manifest"},{"line_number":989,"context_line":"            return self._return_raw_response(req, start_response, resp_iter)"},{"line_number":990,"context_line":"        elif is_manifest_get:"},{"line_number":991,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"}],"source_content_type":"text/x-python","patch_set":14,"id":"a3e460c6_8d7d3ceb","line":988,"in_reply_to":"f27393b5_f606587e","updated":"2023-09-27 20:44:30.000000000","message":"for old swift there\u0027s tests to demonstrated we could refetch an is_slo and discover the name is \"no longer\" an slo - I feel like the same could happen for legacy manifests if we do a HEAD and try to refetch the whole body\n\nanyway all of those cases could come out of _need_to_refresh like \"needed to refresh; but couldn\u0027t\" and they get returned here; maybe only some of those cases are tested...","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a84e9ea79fcac2f702e4dbf3401950358843edd7","unresolved":true,"context_lines":[{"line_number":988,"context_line":"            # original or refetched object might not be SLO manifest"},{"line_number":989,"context_line":"            return self._return_raw_response(req, start_response, resp_iter)"},{"line_number":990,"context_line":"        elif is_manifest_get:"},{"line_number":991,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"},{"line_number":992,"context_line":"            return self._return_manifest_response(req, start_response,"},{"line_number":993,"context_line":"                                                  resp_iter, is_format_raw)"},{"line_number":994,"context_line":"        elif self._response_status_int in (304, 412, 416):"}],"source_content_type":"text/x-python","patch_set":14,"id":"703ee44b_e760a473","line":991,"updated":"2023-09-27 18:21:43.000000000","message":"not sure I understand the significance of this comment","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0011184508ee28592fcce43943da0f6637175d1e","unresolved":false,"context_lines":[{"line_number":988,"context_line":"            # original or refetched object might not be SLO manifest"},{"line_number":989,"context_line":"            return self._return_raw_response(req, start_response, resp_iter)"},{"line_number":990,"context_line":"        elif is_manifest_get:"},{"line_number":991,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"},{"line_number":992,"context_line":"            return self._return_manifest_response(req, start_response,"},{"line_number":993,"context_line":"                                                  resp_iter, is_format_raw)"},{"line_number":994,"context_line":"        elif self._response_status_int in (304, 412, 416):"}],"source_content_type":"text/x-python","patch_set":14,"id":"d2b057c1_57486c93","line":991,"in_reply_to":"3235798f_ab90d13e","updated":"2023-09-29 04:39:26.000000000","message":"Done","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":true,"context_lines":[{"line_number":988,"context_line":"            # original or refetched object might not be SLO manifest"},{"line_number":989,"context_line":"            return self._return_raw_response(req, start_response, resp_iter)"},{"line_number":990,"context_line":"        elif is_manifest_get:"},{"line_number":991,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"},{"line_number":992,"context_line":"            return self._return_manifest_response(req, start_response,"},{"line_number":993,"context_line":"                                                  resp_iter, is_format_raw)"},{"line_number":994,"context_line":"        elif self._response_status_int in (304, 412, 416):"}],"source_content_type":"text/x-python","patch_set":14,"id":"3235798f_ab90d13e","line":991,"in_reply_to":"703ee44b_e760a473","updated":"2023-09-27 20:44:30.000000000","message":"i guess I was noting that the slo_attrs isn\u0027t handed to the _return_manifest_response method because\n\n1) we do send it to _return_slo_response; so that\u0027s different\n2) manifests are just normal json objects, no special header swapping going on - so it makes sense that slo_attrs isn\u0027t needed\n\nmaybe not worth the comment to call out if it\u0027s just confusing?  Or perhaps a more clear way to highlight that difference and/or design property it if it\u0027s a useful concept to draw attention to?","commit_id":"7a79cd56efbbfff2079e34685140d937568717cb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"30f5e2df0fd685473bf3da7813c4747f11382087","unresolved":true,"context_lines":[{"line_number":565,"context_line":"        is_legacy \u003d not all((etag, size))"},{"line_number":566,"context_line":"        return cls(is_slo, is_legacy, etag, size, timestamp)"},{"line_number":567,"context_line":""},{"line_number":568,"context_line":"    def update_from_segments(self, segments):"},{"line_number":569,"context_line":"        \"\"\""},{"line_number":570,"context_line":"        Used for legacy manifests, calculate slo_attrs we wouldn\u0027t have gotten"},{"line_number":571,"context_line":"        from sysmeta."}],"source_content_type":"text/x-python","patch_set":20,"id":"27b159f3_9383a571","line":568,"range":{"start_line":568,"start_character":8,"end_line":568,"end_character":14},"updated":"2023-09-28 13:28:51.000000000","message":"\u0027update\u0027 implies (to me) modify in place (like a dict.update()), but this is more like a copy_and_replace or clone","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"7d153d7329469806711ff3ef47f0721e2d84329f","unresolved":true,"context_lines":[{"line_number":565,"context_line":"        is_legacy \u003d not all((etag, size))"},{"line_number":566,"context_line":"        return cls(is_slo, is_legacy, etag, size, timestamp)"},{"line_number":567,"context_line":""},{"line_number":568,"context_line":"    def update_from_segments(self, segments):"},{"line_number":569,"context_line":"        \"\"\""},{"line_number":570,"context_line":"        Used for legacy manifests, calculate slo_attrs we wouldn\u0027t have gotten"},{"line_number":571,"context_line":"        from sysmeta."}],"source_content_type":"text/x-python","patch_set":20,"id":"df32dde1_1ab2a3e4","line":568,"range":{"start_line":568,"start_character":8,"end_line":568,"end_character":14},"in_reply_to":"27b159f3_9383a571","updated":"2023-09-28 14:34:29.000000000","message":"I agree about the implication and it was intentional.\n\nI feel like that the fact that it\u0027s *really* a \"clone with _replace\" is *just* an implementation detail; if it wasn\u0027t a namedtuple I would have just updated the attributes.  Plus \"update\" clearly signals that it\u0027s keeping the \"timestamp\" and \"is_legacy\" attributes it can only get from the headers; so it\u0027s not really \"create a new slo_attrs from segments info\"\n\n... maybe there\u0027s a compromise on the name, but I\u0027d prefer the interface *name* to lean towards the behavior and how it\u0027s used than towards how it done under the hood.","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0011184508ee28592fcce43943da0f6637175d1e","unresolved":false,"context_lines":[{"line_number":565,"context_line":"        is_legacy \u003d not all((etag, size))"},{"line_number":566,"context_line":"        return cls(is_slo, is_legacy, etag, size, timestamp)"},{"line_number":567,"context_line":""},{"line_number":568,"context_line":"    def update_from_segments(self, segments):"},{"line_number":569,"context_line":"        \"\"\""},{"line_number":570,"context_line":"        Used for legacy manifests, calculate slo_attrs we wouldn\u0027t have gotten"},{"line_number":571,"context_line":"        from sysmeta."}],"source_content_type":"text/x-python","patch_set":20,"id":"cb533daf_083db925","line":568,"range":{"start_line":568,"start_character":8,"end_line":568,"end_character":14},"in_reply_to":"df32dde1_1ab2a3e4","updated":"2023-09-29 04:39:26.000000000","message":"Done","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"30f5e2df0fd685473bf3da7813c4747f11382087","unresolved":true,"context_lines":[{"line_number":590,"context_line":"                r \u003d seg_dict[\u0027hash\u0027]"},{"line_number":591,"context_line":"            calculated_etag.update(r.encode(\u0027ascii\u0027))"},{"line_number":592,"context_line":""},{"line_number":593,"context_line":"        # N.B. updated slo_attrs retain their timestamp and is_legacy \u003d True"},{"line_number":594,"context_line":"        return self._replace("},{"line_number":595,"context_line":"            size\u003dcalculated_size,"},{"line_number":596,"context_line":"            etag\u003dcalculated_etag.hexdigest())"}],"source_content_type":"text/x-python","patch_set":20,"id":"65406630_61cb8fad","line":593,"updated":"2023-09-28 13:28:51.000000000","message":"probably worth mentioning in the docstring","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0011184508ee28592fcce43943da0f6637175d1e","unresolved":false,"context_lines":[{"line_number":590,"context_line":"                r \u003d seg_dict[\u0027hash\u0027]"},{"line_number":591,"context_line":"            calculated_etag.update(r.encode(\u0027ascii\u0027))"},{"line_number":592,"context_line":""},{"line_number":593,"context_line":"        # N.B. updated slo_attrs retain their timestamp and is_legacy \u003d True"},{"line_number":594,"context_line":"        return self._replace("},{"line_number":595,"context_line":"            size\u003dcalculated_size,"},{"line_number":596,"context_line":"            etag\u003dcalculated_etag.hexdigest())"}],"source_content_type":"text/x-python","patch_set":20,"id":"8872625d_43430815","line":593,"in_reply_to":"21eddb32_e1f0aa3d","updated":"2023-09-29 04:39:26.000000000","message":"Done","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"7d153d7329469806711ff3ef47f0721e2d84329f","unresolved":true,"context_lines":[{"line_number":590,"context_line":"                r \u003d seg_dict[\u0027hash\u0027]"},{"line_number":591,"context_line":"            calculated_etag.update(r.encode(\u0027ascii\u0027))"},{"line_number":592,"context_line":""},{"line_number":593,"context_line":"        # N.B. updated slo_attrs retain their timestamp and is_legacy \u003d True"},{"line_number":594,"context_line":"        return self._replace("},{"line_number":595,"context_line":"            size\u003dcalculated_size,"},{"line_number":596,"context_line":"            etag\u003dcalculated_etag.hexdigest())"}],"source_content_type":"text/x-python","patch_set":20,"id":"21eddb32_e1f0aa3d","line":593,"in_reply_to":"65406630_61cb8fad","updated":"2023-09-28 14:34:29.000000000","message":"yeah, especially if you give it dumb name like like \"create_new_copy_from_segments_only_not_some_attributes\"","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"30f5e2df0fd685473bf3da7813c4747f11382087","unresolved":true,"context_lines":[{"line_number":829,"context_line":"        resp_iter \u003d self._app_call(get_req.environ)"},{"line_number":830,"context_line":"        new_slo_attrs \u003d SloAttrs.from_headers(self._response_headers)"},{"line_number":831,"context_line":"        if not new_slo_attrs.is_slo:"},{"line_number":832,"context_line":"            if Timestamp(new_slo_attrs.timestamp) \u003e\u003d Timestamp("},{"line_number":833,"context_line":"                    orig_slo_attrs.timestamp):"},{"line_number":834,"context_line":"                # We\u0027ve got a newer response available, so serve that."},{"line_number":835,"context_line":"                # Note that if there\u0027s data, it\u0027s going to be a 200 now,"}],"source_content_type":"text/x-python","patch_set":20,"id":"4f63de0e_39a3f087","line":832,"range":{"start_line":832,"start_character":15,"end_line":832,"end_character":24},"updated":"2023-09-28 13:28:51.000000000","message":"SloAttrs ought to take care of casting time values to Timestamps - see https://review.opendev.org/c/openstack/swift/+/896791","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"7d153d7329469806711ff3ef47f0721e2d84329f","unresolved":true,"context_lines":[{"line_number":829,"context_line":"        resp_iter \u003d self._app_call(get_req.environ)"},{"line_number":830,"context_line":"        new_slo_attrs \u003d SloAttrs.from_headers(self._response_headers)"},{"line_number":831,"context_line":"        if not new_slo_attrs.is_slo:"},{"line_number":832,"context_line":"            if Timestamp(new_slo_attrs.timestamp) \u003e\u003d Timestamp("},{"line_number":833,"context_line":"                    orig_slo_attrs.timestamp):"},{"line_number":834,"context_line":"                # We\u0027ve got a newer response available, so serve that."},{"line_number":835,"context_line":"                # Note that if there\u0027s data, it\u0027s going to be a 200 now,"}],"source_content_type":"text/x-python","patch_set":20,"id":"b6af753a_0e1f7973","line":832,"range":{"start_line":832,"start_character":15,"end_line":832,"end_character":24},"in_reply_to":"4f63de0e_39a3f087","updated":"2023-09-28 14:34:29.000000000","message":"yes, that could definately be more consistent - nice catch, thanks!","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0011184508ee28592fcce43943da0f6637175d1e","unresolved":false,"context_lines":[{"line_number":829,"context_line":"        resp_iter \u003d self._app_call(get_req.environ)"},{"line_number":830,"context_line":"        new_slo_attrs \u003d SloAttrs.from_headers(self._response_headers)"},{"line_number":831,"context_line":"        if not new_slo_attrs.is_slo:"},{"line_number":832,"context_line":"            if Timestamp(new_slo_attrs.timestamp) \u003e\u003d Timestamp("},{"line_number":833,"context_line":"                    orig_slo_attrs.timestamp):"},{"line_number":834,"context_line":"                # We\u0027ve got a newer response available, so serve that."},{"line_number":835,"context_line":"                # Note that if there\u0027s data, it\u0027s going to be a 200 now,"}],"source_content_type":"text/x-python","patch_set":20,"id":"6cb87db0_063a1c4b","line":832,"range":{"start_line":832,"start_character":15,"end_line":832,"end_character":24},"in_reply_to":"b6af753a_0e1f7973","updated":"2023-09-29 04:39:26.000000000","message":"Done","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":1049,"context_line":"        :param slo_attrs: the slo attributes"},{"line_number":1050,"context_line":""},{"line_number":1051,"context_line":"        :returns: a segmented iterable"},{"line_number":1052,"context_line":"        \"\"\""},{"line_number":1053,"context_line":"        if req.range:"},{"line_number":1054,"context_line":"            byteranges \u003d ["},{"line_number":1055,"context_line":"                # For some reason, swob.Range.ranges_for_length adds 1 to the"}],"source_content_type":"text/x-python","patch_set":20,"id":"8a4766fb_85ecf03f","line":1052,"updated":"2023-09-29 14:29:51.000000000","message":"this got lost","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"context_lines":[{"line_number":1049,"context_line":"        :param slo_attrs: the slo attributes"},{"line_number":1050,"context_line":""},{"line_number":1051,"context_line":"        :returns: a segmented iterable"},{"line_number":1052,"context_line":"        \"\"\""},{"line_number":1053,"context_line":"        if req.range:"},{"line_number":1054,"context_line":"            byteranges \u003d ["},{"line_number":1055,"context_line":"                # For some reason, swob.Range.ranges_for_length adds 1 to the"}],"source_content_type":"text/x-python","patch_set":20,"id":"9224c367_72bedb58","line":1052,"in_reply_to":"8a4766fb_85ecf03f","updated":"2023-09-29 19:52:06.000000000","message":"Done","commit_id":"0d9245d8c1c30689e48e275c2cf133155410e80b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":879,"context_line":"                        app_iter\u003dresp_iter,"},{"line_number":880,"context_line":"                        request\u003dreq,"},{"line_number":881,"context_line":"                        conditional_etag\u003dresolve_etag_is_at_header("},{"line_number":882,"context_line":"                            req, self._response_headers),"},{"line_number":883,"context_line":"                        conditional_response\u003dis_success("},{"line_number":884,"context_line":"                            int(self._response_status[:3])))"},{"line_number":885,"context_line":"                    return resp(req.environ, start_response)"}],"source_content_type":"text/x-python","patch_set":21,"id":"13d42393_4323c2f3","side":"PARENT","line":882,"updated":"2023-09-29 14:29:51.000000000","message":"I can\u0027t see this in the new patch\u0027s _return_raw_response()","commit_id":"3d36ccc3405152b983d86faf28974cafe88521d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"116890ebea9ac6698113d753af315d9a47903370","unresolved":true,"context_lines":[{"line_number":879,"context_line":"                        app_iter\u003dresp_iter,"},{"line_number":880,"context_line":"                        request\u003dreq,"},{"line_number":881,"context_line":"                        conditional_etag\u003dresolve_etag_is_at_header("},{"line_number":882,"context_line":"                            req, self._response_headers),"},{"line_number":883,"context_line":"                        conditional_response\u003dis_success("},{"line_number":884,"context_line":"                            int(self._response_status[:3])))"},{"line_number":885,"context_line":"                    return resp(req.environ, start_response)"}],"source_content_type":"text/x-python","patch_set":21,"id":"5cf21ee7_98c0034f","side":"PARENT","line":882,"in_reply_to":"13d42393_4323c2f3","updated":"2023-10-05 15:30:57.000000000","message":"I think this is needed for the case when unconditional refetch returns a non-slo but the client request was conditional\n\nSee https://review.opendev.org/c/openstack/swift/+/897468","commit_id":"3d36ccc3405152b983d86faf28974cafe88521d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0b1d76caf5ef4327b324c7dfe7643f5b57ee0f42","unresolved":false,"context_lines":[{"line_number":879,"context_line":"                        app_iter\u003dresp_iter,"},{"line_number":880,"context_line":"                        request\u003dreq,"},{"line_number":881,"context_line":"                        conditional_etag\u003dresolve_etag_is_at_header("},{"line_number":882,"context_line":"                            req, self._response_headers),"},{"line_number":883,"context_line":"                        conditional_response\u003dis_success("},{"line_number":884,"context_line":"                            int(self._response_status[:3])))"},{"line_number":885,"context_line":"                    return resp(req.environ, start_response)"}],"source_content_type":"text/x-python","patch_set":21,"id":"421e493b_fd4872eb","side":"PARENT","line":882,"in_reply_to":"5cf21ee7_98c0034f","updated":"2023-10-23 18:57:56.000000000","message":"Done","commit_id":"3d36ccc3405152b983d86faf28974cafe88521d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":881,"context_line":"                        conditional_etag\u003dresolve_etag_is_at_header("},{"line_number":882,"context_line":"                            req, self._response_headers),"},{"line_number":883,"context_line":"                        conditional_response\u003dis_success("},{"line_number":884,"context_line":"                            int(self._response_status[:3])))"},{"line_number":885,"context_line":"                    return resp(req.environ, start_response)"},{"line_number":886,"context_line":"                else:"},{"line_number":887,"context_line":"                    # We saw newer data that indicated it\u0027s an SLO, but"}],"source_content_type":"text/x-python","patch_set":21,"id":"a08a60aa_514825fe","side":"PARENT","line":884,"updated":"2023-09-29 14:29:51.000000000","message":"this condition seems to have changed in the new patch\u0027s _return_raw_response()","commit_id":"3d36ccc3405152b983d86faf28974cafe88521d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0b1d76caf5ef4327b324c7dfe7643f5b57ee0f42","unresolved":false,"context_lines":[{"line_number":881,"context_line":"                        conditional_etag\u003dresolve_etag_is_at_header("},{"line_number":882,"context_line":"                            req, self._response_headers),"},{"line_number":883,"context_line":"                        conditional_response\u003dis_success("},{"line_number":884,"context_line":"                            int(self._response_status[:3])))"},{"line_number":885,"context_line":"                    return resp(req.environ, start_response)"},{"line_number":886,"context_line":"                else:"},{"line_number":887,"context_line":"                    # We saw newer data that indicated it\u0027s an SLO, but"}],"source_content_type":"text/x-python","patch_set":21,"id":"7b2f0cd7_15b1d88b","side":"PARENT","line":884,"in_reply_to":"a08a60aa_514825fe","updated":"2023-10-23 18:57:56.000000000","message":"turns out the correct answer for our new _return_non_slo_response was only `_response_status \u003d\u003d\u003d 200` - this code got away with is_success because a 206 response would have resulted in in a refetch (there\u0027s even a comment about \"this is a 200 now\")\n\n... if we\u0027re going to return with conditional_response\u003dTrue a for pass-through responses we need to give swob the whole body (alternatively if we already have a 206, maybe multi-range body, or some kind of error - we can just return that through swob with conditional_repsonse\u003dFalse and it will pass it along unmolested)","commit_id":"3d36ccc3405152b983d86faf28974cafe88521d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":1015,"context_line":"                      conditional_etag\u003dconditional_etag,"},{"line_number":1016,"context_line":"                      conditional_response\u003dTrue)"},{"line_number":1017,"context_line":""},{"line_number":1018,"context_line":"    def _manifest_get_response(self, req, content_length, response_headers,"},{"line_number":1019,"context_line":"                               segments):"},{"line_number":1020,"context_line":"        if req.range:"},{"line_number":1021,"context_line":"            byteranges \u003d ["}],"source_content_type":"text/x-python","patch_set":21,"id":"47cb583b_a3448072","side":"PARENT","line":1018,"range":{"start_line":1018,"start_character":8,"end_line":1018,"end_character":30},"updated":"2023-09-29 14:29:51.000000000","message":"this was really unhelpful naming! \n\n_manifest_get_response !\u003d the new _return_manifest_response()","commit_id":"3d36ccc3405152b983d86faf28974cafe88521d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"context_lines":[{"line_number":1015,"context_line":"                      conditional_etag\u003dconditional_etag,"},{"line_number":1016,"context_line":"                      conditional_response\u003dTrue)"},{"line_number":1017,"context_line":""},{"line_number":1018,"context_line":"    def _manifest_get_response(self, req, content_length, response_headers,"},{"line_number":1019,"context_line":"                               segments):"},{"line_number":1020,"context_line":"        if req.range:"},{"line_number":1021,"context_line":"            byteranges \u003d ["}],"source_content_type":"text/x-python","patch_set":21,"id":"3c9472b0_5e3d740a","side":"PARENT","line":1018,"range":{"start_line":1018,"start_character":8,"end_line":1018,"end_character":30},"in_reply_to":"47cb583b_a3448072","updated":"2023-09-29 19:52:06.000000000","message":"Ack","commit_id":"3d36ccc3405152b983d86faf28974cafe88521d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":577,"context_line":"        self.is_legacy \u003d self._calc_is_legacy()"},{"line_number":578,"context_line":""},{"line_number":579,"context_line":"    def _calc_is_legacy(self):"},{"line_number":580,"context_line":"        return self.size \u003c 0 or not self.etag"},{"line_number":581,"context_line":""},{"line_number":582,"context_line":"    @classmethod"},{"line_number":583,"context_line":"    def from_headers(cls, response_headers):"}],"source_content_type":"text/x-python","patch_set":21,"id":"901fe7b2_3cbff341","line":580,"updated":"2023-09-29 14:29:51.000000000","message":"I\u0027m not seeing the perhaps subtle reason for this to be a method...and the method is called at line 613?\n\nI get that is_legacy should be immutable even during the update, but... it is?","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"116890ebea9ac6698113d753af315d9a47903370","unresolved":false,"context_lines":[{"line_number":577,"context_line":"        self.is_legacy \u003d self._calc_is_legacy()"},{"line_number":578,"context_line":""},{"line_number":579,"context_line":"    def _calc_is_legacy(self):"},{"line_number":580,"context_line":"        return self.size \u003c 0 or not self.etag"},{"line_number":581,"context_line":""},{"line_number":582,"context_line":"    @classmethod"},{"line_number":583,"context_line":"    def from_headers(cls, response_headers):"}],"source_content_type":"text/x-python","patch_set":21,"id":"e62c21a7_1812265a","line":580,"in_reply_to":"901fe7b2_3cbff341","updated":"2023-10-05 15:30:57.000000000","message":"A: this allows the early return from update_from_segments","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"context_lines":[{"line_number":577,"context_line":"        self.is_legacy \u003d self._calc_is_legacy()"},{"line_number":578,"context_line":""},{"line_number":579,"context_line":"    def _calc_is_legacy(self):"},{"line_number":580,"context_line":"        return self.size \u003c 0 or not self.etag"},{"line_number":581,"context_line":""},{"line_number":582,"context_line":"    @classmethod"},{"line_number":583,"context_line":"    def from_headers(cls, response_headers):"}],"source_content_type":"text/x-python","patch_set":21,"id":"07aee5d9_babd151a","line":580,"in_reply_to":"901fe7b2_3cbff341","updated":"2023-09-29 19:52:06.000000000","message":"_has_etag_and_size()","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":640,"context_line":"        self.slo \u003d slo"},{"line_number":641,"context_line":"        super(SloGetContext, self).__init__(slo.app)"},{"line_number":642,"context_line":"        # we\u0027ll know more after we look at the response metadata"},{"line_number":643,"context_line":"        self.segments_needed \u003d False"},{"line_number":644,"context_line":""},{"line_number":645,"context_line":"    def _fetch_sub_slo_segments(self, req, version, acc, con, obj):"},{"line_number":646,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":21,"id":"565e579f_f1312488","line":643,"updated":"2023-09-29 14:29:51.000000000","message":"nit: This var name kind of makes sense because the flag governs if we parse and annotate the segments.\n\nBut, I think of \"segments\" as being the objects in the +segments container, and they\u0027re not needed for a HEAD! What\u0027s being parsed is the *list of segments* in the manifest. We also have _segment_listing_iterator and convert_segment_listing.","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"context_lines":[{"line_number":640,"context_line":"        self.slo \u003d slo"},{"line_number":641,"context_line":"        super(SloGetContext, self).__init__(slo.app)"},{"line_number":642,"context_line":"        # we\u0027ll know more after we look at the response metadata"},{"line_number":643,"context_line":"        self.segments_needed \u003d False"},{"line_number":644,"context_line":""},{"line_number":645,"context_line":"    def _fetch_sub_slo_segments(self, req, version, acc, con, obj):"},{"line_number":646,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":21,"id":"272b60fe_4730b734","line":643,"in_reply_to":"565e579f_f1312488","updated":"2023-09-29 19:52:06.000000000","message":"segment_listing_needed","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":808,"context_line":"            first_byte -\u003d seg_length"},{"line_number":809,"context_line":"            last_byte -\u003d seg_length"},{"line_number":810,"context_line":""},{"line_number":811,"context_line":"    def _is_body_complete(self):"},{"line_number":812,"context_line":"        content_range \u003d \u0027\u0027"},{"line_number":813,"context_line":"        for header, value in self._response_headers:"},{"line_number":814,"context_line":"            if header.lower() \u003d\u003d \u0027content-range\u0027:"}],"source_content_type":"text/x-python","patch_set":21,"id":"4730bfed_d2d3af56","line":811,"updated":"2023-09-29 14:29:51.000000000","message":"+1 this is better without the is_range_response condition","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"context_lines":[{"line_number":808,"context_line":"            first_byte -\u003d seg_length"},{"line_number":809,"context_line":"            last_byte -\u003d seg_length"},{"line_number":810,"context_line":""},{"line_number":811,"context_line":"    def _is_body_complete(self):"},{"line_number":812,"context_line":"        content_range \u003d \u0027\u0027"},{"line_number":813,"context_line":"        for header, value in self._response_headers:"},{"line_number":814,"context_line":"            if header.lower() \u003d\u003d \u0027content-range\u0027:"}],"source_content_type":"text/x-python","patch_set":21,"id":"5ca54c54_d236e7ce","line":811,"in_reply_to":"4730bfed_d2d3af56","updated":"2023-09-29 19:52:06.000000000","message":"Ack","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":872,"context_line":"        # refetch"},{"line_number":873,"context_line":"        if self._response_status_int \u003d\u003d 416:"},{"line_number":874,"context_line":"            # if the range wasn\u0027t satisfiable we need to refetch"},{"line_number":875,"context_line":"            return True"},{"line_number":876,"context_line":"        elif self._response_status_int \u003d\u003d 206:"},{"line_number":877,"context_line":"            # a partial response might included the whole content-range?!"},{"line_number":878,"context_line":"            return not self._is_body_complete()"}],"source_content_type":"text/x-python","patch_set":21,"id":"681f9a0c_fb28ae14","line":875,"updated":"2023-09-29 14:29:51.000000000","message":"ok but on master we still checked if body might be complete: IIUC from swob.Response, a 416 has no body, so it\u0027s moot","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"context_lines":[{"line_number":872,"context_line":"        # refetch"},{"line_number":873,"context_line":"        if self._response_status_int \u003d\u003d 416:"},{"line_number":874,"context_line":"            # if the range wasn\u0027t satisfiable we need to refetch"},{"line_number":875,"context_line":"            return True"},{"line_number":876,"context_line":"        elif self._response_status_int \u003d\u003d 206:"},{"line_number":877,"context_line":"            # a partial response might included the whole content-range?!"},{"line_number":878,"context_line":"            return not self._is_body_complete()"}],"source_content_type":"text/x-python","patch_set":21,"id":"0a19f434_29236b74","line":875,"in_reply_to":"681f9a0c_fb28ae14","updated":"2023-09-29 19:52:06.000000000","message":"Ack","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":879,"context_line":""},{"line_number":880,"context_line":"        # we\u0027re out of ideas for stuff that could\u0027ve gone wrong,"},{"line_number":881,"context_line":"        # this response will just have to do"},{"line_number":882,"context_line":"        assert is_success(self._response_status_int)"},{"line_number":883,"context_line":"        return False"},{"line_number":884,"context_line":""},{"line_number":885,"context_line":"    def _refetch_manifest(self, req, resp_iter, orig_slo_attrs):"}],"source_content_type":"text/x-python","patch_set":21,"id":"ce39166b_62d9157a","line":882,"updated":"2023-09-29 14:29:51.000000000","message":"we get here for any GET response with X-Static-Large-Object and status not in (304, 412, 416, 206)\n\nwithout this assert...\nIF something downstream was leaking X-Static-Large-Object with a non-success response, then we\u0027ve set segments_needed \u003d True so I guess parse_segments would raise an HTTPException","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0b1d76caf5ef4327b324c7dfe7643f5b57ee0f42","unresolved":false,"context_lines":[{"line_number":879,"context_line":""},{"line_number":880,"context_line":"        # we\u0027re out of ideas for stuff that could\u0027ve gone wrong,"},{"line_number":881,"context_line":"        # this response will just have to do"},{"line_number":882,"context_line":"        assert is_success(self._response_status_int)"},{"line_number":883,"context_line":"        return False"},{"line_number":884,"context_line":""},{"line_number":885,"context_line":"    def _refetch_manifest(self, req, resp_iter, orig_slo_attrs):"}],"source_content_type":"text/x-python","patch_set":21,"id":"8c66b4d3_c14e6c00","line":882,"in_reply_to":"4c636240_b2ae4649","updated":"2023-10-23 18:57:56.000000000","message":"I\u0027m not sure there\u0027s a more elegant way to express the assumptions that make this code correct; but I added a test that slo metadata on non-success response does result in a 500 error - at least we consistent with master.","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":true,"context_lines":[{"line_number":879,"context_line":""},{"line_number":880,"context_line":"        # we\u0027re out of ideas for stuff that could\u0027ve gone wrong,"},{"line_number":881,"context_line":"        # this response will just have to do"},{"line_number":882,"context_line":"        assert is_success(self._response_status_int)"},{"line_number":883,"context_line":"        return False"},{"line_number":884,"context_line":""},{"line_number":885,"context_line":"    def _refetch_manifest(self, req, resp_iter, orig_slo_attrs):"}],"source_content_type":"text/x-python","patch_set":21,"id":"4c636240_b2ae4649","line":882,"in_reply_to":"ce39166b_62d9157a","updated":"2023-09-29 19:52:06.000000000","message":"drop this out, but it is still weird/scary\n\nwhat about a 404 + x-slo sysmeta?","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":880,"context_line":"        # we\u0027re out of ideas for stuff that could\u0027ve gone wrong,"},{"line_number":881,"context_line":"        # this response will just have to do"},{"line_number":882,"context_line":"        assert is_success(self._response_status_int)"},{"line_number":883,"context_line":"        return False"},{"line_number":884,"context_line":""},{"line_number":885,"context_line":"    def _refetch_manifest(self, req, resp_iter, orig_slo_attrs):"},{"line_number":886,"context_line":"        req.environ[\u0027swift.non_client_disconnect\u0027] \u003d True"}],"source_content_type":"text/x-python","patch_set":21,"id":"a8e815b6_29769959","line":883,"updated":"2023-09-29 14:29:51.000000000","message":"+1 this method has cleaned up nicely","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"context_lines":[{"line_number":880,"context_line":"        # we\u0027re out of ideas for stuff that could\u0027ve gone wrong,"},{"line_number":881,"context_line":"        # this response will just have to do"},{"line_number":882,"context_line":"        assert is_success(self._response_status_int)"},{"line_number":883,"context_line":"        return False"},{"line_number":884,"context_line":""},{"line_number":885,"context_line":"    def _refetch_manifest(self, req, resp_iter, orig_slo_attrs):"},{"line_number":886,"context_line":"        req.environ[\u0027swift.non_client_disconnect\u0027] \u003d True"}],"source_content_type":"text/x-python","patch_set":21,"id":"41e63e62_710ce992","line":883,"in_reply_to":"a8e815b6_29769959","updated":"2023-09-29 19:52:06.000000000","message":"Ack","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":894,"context_line":"        resp_iter \u003d self._app_call(get_req.environ)"},{"line_number":895,"context_line":"        new_slo_attrs \u003d SloAttrs.from_headers(self._response_headers)"},{"line_number":896,"context_line":"        if not new_slo_attrs.is_slo:"},{"line_number":897,"context_line":"            if new_slo_attrs.timestamp \u003e\u003d orig_slo_attrs.timestamp:"},{"line_number":898,"context_line":"                # We\u0027ve got a newer response available, so serve that."},{"line_number":899,"context_line":"                # Note that if there\u0027s data, it\u0027s going to be a 200 now,"},{"line_number":900,"context_line":"                # not a 206, and we\u0027re not going to drop bytes in the"}],"source_content_type":"text/x-python","patch_set":21,"id":"f286f016_62550569","line":897,"updated":"2023-09-29 14:29:51.000000000","message":"ok, so this is maybe the one place where it\u0027s obvious that we need to pass around an SloAttrs rather than have SloGetContext *be* an SloAttrs","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"context_lines":[{"line_number":894,"context_line":"        resp_iter \u003d self._app_call(get_req.environ)"},{"line_number":895,"context_line":"        new_slo_attrs \u003d SloAttrs.from_headers(self._response_headers)"},{"line_number":896,"context_line":"        if not new_slo_attrs.is_slo:"},{"line_number":897,"context_line":"            if new_slo_attrs.timestamp \u003e\u003d orig_slo_attrs.timestamp:"},{"line_number":898,"context_line":"                # We\u0027ve got a newer response available, so serve that."},{"line_number":899,"context_line":"                # Note that if there\u0027s data, it\u0027s going to be a 200 now,"},{"line_number":900,"context_line":"                # not a 206, and we\u0027re not going to drop bytes in the"}],"source_content_type":"text/x-python","patch_set":21,"id":"0a931dff_2eceb68f","line":897,"in_reply_to":"f286f016_62550569","updated":"2023-09-29 19:52:06.000000000","message":"Ack","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":967,"context_line":"            app_iter\u003dresp_iter,"},{"line_number":968,"context_line":"            request\u003dreq,"},{"line_number":969,"context_line":"            conditional_response\u003dTrue,"},{"line_number":970,"context_line":"            conditional_etag\u003dresolve_etag_is_at_header(req, resp_headers))"},{"line_number":971,"context_line":"        return resp(req.environ, start_response)"},{"line_number":972,"context_line":""},{"line_number":973,"context_line":"    def _return_raw_response(self, req, start_response, resp_iter):"}],"source_content_type":"text/x-python","patch_set":21,"id":"d1dddd28_7db00048","line":970,"updated":"2023-09-29 14:29:51.000000000","message":"I don\u0027t see this in the original response for manifest_get\u0027s, only for actual large body get\u0027s and head\u0027s","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"116890ebea9ac6698113d753af315d9a47903370","unresolved":true,"context_lines":[{"line_number":967,"context_line":"            app_iter\u003dresp_iter,"},{"line_number":968,"context_line":"            request\u003dreq,"},{"line_number":969,"context_line":"            conditional_response\u003dTrue,"},{"line_number":970,"context_line":"            conditional_etag\u003dresolve_etag_is_at_header(req, resp_headers))"},{"line_number":971,"context_line":"        return resp(req.environ, start_response)"},{"line_number":972,"context_line":""},{"line_number":973,"context_line":"    def _return_raw_response(self, req, start_response, resp_iter):"}],"source_content_type":"text/x-python","patch_set":21,"id":"d0a41623_eb4bd4c2","line":970,"in_reply_to":"90d3d9d2_38a20ebb","updated":"2023-10-05 15:30:57.000000000","message":"ok, I now think it is *necessary* to set conditional_etag\u003dresolve_etag_is_at_header(req, resp_headers)\n\nConsider an if-match with etag-is-at other-place, that matches at the backend so backend returns 200:\n\n- on master we use response status from the backend request.\n\n- Here we construct a fresh Response, which will perform the if-match logic again and so it *needs to know* that the request has an etag-is-at pointing to other-place, otherwise it will turn into a 412 even though the backend response was a 200.\n\nWill add a test.","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0b1d76caf5ef4327b324c7dfe7643f5b57ee0f42","unresolved":false,"context_lines":[{"line_number":967,"context_line":"            app_iter\u003dresp_iter,"},{"line_number":968,"context_line":"            request\u003dreq,"},{"line_number":969,"context_line":"            conditional_response\u003dTrue,"},{"line_number":970,"context_line":"            conditional_etag\u003dresolve_etag_is_at_header(req, resp_headers))"},{"line_number":971,"context_line":"        return resp(req.environ, start_response)"},{"line_number":972,"context_line":""},{"line_number":973,"context_line":"    def _return_raw_response(self, req, start_response, resp_iter):"}],"source_content_type":"text/x-python","patch_set":21,"id":"30ced663_941655e7","line":970,"in_reply_to":"d0a41623_eb4bd4c2","updated":"2023-10-23 18:57:56.000000000","message":"Done","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":true,"context_lines":[{"line_number":967,"context_line":"            app_iter\u003dresp_iter,"},{"line_number":968,"context_line":"            request\u003dreq,"},{"line_number":969,"context_line":"            conditional_response\u003dTrue,"},{"line_number":970,"context_line":"            conditional_etag\u003dresolve_etag_is_at_header(req, resp_headers))"},{"line_number":971,"context_line":"        return resp(req.environ, start_response)"},{"line_number":972,"context_line":""},{"line_number":973,"context_line":"    def _return_raw_response(self, req, start_response, resp_iter):"}],"source_content_type":"text/x-python","patch_set":21,"id":"90d3d9d2_38a20ebb","line":970,"in_reply_to":"d1dddd28_7db00048","updated":"2023-09-29 19:52:06.000000000","message":"do we have conditional requests tests for manifests!?\n\nwhat happens if I just change this to resp_headers[\u0027Etag\u0027]!?\n\n... so sketch","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":970,"context_line":"            conditional_etag\u003dresolve_etag_is_at_header(req, resp_headers))"},{"line_number":971,"context_line":"        return resp(req.environ, start_response)"},{"line_number":972,"context_line":""},{"line_number":973,"context_line":"    def _return_raw_response(self, req, start_response, resp_iter):"},{"line_number":974,"context_line":"        # our \"pass-through\" response may have been from a manifest refetch w/o"},{"line_number":975,"context_line":"        # range headers that turned out to be a real object, but if the client"},{"line_number":976,"context_line":"        # included a Range header we can trust swob to do the right conversion"}],"source_content_type":"text/x-python","patch_set":21,"id":"d5c8eaf2_bbb71af5","line":973,"updated":"2023-09-29 14:29:51.000000000","message":"\u0027raw\u0027 here is confusing w.r.t. \u0027raw\u0027 manifest responses...how about _return_non_slo_response?","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"context_lines":[{"line_number":970,"context_line":"            conditional_etag\u003dresolve_etag_is_at_header(req, resp_headers))"},{"line_number":971,"context_line":"        return resp(req.environ, start_response)"},{"line_number":972,"context_line":""},{"line_number":973,"context_line":"    def _return_raw_response(self, req, start_response, resp_iter):"},{"line_number":974,"context_line":"        # our \"pass-through\" response may have been from a manifest refetch w/o"},{"line_number":975,"context_line":"        # range headers that turned out to be a real object, but if the client"},{"line_number":976,"context_line":"        # included a Range header we can trust swob to do the right conversion"}],"source_content_type":"text/x-python","patch_set":21,"id":"50dc0a43_a2f1d38f","line":973,"in_reply_to":"d5c8eaf2_bbb71af5","updated":"2023-09-29 19:52:06.000000000","message":"_return_non_slo_response sounds great!","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":true,"context_lines":[{"line_number":975,"context_line":"        # range headers that turned out to be a real object, but if the client"},{"line_number":976,"context_line":"        # included a Range header we can trust swob to do the right conversion"},{"line_number":977,"context_line":"        # back into a 206"},{"line_number":978,"context_line":"        conditional_response \u003d req.range and self._response_status_int \u003d\u003d 200"},{"line_number":979,"context_line":"        resp \u003d Response("},{"line_number":980,"context_line":"            status\u003dself._response_status,"},{"line_number":981,"context_line":"            headers\u003dself._response_headers,"}],"source_content_type":"text/x-python","patch_set":21,"id":"1851b7d5_ef8452ef","line":978,"updated":"2023-09-29 19:52:06.000000000","message":"yeah, this is slightly different than conditions used to describe the behaviors it was trying to preseve.  We should double check the tests - although I sort of think it was the existing tests that lead me to this being the correct code in the first place.\n\nparticuarlly around x-if-match etag handling for the resolve-etag-is-at change","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0b1d76caf5ef4327b324c7dfe7643f5b57ee0f42","unresolved":false,"context_lines":[{"line_number":975,"context_line":"        # range headers that turned out to be a real object, but if the client"},{"line_number":976,"context_line":"        # included a Range header we can trust swob to do the right conversion"},{"line_number":977,"context_line":"        # back into a 206"},{"line_number":978,"context_line":"        conditional_response \u003d req.range and self._response_status_int \u003d\u003d 200"},{"line_number":979,"context_line":"        resp \u003d Response("},{"line_number":980,"context_line":"            status\u003dself._response_status,"},{"line_number":981,"context_line":"            headers\u003dself._response_headers,"}],"source_content_type":"text/x-python","patch_set":21,"id":"e796ce8c_6b19e306","line":978,"in_reply_to":"1851b7d5_ef8452ef","updated":"2023-10-23 18:57:56.000000000","message":"ultimately we decided _response_status_int \u003d\u003d 200 was sufficient for swob to do the right thing with refetched responses that had removed conditional headers\n\nthe if[-none]-match and if-[un]modifed-since passthrough tests were a bit lacking; but functests helped us get the bugs worked out and the related change fills in all the unittest gaps.","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","unresolved":true,"context_lines":[{"line_number":1013,"context_line":"            slo_attrs, resp_iter \u003d self._refetch_manifest("},{"line_number":1014,"context_line":"                req, resp_iter, slo_attrs)"},{"line_number":1015,"context_line":""},{"line_number":1016,"context_line":"        if not slo_attrs.is_slo:"},{"line_number":1017,"context_line":"            # even if the original slo_attrs maybe have been SLO we may have"},{"line_number":1018,"context_line":"            # refetched, this also handles the server error case"},{"line_number":1019,"context_line":"            return self._return_raw_response(req, start_response, resp_iter)"},{"line_number":1020,"context_line":"        elif is_manifest_get:"},{"line_number":1021,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"},{"line_number":1022,"context_line":"            return self._return_manifest_response(req, start_response,"},{"line_number":1023,"context_line":"                                                  resp_iter, is_format_raw)"},{"line_number":1024,"context_line":""},{"line_number":1025,"context_line":"        # this a GET/HEAD response for the SLO object (not the manifest)"},{"line_number":1026,"context_line":"        if self.segments_needed:"},{"line_number":1027,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1028,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1029,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1030,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"},{"line_number":1031,"context_line":"                # frist segment on HEAD"},{"line_number":1032,"context_line":"                resp_iter \u003d self._build_resp_iter(req, segments, slo_attrs)"},{"line_number":1033,"context_line":"        else:"},{"line_number":1034,"context_line":"            # if we\u0027d\u0027ve needed the segments we\u0027d\u0027ve refetched them without"},{"line_number":1035,"context_line":"            # conditions already, so this is a HEAD or conditional response"},{"line_number":1036,"context_line":"            # from a new-style manifests or something; but whatever the reason"},{"line_number":1037,"context_line":"            # our SLO response doesn\u0027t need the segments from this manifest"},{"line_number":1038,"context_line":"            # resp_iter - so we can close it down"},{"line_number":1039,"context_line":"            friendly_close(resp_iter)  # swob will discard this anyway"},{"line_number":1040,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1041,"context_line":"                                         slo_attrs)"},{"line_number":1042,"context_line":""},{"line_number":1043,"context_line":"    def convert_segment_listing(self, resp_iter):"},{"line_number":1044,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":21,"id":"cc53f5a1_7db09aa6","line":1041,"range":{"start_line":1016,"start_character":1,"end_line":1041,"end_character":51},"updated":"2023-09-29 14:29:51.000000000","message":"this is so much nicer!","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"context_lines":[{"line_number":1013,"context_line":"            slo_attrs, resp_iter \u003d self._refetch_manifest("},{"line_number":1014,"context_line":"                req, resp_iter, slo_attrs)"},{"line_number":1015,"context_line":""},{"line_number":1016,"context_line":"        if not slo_attrs.is_slo:"},{"line_number":1017,"context_line":"            # even if the original slo_attrs maybe have been SLO we may have"},{"line_number":1018,"context_line":"            # refetched, this also handles the server error case"},{"line_number":1019,"context_line":"            return self._return_raw_response(req, start_response, resp_iter)"},{"line_number":1020,"context_line":"        elif is_manifest_get:"},{"line_number":1021,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"},{"line_number":1022,"context_line":"            return self._return_manifest_response(req, start_response,"},{"line_number":1023,"context_line":"                                                  resp_iter, is_format_raw)"},{"line_number":1024,"context_line":""},{"line_number":1025,"context_line":"        # this a GET/HEAD response for the SLO object (not the manifest)"},{"line_number":1026,"context_line":"        if self.segments_needed:"},{"line_number":1027,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1028,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1029,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1030,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"},{"line_number":1031,"context_line":"                # frist segment on HEAD"},{"line_number":1032,"context_line":"                resp_iter \u003d self._build_resp_iter(req, segments, slo_attrs)"},{"line_number":1033,"context_line":"        else:"},{"line_number":1034,"context_line":"            # if we\u0027d\u0027ve needed the segments we\u0027d\u0027ve refetched them without"},{"line_number":1035,"context_line":"            # conditions already, so this is a HEAD or conditional response"},{"line_number":1036,"context_line":"            # from a new-style manifests or something; but whatever the reason"},{"line_number":1037,"context_line":"            # our SLO response doesn\u0027t need the segments from this manifest"},{"line_number":1038,"context_line":"            # resp_iter - so we can close it down"},{"line_number":1039,"context_line":"            friendly_close(resp_iter)  # swob will discard this anyway"},{"line_number":1040,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1041,"context_line":"                                         slo_attrs)"},{"line_number":1042,"context_line":""},{"line_number":1043,"context_line":"    def convert_segment_listing(self, resp_iter):"},{"line_number":1044,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":21,"id":"75e546c0_c851823a","line":1041,"range":{"start_line":1016,"start_character":1,"end_line":1041,"end_character":51},"in_reply_to":"cc53f5a1_7db09aa6","updated":"2023-09-29 19:52:06.000000000","message":"yeah, i feel pretty good about this *finally*","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":565,"context_line":""},{"line_number":566,"context_line":"class SloAttrs(object):"},{"line_number":567,"context_line":"    def __init__(self, is_slo, etag, manifest_etag, size, timestamp):"},{"line_number":568,"context_line":"        self.segments \u003d None"},{"line_number":569,"context_line":"        self.is_slo \u003d bool(is_slo)"},{"line_number":570,"context_line":"        self.etag \u003d etag or \u0027\u0027"},{"line_number":571,"context_line":"        self.manifest_etag \u003d manifest_etag or \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":31,"id":"56dc72b8_e2d31f5e","line":568,"updated":"2023-10-25 14:57:41.000000000","message":"this seems premature - I can see how it will be used in the next patch, but in the context of this patch it is unused. I don\u0027t see the need to add it ahead of the partnum patch.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":565,"context_line":""},{"line_number":566,"context_line":"class SloAttrs(object):"},{"line_number":567,"context_line":"    def __init__(self, is_slo, etag, manifest_etag, size, timestamp):"},{"line_number":568,"context_line":"        self.segments \u003d None"},{"line_number":569,"context_line":"        self.is_slo \u003d bool(is_slo)"},{"line_number":570,"context_line":"        self.etag \u003d etag or \u0027\u0027"},{"line_number":571,"context_line":"        self.manifest_etag \u003d manifest_etag or \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":31,"id":"b632bf0e_ec75b2a3","line":568,"in_reply_to":"56dc72b8_e2d31f5e","updated":"2023-10-26 00:15:45.000000000","message":"Ack","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":568,"context_line":"        self.segments \u003d None"},{"line_number":569,"context_line":"        self.is_slo \u003d bool(is_slo)"},{"line_number":570,"context_line":"        self.etag \u003d etag or \u0027\u0027"},{"line_number":571,"context_line":"        self.manifest_etag \u003d manifest_etag or \u0027\u0027"},{"line_number":572,"context_line":"        try:"},{"line_number":573,"context_line":"            # even though it\u0027s from sysmeta, we have to worry about empty"},{"line_number":574,"context_line":"            # values - see test_get_invalid_sysmeta_passthrough"}],"source_content_type":"text/x-python","patch_set":31,"id":"6b5dcff2_d54da9ce","line":571,"updated":"2023-10-25 14:57:41.000000000","message":"this seems reasonable","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":568,"context_line":"        self.segments \u003d None"},{"line_number":569,"context_line":"        self.is_slo \u003d bool(is_slo)"},{"line_number":570,"context_line":"        self.etag \u003d etag or \u0027\u0027"},{"line_number":571,"context_line":"        self.manifest_etag \u003d manifest_etag or \u0027\u0027"},{"line_number":572,"context_line":"        try:"},{"line_number":573,"context_line":"            # even though it\u0027s from sysmeta, we have to worry about empty"},{"line_number":574,"context_line":"            # values - see test_get_invalid_sysmeta_passthrough"}],"source_content_type":"text/x-python","patch_set":31,"id":"7c1d87d6_ab5ce9ae","line":571,"in_reply_to":"6b5dcff2_d54da9ce","updated":"2023-10-26 00:15:45.000000000","message":"Ack","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":611,"context_line":""},{"line_number":612,"context_line":"    def update_from_segments(self, segments):"},{"line_number":613,"context_line":"        \"\"\""},{"line_number":614,"context_line":"        Only useful for legacy manifests or part-num requests, calculate"},{"line_number":615,"context_line":"        size/etag values we wouldn\u0027t have gotten from sys-meta headers."},{"line_number":616,"context_line":"        \"\"\""},{"line_number":617,"context_line":"        self.segments \u003d segments"}],"source_content_type":"text/x-python","patch_set":31,"id":"fbc535e4_a0d32391","line":614,"range":{"start_line":614,"start_character":44,"end_line":614,"end_character":61},"updated":"2023-10-25 14:57:41.000000000","message":"this is definitely premature","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":611,"context_line":""},{"line_number":612,"context_line":"    def update_from_segments(self, segments):"},{"line_number":613,"context_line":"        \"\"\""},{"line_number":614,"context_line":"        Only useful for legacy manifests or part-num requests, calculate"},{"line_number":615,"context_line":"        size/etag values we wouldn\u0027t have gotten from sys-meta headers."},{"line_number":616,"context_line":"        \"\"\""},{"line_number":617,"context_line":"        self.segments \u003d segments"}],"source_content_type":"text/x-python","patch_set":31,"id":"c6a083e1_9d92dbce","line":614,"range":{"start_line":614,"start_character":44,"end_line":614,"end_character":61},"in_reply_to":"fbc535e4_a0d32391","updated":"2023-10-26 00:15:45.000000000","message":"hahah!  #willfix","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":856,"context_line":"            # segment_listing_needed"},{"line_number":857,"context_line":"            return self.segment_listing_needed"},{"line_number":858,"context_line":""},{"line_number":859,"context_line":"        # These are based on etag (or last-modified), but the SLO\u0027s etag is"},{"line_number":860,"context_line":"        # almost certainly not the manifest object\u0027s etag. Still, it\u0027s highly"},{"line_number":861,"context_line":"        # likely that the submitted If-None-Match won\u0027t match the manifest"},{"line_number":862,"context_line":"        # object\u0027s etag, so we can avoid re-fetching the manifest if we got a"}],"source_content_type":"text/x-python","patch_set":31,"id":"d73e3c72_78db7537","line":859,"range":{"start_line":859,"start_character":38,"end_line":859,"end_character":51},"updated":"2023-10-25 14:57:41.000000000","message":"so if it\u0027s a conditional error based on last-modified, and legacy, we\u0027ll refetch unnecessarily (we don\u0027t need the segments)? IMO that\u0027s ok, otherwise we\u0027d have to parse the request headers to figure out what caused the 304 - just want to make sure I understand.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":856,"context_line":"            # segment_listing_needed"},{"line_number":857,"context_line":"            return self.segment_listing_needed"},{"line_number":858,"context_line":""},{"line_number":859,"context_line":"        # These are based on etag (or last-modified), but the SLO\u0027s etag is"},{"line_number":860,"context_line":"        # almost certainly not the manifest object\u0027s etag. Still, it\u0027s highly"},{"line_number":861,"context_line":"        # likely that the submitted If-None-Match won\u0027t match the manifest"},{"line_number":862,"context_line":"        # object\u0027s etag, so we can avoid re-fetching the manifest if we got a"}],"source_content_type":"text/x-python","patch_set":31,"id":"0f30a803_1fa54297","line":859,"range":{"start_line":859,"start_character":38,"end_line":859,"end_character":51},"in_reply_to":"d73e3c72_78db7537","updated":"2023-10-26 00:15:45.000000000","message":"turns out we DO need the segments!  we can\u0027t response 304 not-modified with the \"correct\" slo-etag unless we fetch the body.  I learned this writing tests but I can update the comment.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":858,"context_line":""},{"line_number":859,"context_line":"        # These are based on etag (or last-modified), but the SLO\u0027s etag is"},{"line_number":860,"context_line":"        # almost certainly not the manifest object\u0027s etag. Still, it\u0027s highly"},{"line_number":861,"context_line":"        # likely that the submitted If-None-Match won\u0027t match the manifest"},{"line_number":862,"context_line":"        # object\u0027s etag, so we can avoid re-fetching the manifest if we got a"},{"line_number":863,"context_line":"        # successful response."},{"line_number":864,"context_line":"        if is_conditional_error(self._response_status_int):"}],"source_content_type":"text/x-python","patch_set":31,"id":"b0ad8ae3_a4cd8d46","line":861,"range":{"start_line":861,"start_character":36,"end_line":861,"end_character":49},"updated":"2023-10-25 14:57:41.000000000","message":"I\u0027m confused again !?! we get a success response because the etag did not match If-None-Match, but it\u0027s legacy so we don\u0027t know the correct etag - how do we know that this If-None-Match on a legacy manifest should not actually return 304 unless we get the segments?","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":858,"context_line":""},{"line_number":859,"context_line":"        # These are based on etag (or last-modified), but the SLO\u0027s etag is"},{"line_number":860,"context_line":"        # almost certainly not the manifest object\u0027s etag. Still, it\u0027s highly"},{"line_number":861,"context_line":"        # likely that the submitted If-None-Match won\u0027t match the manifest"},{"line_number":862,"context_line":"        # object\u0027s etag, so we can avoid re-fetching the manifest if we got a"},{"line_number":863,"context_line":"        # successful response."},{"line_number":864,"context_line":"        if is_conditional_error(self._response_status_int):"}],"source_content_type":"text/x-python","patch_set":31,"id":"f7773094_c4bcd67d","line":861,"range":{"start_line":861,"start_character":36,"end_line":861,"end_character":49},"in_reply_to":"b0ad8ae3_a4cd8d46","updated":"2023-10-26 00:15:45.000000000","message":"umm.. this function decides two things\n\n1) are we going to need the segments\n2) should we refetch the manifest\n\nit doesn\u0027t decide if we should return the response or if we should error; that will happen later - possibly after we\u0027ve refetched the manifest.  So here we say \"this is a conditional error, and for legacy attrs we\u0027ll need the segments, so if we need them we better refetch them\" - then later swob will decide what the repsonse should be.  It *is* confusing isn\u0027t it!?  It\u0027s hopeless - you cna\u0027t undrestand this code enough to say it\u0027s correct - lots of tests is our only hope.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d110631b6c6835cee843e209fde32c6bfefab186","unresolved":false,"context_lines":[{"line_number":858,"context_line":""},{"line_number":859,"context_line":"        # These are based on etag (or last-modified), but the SLO\u0027s etag is"},{"line_number":860,"context_line":"        # almost certainly not the manifest object\u0027s etag. Still, it\u0027s highly"},{"line_number":861,"context_line":"        # likely that the submitted If-None-Match won\u0027t match the manifest"},{"line_number":862,"context_line":"        # object\u0027s etag, so we can avoid re-fetching the manifest if we got a"},{"line_number":863,"context_line":"        # successful response."},{"line_number":864,"context_line":"        if is_conditional_error(self._response_status_int):"}],"source_content_type":"text/x-python","patch_set":31,"id":"790b828e_897e779e","line":861,"range":{"start_line":861,"start_character":36,"end_line":861,"end_character":49},"in_reply_to":"f7773094_c4bcd67d","updated":"2023-10-27 17:44:25.000000000","message":"I\u0027m sorry :/ I\u0027m glad I am not alone is struggling to grok this.  I should go and find the test, but my concern was:\n\nit\u0027s legacy, and json_md5\u003d\u0027abc\u0027\n\nIf-None-Match: \u0027xyz\u0027 returns success because \u0027abc\u0027 !\u003d \u0027xyz\u0027\n\nbut don\u0027t we need to calculate the slo etag and compare that to \u0027xyz\u0027?\n\nOhhh! but line 876, of course!","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d110631b6c6835cee843e209fde32c6bfefab186","unresolved":true,"context_lines":[{"line_number":859,"context_line":"        # These are based on etag (or last-modified), but the SLO\u0027s etag is"},{"line_number":860,"context_line":"        # almost certainly not the manifest object\u0027s etag. Still, it\u0027s highly"},{"line_number":861,"context_line":"        # likely that the submitted If-None-Match won\u0027t match the manifest"},{"line_number":862,"context_line":"        # object\u0027s etag, so we can avoid re-fetching the manifest if we got a"},{"line_number":863,"context_line":"        # successful response."},{"line_number":864,"context_line":"        if is_conditional_error(self._response_status_int):"},{"line_number":865,"context_line":"            # a conditional response from a modern manifest would have an"},{"line_number":866,"context_line":"            # accurate SLO etag, AND comparison with the etag-is-at header, but"}],"source_content_type":"text/x-python","patch_set":31,"id":"902b8dfe_79b96ef9","line":863,"range":{"start_line":862,"start_character":25,"end_line":863,"end_character":29},"updated":"2023-10-27 17:44:25.000000000","message":"nope! I think this is maybe what threw me (that\u0027ll teach me to read comments)\n\n\"we may be able to avoid re-fetching the manifest if we got a successful response, so long as we got all of it\" - lines 881-886","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96235704ef07bcf9f723add0d0358b7085dd4b06","unresolved":false,"context_lines":[{"line_number":859,"context_line":"        # These are based on etag (or last-modified), but the SLO\u0027s etag is"},{"line_number":860,"context_line":"        # almost certainly not the manifest object\u0027s etag. Still, it\u0027s highly"},{"line_number":861,"context_line":"        # likely that the submitted If-None-Match won\u0027t match the manifest"},{"line_number":862,"context_line":"        # object\u0027s etag, so we can avoid re-fetching the manifest if we got a"},{"line_number":863,"context_line":"        # successful response."},{"line_number":864,"context_line":"        if is_conditional_error(self._response_status_int):"},{"line_number":865,"context_line":"            # a conditional response from a modern manifest would have an"},{"line_number":866,"context_line":"            # accurate SLO etag, AND comparison with the etag-is-at header, but"}],"source_content_type":"text/x-python","patch_set":31,"id":"d9fca5b2_12fab69d","line":863,"range":{"start_line":862,"start_character":25,"end_line":863,"end_character":29},"in_reply_to":"902b8dfe_79b96ef9","updated":"2023-10-28 01:32:43.000000000","message":"heh, in this context I *meant* \"successful\" \u003d\u003d \"good and complete\" not \"merely\" 2XX - english sucks, code is better, comments are a weakness.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":864,"context_line":"        if is_conditional_error(self._response_status_int):"},{"line_number":865,"context_line":"            # a conditional response from a modern manifest would have an"},{"line_number":866,"context_line":"            # accurate SLO etag, AND comparison with the etag-is-at header, but"},{"line_number":867,"context_line":"            # for legacy manifests we can\u0027t say what the is or if it matches"},{"line_number":868,"context_line":"            # unless we calculate it from segments - so we need them"},{"line_number":869,"context_line":"            self.segment_listing_needed \u003d slo_attrs.is_legacy"},{"line_number":870,"context_line":"            # if we need them; we can\u0027t get them from the error"}],"source_content_type":"text/x-python","patch_set":31,"id":"4a916b2a_adcc6eea","line":867,"range":{"start_line":867,"start_character":53,"end_line":867,"end_character":59},"updated":"2023-10-25 14:57:41.000000000","message":"\"the etag is\"","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":864,"context_line":"        if is_conditional_error(self._response_status_int):"},{"line_number":865,"context_line":"            # a conditional response from a modern manifest would have an"},{"line_number":866,"context_line":"            # accurate SLO etag, AND comparison with the etag-is-at header, but"},{"line_number":867,"context_line":"            # for legacy manifests we can\u0027t say what the is or if it matches"},{"line_number":868,"context_line":"            # unless we calculate it from segments - so we need them"},{"line_number":869,"context_line":"            self.segment_listing_needed \u003d slo_attrs.is_legacy"},{"line_number":870,"context_line":"            # if we need them; we can\u0027t get them from the error"}],"source_content_type":"text/x-python","patch_set":31,"id":"ccaddd74_23cf7b8b","line":867,"range":{"start_line":867,"start_character":53,"end_line":867,"end_character":59},"in_reply_to":"4a916b2a_adcc6eea","updated":"2023-10-26 00:15:45.000000000","message":"Done","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":868,"context_line":"            # unless we calculate it from segments - so we need them"},{"line_number":869,"context_line":"            self.segment_listing_needed \u003d slo_attrs.is_legacy"},{"line_number":870,"context_line":"            # if we need them; we can\u0027t get them from the error"},{"line_number":871,"context_line":"            return self.segment_listing_needed"},{"line_number":872,"context_line":""},{"line_number":873,"context_line":"        # This is GET request for an SLO object, if we\u0027re going to return a"},{"line_number":874,"context_line":"        # successful response we\u0027re going to need the segments, but this"}],"source_content_type":"text/x-python","patch_set":31,"id":"d2a34e6d_9ae86061","line":871,"updated":"2023-10-25 14:57:41.000000000","message":"ok, so for legacy, we\u0027ll refetch with an *unconditional* request, calculate the correct etag from segments, put etag that in the response headers, then (critically) delegate to swob.Response to do the matching against the original requests\u0027 conditional headers and possibly morph the response to a 304 or 412. Phew!","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":868,"context_line":"            # unless we calculate it from segments - so we need them"},{"line_number":869,"context_line":"            self.segment_listing_needed \u003d slo_attrs.is_legacy"},{"line_number":870,"context_line":"            # if we need them; we can\u0027t get them from the error"},{"line_number":871,"context_line":"            return self.segment_listing_needed"},{"line_number":872,"context_line":""},{"line_number":873,"context_line":"        # This is GET request for an SLO object, if we\u0027re going to return a"},{"line_number":874,"context_line":"        # successful response we\u0027re going to need the segments, but this"}],"source_content_type":"text/x-python","patch_set":31,"id":"52da7b6b_e6e23a22","line":871,"in_reply_to":"d2a34e6d_9ae86061","updated":"2023-10-26 00:15:45.000000000","message":"haha, oh you got there.  maybe I can keep a little hope.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":885,"context_line":"            # a partial response might included the whole content-range?!"},{"line_number":886,"context_line":"            return not self._is_body_complete()"},{"line_number":887,"context_line":"        else:"},{"line_number":888,"context_line":"            # this is a prefectly normal 200 response, no need to refetch"},{"line_number":889,"context_line":"            # assert self._response_status_int \u003d\u003d 200"},{"line_number":890,"context_line":"            return False"},{"line_number":891,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"95081cb6_4d08d862","line":888,"range":{"start_line":888,"start_character":34,"end_line":888,"end_character":53},"updated":"2023-10-25 14:57:41.000000000","message":"ok, because anything else would have lacked an X-Static-Large-Object header\n\nmaybe add that to the comment?","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":885,"context_line":"            # a partial response might included the whole content-range?!"},{"line_number":886,"context_line":"            return not self._is_body_complete()"},{"line_number":887,"context_line":"        else:"},{"line_number":888,"context_line":"            # this is a prefectly normal 200 response, no need to refetch"},{"line_number":889,"context_line":"            # assert self._response_status_int \u003d\u003d 200"},{"line_number":890,"context_line":"            return False"},{"line_number":891,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"6aa2e1f5_856692c0","line":888,"range":{"start_line":888,"start_character":34,"end_line":888,"end_character":53},"in_reply_to":"95081cb6_4d08d862","updated":"2023-10-26 00:15:45.000000000","message":"well I added a *test* you\u0027d think that be good enough\n\n\tdiff --git a/swift/common/middleware/slo.py b/swift/common/middleware/slo.py\n\tindex 1770d5c1e..101b944d9 100644\n\t--- a/swift/common/middleware/slo.py\n\t+++ b/swift/common/middleware/slo.py\n\t@@ -892,7 +892,7 @@ class SloGetContext(WSGIContext):\n\t\t     # lacking is_slo sys-meta, at this point we\u0027ve filtered all the\n\t\t     # other response codes, so this is a prefectly normal 200 response,\n\t\t     # no need to refetch\n\t-            # assert self._response_status_int \u003d\u003d 200\n\t+            assert self._response_status_int \u003d\u003d 200\n\t\t     return False\n\t \n\t     def _refetch_manifest(self, req, resp_iter, orig_slo_attrs):\n\n\t\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d FAILURES \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\t_______________________________________________________________________ TestSloErrors.test_slo_sysmeta_on_error _______________________________________________________________________\n\n\tself \u003d \u003ctest.unit.common.middleware.test_slo.TestSloErrors testMethod\u003dtest_slo_sysmeta_on_error\u003e\n\n\t    def test_slo_sysmeta_on_error(self):\n\t\theaders \u003d {\n\t\t    \u0027Content-Type\u0027: \u0027application/octet-stream\u0027,\n\t\t    \u0027X-Static-Large-Object\u0027: \u0027true\u0027,\n\t\t    \u0027X-Object-Meta-Animal\u0027: \u0027Pig\u0027,\n\t\t}\n\t\tif self.modern_manifest_headers:\n\t\t    headers.update({\n\t\t\t\u0027X-Object-Sysmeta-Slo-Etag\u0027: \u0027badmeta-etag\u0027,\n\t\t\t\u0027X-Object-Sysmeta-Slo-Size\u0027: \u0027123\u0027,\n\t\t    })\n\t\tself.app.register(\n\t\t    \u0027GET\u0027, \u0027/v1/AUTH_test/gettest/manifest-badmeta\u0027,\n\t\t    swob.HTTPNotFound, headers)\n\t\treq \u003d Request.blank(\u0027/v1/AUTH_test/gettest/manifest-badmeta\u0027)\n\t\u003e       status, headers, body \u003d self.call_slo(req)\n\n\tswift/test/unit/common/middleware/test_slo.py:3572: \n\t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\n\n... the truth is I\u0027m just not happy with this part of the code yet; and the comment is just a band-aid - I rephrase it but I doubt it\u0027ll make anyone less unhappy.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":944,"context_line":"    def _prepare_slo_headers(self, req, slo_attrs):"},{"line_number":945,"context_line":"        \"\"\""},{"line_number":946,"context_line":"        Prepare headers for a SLO response."},{"line_number":947,"context_line":"        :param req: the request"},{"line_number":948,"context_line":"        :param slo_attrs: SloAttrs instance"},{"line_number":949,"context_line":""},{"line_number":950,"context_line":"        :returns: all headers needed for slo response"}],"source_content_type":"text/x-python","patch_set":31,"id":"a807e29a_77f04963","line":947,"range":{"start_line":947,"start_character":8,"end_line":947,"end_character":31},"updated":"2023-10-25 14:57:41.000000000","message":"not used\n\nI can see it is used in the next patch, but this method would actually be great as a method of SloAttrs (SloAttrs.to_headers() ?) and then _return_slo_response could be written\n\n```\ndef _return_slo_response(self, req, start_response, resp_iter, slo_attrs):\n        replace_headers \u003d slo_attrs.to_headers()\n        return self._return_response(req, start_response, resp_iter, replace_headers)\n        ```\n        \nand in the partnum patch:\n\n```\ndef _return_slo_response(self, req, start_response, resp_iter, slo_attrs):\n        replace_headers \u003d slo_attrs.to_headers()\n        replace_headers.update(self._get_partnum_headers(req, slo_attrs))\n        return self._return_response(req, start_response, resp_iter, replace_headers)\n        ```","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96235704ef07bcf9f723add0d0358b7085dd4b06","unresolved":false,"context_lines":[{"line_number":944,"context_line":"    def _prepare_slo_headers(self, req, slo_attrs):"},{"line_number":945,"context_line":"        \"\"\""},{"line_number":946,"context_line":"        Prepare headers for a SLO response."},{"line_number":947,"context_line":"        :param req: the request"},{"line_number":948,"context_line":"        :param slo_attrs: SloAttrs instance"},{"line_number":949,"context_line":""},{"line_number":950,"context_line":"        :returns: all headers needed for slo response"}],"source_content_type":"text/x-python","patch_set":31,"id":"3a5c4228_bcee38dc","line":947,"range":{"start_line":947,"start_character":8,"end_line":947,"end_character":31},"in_reply_to":"73855c61_84419b69","updated":"2023-10-28 01:32:43.000000000","message":"Ack","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":true,"context_lines":[{"line_number":944,"context_line":"    def _prepare_slo_headers(self, req, slo_attrs):"},{"line_number":945,"context_line":"        \"\"\""},{"line_number":946,"context_line":"        Prepare headers for a SLO response."},{"line_number":947,"context_line":"        :param req: the request"},{"line_number":948,"context_line":"        :param slo_attrs: SloAttrs instance"},{"line_number":949,"context_line":""},{"line_number":950,"context_line":"        :returns: all headers needed for slo response"}],"source_content_type":"text/x-python","patch_set":31,"id":"ba0364b2_d2c3dbd1","line":947,"range":{"start_line":947,"start_character":8,"end_line":947,"end_character":31},"in_reply_to":"a807e29a_77f04963","updated":"2023-10-26 00:15:45.000000000","message":"I don\u0027t know why we\u0027d want to split building the resp headers into two methods if we could avoid it - one of the problems before the refactor was we\u0027d update response headers all over half a dozen methods as we go and you couldn\u0027t see the full list of made up headers we\u0027d annotate one which types of responses.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"a0051fd3a9deeb9fed36142532521a009c6d3bd0","unresolved":true,"context_lines":[{"line_number":944,"context_line":"    def _prepare_slo_headers(self, req, slo_attrs):"},{"line_number":945,"context_line":"        \"\"\""},{"line_number":946,"context_line":"        Prepare headers for a SLO response."},{"line_number":947,"context_line":"        :param req: the request"},{"line_number":948,"context_line":"        :param slo_attrs: SloAttrs instance"},{"line_number":949,"context_line":""},{"line_number":950,"context_line":"        :returns: all headers needed for slo response"}],"source_content_type":"text/x-python","patch_set":31,"id":"73855c61_84419b69","line":947,"range":{"start_line":947,"start_character":8,"end_line":947,"end_character":31},"in_reply_to":"ba0364b2_d2c3dbd1","updated":"2023-10-27 02:13:57.000000000","message":"I agree with Clay on this when we split building the slo response headers and have it branch out on all these pre-conditions including conditional_responses, non_slo responses and legacy, non-legacy slo, all those list of pre-condition blocks that would in-line replace headers was the bit that i found out most \"annoying\" about the slo code","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":958,"context_line":"            \u0027Content-Range\u0027: None"},{"line_number":959,"context_line":"        }"},{"line_number":960,"context_line":""},{"line_number":961,"context_line":"        return headers"},{"line_number":962,"context_line":""},{"line_number":963,"context_line":"    def _return_slo_response(self, req, start_response, resp_iter, slo_attrs):"},{"line_number":964,"context_line":"        headers \u003d self._prepare_slo_headers(req, slo_attrs)"}],"source_content_type":"text/x-python","patch_set":31,"id":"f47eac2c_0bca7fdf","line":961,"updated":"2023-10-25 14:57:41.000000000","message":"this would be great as a ``to_headers`` method of SloAttrs","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96235704ef07bcf9f723add0d0358b7085dd4b06","unresolved":false,"context_lines":[{"line_number":958,"context_line":"            \u0027Content-Range\u0027: None"},{"line_number":959,"context_line":"        }"},{"line_number":960,"context_line":""},{"line_number":961,"context_line":"        return headers"},{"line_number":962,"context_line":""},{"line_number":963,"context_line":"    def _return_slo_response(self, req, start_response, resp_iter, slo_attrs):"},{"line_number":964,"context_line":"        headers \u003d self._prepare_slo_headers(req, slo_attrs)"}],"source_content_type":"text/x-python","patch_set":31,"id":"1e53813e_71712ef3","line":961,"in_reply_to":"008a2237_fb043af9","updated":"2023-10-28 01:32:43.000000000","message":"correct.  And I liked the idea until I wrote it - then the swob comment about slo_attrs.slo_size and the extra method for the req-param/part-num-headers made me back out.  #fullack","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d110631b6c6835cee843e209fde32c6bfefab186","unresolved":true,"context_lines":[{"line_number":958,"context_line":"            \u0027Content-Range\u0027: None"},{"line_number":959,"context_line":"        }"},{"line_number":960,"context_line":""},{"line_number":961,"context_line":"        return headers"},{"line_number":962,"context_line":""},{"line_number":963,"context_line":"    def _return_slo_response(self, req, start_response, resp_iter, slo_attrs):"},{"line_number":964,"context_line":"        headers \u003d self._prepare_slo_headers(req, slo_attrs)"}],"source_content_type":"text/x-python","patch_set":31,"id":"008a2237_fb043af9","line":961,"in_reply_to":"ce8f758f_f2ef41bd","updated":"2023-10-27 17:44:25.000000000","message":"As I proposed it, the request wouldn\u0027t be a required argument - it would be a no-arg method asking for a representation of the attrs as a dict of headers.\n\nHowever, ACK your desire to build the headers in one place.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":true,"context_lines":[{"line_number":958,"context_line":"            \u0027Content-Range\u0027: None"},{"line_number":959,"context_line":"        }"},{"line_number":960,"context_line":""},{"line_number":961,"context_line":"        return headers"},{"line_number":962,"context_line":""},{"line_number":963,"context_line":"    def _return_slo_response(self, req, start_response, resp_iter, slo_attrs):"},{"line_number":964,"context_line":"        headers \u003d self._prepare_slo_headers(req, slo_attrs)"}],"source_content_type":"text/x-python","patch_set":31,"id":"ce8f758f_f2ef41bd","line":961,"in_reply_to":"f47eac2c_0bca7fdf","updated":"2023-10-26 00:15:45.000000000","message":"I\u0027m not sure i buy to_headers as a method on SloAttrs; we\u0027re making up the abstractoin boundaries but I think when you get to the point that the request is a required param the method belongs to the request handler; it\u0027s not \"merely\" a property of the [meta]data  of the slo manifest.\n\nComments like \"swob will fix it\" and \"make swob figure it out\" sound way more plausible in SLO where we\u0027re calling \"_return_repsonse(replace_headers\u003dheaders)\"","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":961,"context_line":"        return headers"},{"line_number":962,"context_line":""},{"line_number":963,"context_line":"    def _return_slo_response(self, req, start_response, resp_iter, slo_attrs):"},{"line_number":964,"context_line":"        headers \u003d self._prepare_slo_headers(req, slo_attrs)"},{"line_number":965,"context_line":"        return self._return_response(req, start_response, resp_iter, headers)"},{"line_number":966,"context_line":""},{"line_number":967,"context_line":"    def _return_response(self, req, start_response, resp_iter,"}],"source_content_type":"text/x-python","patch_set":31,"id":"a00a0619_3f614bb4","line":964,"updated":"2023-10-25 14:57:41.000000000","message":"please name this ``replace_headers`` so the naming is consistent through the various _return_*_response methods","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":961,"context_line":"        return headers"},{"line_number":962,"context_line":""},{"line_number":963,"context_line":"    def _return_slo_response(self, req, start_response, resp_iter, slo_attrs):"},{"line_number":964,"context_line":"        headers \u003d self._prepare_slo_headers(req, slo_attrs)"},{"line_number":965,"context_line":"        return self._return_response(req, start_response, resp_iter, headers)"},{"line_number":966,"context_line":""},{"line_number":967,"context_line":"    def _return_response(self, req, start_response, resp_iter,"}],"source_content_type":"text/x-python","patch_set":31,"id":"43caa8ec_cc19fc7e","line":964,"in_reply_to":"a00a0619_3f614bb4","updated":"2023-10-26 00:15:45.000000000","message":"Done","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":966,"context_line":""},{"line_number":967,"context_line":"    def _return_response(self, req, start_response, resp_iter,"},{"line_number":968,"context_line":"                         replace_headers):"},{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"}],"source_content_type":"text/x-python","patch_set":31,"id":"4b1b9c95_b31e22e2","line":969,"updated":"2023-10-25 14:57:41.000000000","message":"ok, so this now gets applied to slo and manifest responses","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"74de58a3ae58aceac9bd7ae9508506e58211d515","unresolved":false,"context_lines":[{"line_number":966,"context_line":""},{"line_number":967,"context_line":"    def _return_response(self, req, start_response, resp_iter,"},{"line_number":968,"context_line":"                         replace_headers):"},{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"}],"source_content_type":"text/x-python","patch_set":31,"id":"f971d23a_1cf3e497","line":969,"in_reply_to":"2d667257_f5da03f0","updated":"2023-11-02 15:55:22.000000000","message":"Ack","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":true,"context_lines":[{"line_number":966,"context_line":""},{"line_number":967,"context_line":"    def _return_response(self, req, start_response, resp_iter,"},{"line_number":968,"context_line":"                         replace_headers):"},{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"}],"source_content_type":"text/x-python","patch_set":31,"id":"2d667257_f5da03f0","line":969,"in_reply_to":"4b1b9c95_b31e22e2","updated":"2023-10-26 00:15:45.000000000","message":"I still can\u0027t find a way to unify _return_response and _return_non_slo_response\n\nsince our slo responses set Content-Length we have to tell swob conditional_response\u003dTrue or else we get the wrong content-length on conditional errors.  I tried popping content-length from replace_headers for conditional_errors but for legacy manifests the refetched response_status is a normal 200; so we have to rely on swob.  Maybe there\u0027s a fix in swob were it always resets content-length on conditional error even if caller sets content-length (N.B. it always truncates the body; so it would make sense)\n\n... I\u0027ll try and remmeber to pull on this a little harder.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":968,"context_line":"                         replace_headers):"},{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"},{"line_number":973,"context_line":"            resp_iter \u003d b\u0027\u0027"},{"line_number":974,"context_line":"        resp_headers \u003d HeaderKeyDict(self._response_headers, **replace_headers)"}],"source_content_type":"text/x-python","patch_set":31,"id":"a734b413_a9be16aa","line":971,"updated":"2023-10-25 14:57:41.000000000","message":"swob won\u0027t, but it\u0027s not clear to me that SLO itself has created a swob.Response for the backend response - so we don\u0027t know the provenance of this resp_iter.\n\nI\u0027m comparing to this comment https://review.opendev.org/c/openstack/swift/+/893578/31/swift/common/swob.py#1398\n\nI *think* this is OK, if it\u0027s true to say that \"whatever middleware gave us this resp_iter, it should be empty if the status is a conditional error\". If the middleware used a swob.Response, like SLO does, then that is true.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"caed97b555062c33e39ca8c6e545607602204090","unresolved":true,"context_lines":[{"line_number":968,"context_line":"                         replace_headers):"},{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"},{"line_number":973,"context_line":"            resp_iter \u003d b\u0027\u0027"},{"line_number":974,"context_line":"        resp_headers \u003d HeaderKeyDict(self._response_headers, **replace_headers)"}],"source_content_type":"text/x-python","patch_set":31,"id":"e396ad81_6a6d15d9","line":971,"in_reply_to":"1991f82a_1e262896","updated":"2023-10-31 11:27:24.000000000","message":"this -\u003e \"merely you don\u0027t understand if it\u0027s justifiable that they\u0027re not consistent\" with the emphasis on *understand*\n\nbut it\u0027s ok, I\u0027m going in circles, thanks for the reminder. 304 should not have body, 412 should have short body, so it\u0027s reasonable to friendly_close them. However, swob.Response cannot assume that about a 200 response that *it* decides is going to be a 304/412.\n\nhttps://datatracker.ietf.org/doc/html/rfc7232#section-4.1\n\"A 304 response cannot contain a message-body; it is always terminated\n   by the first empty line after the header fields.\"\n\nhttps://www.rfc-editor.org/rfc/rfc9110.html#name-client-error-4xx\n\"The 4xx (Client Error) class of status code indicates that the client seems to have erred. Except when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation,\"\n(I can\u0027t find anything more specific about 412 body, but no reason to think the 4xx guidance doesn\u0027t apply)","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96235704ef07bcf9f723add0d0358b7085dd4b06","unresolved":false,"context_lines":[{"line_number":968,"context_line":"                         replace_headers):"},{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"},{"line_number":973,"context_line":"            resp_iter \u003d b\u0027\u0027"},{"line_number":974,"context_line":"        resp_headers \u003d HeaderKeyDict(self._response_headers, **replace_headers)"}],"source_content_type":"text/x-python","patch_set":31,"id":"1991f82a_1e262896","line":971,"in_reply_to":"8f69408d_0d5a8585","updated":"2023-10-28 01:32:43.000000000","message":"well, maybe I\u0027m mis-remembering swob and still need to do some spelunking; but I think in swob\u0027s case *it* decides the 2XX response was is_unmet_condition so IT might have a bunch of body to drain?  In our case we already have the is_unmet_condition status; so at least if our source app used swob to do that - the body was already truncated - by swob - and there\u0027s not much to close.\n\nI\u0027m not sure if you\u0027re advocating this shouldn\u0027t friendly_close; or that swob *should* friendly_close; or that merely you don\u0027t understand if it\u0027s justifiable that they\u0027re not consistent.  I think the way it\u0027s written passes best tests we have for the behaviors we want and has the best chance of not breaking anything we know about - but I wouldn\u0027t assume for a minute that we couldn\u0027t make it even BETTER if we keep trying.  Do you have any specific suggestion?","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":968,"context_line":"                         replace_headers):"},{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"},{"line_number":973,"context_line":"            resp_iter \u003d b\u0027\u0027"},{"line_number":974,"context_line":"        resp_headers \u003d HeaderKeyDict(self._response_headers, **replace_headers)"}],"source_content_type":"text/x-python","patch_set":31,"id":"c14e1f50_40b01b26","line":971,"in_reply_to":"a734b413_a9be16aa","updated":"2023-10-26 00:15:45.000000000","message":"this comment was less about if it\u0027s appropriate or not; and more about \"we\u0027re screwed anyway\"\n\nLike this resp_iter isn\u0027t getting through swob, and since it\u0027s not going to read it we may as well.  The fact we now have a \"safe\" friendly_close that will just drain the *probably* small/empty resp_iter means we don\u0027t have to think TOO hard about all the horrible horrible things middleware to the right MIGHT have done.  Certainly if it\u0027s big enough to run into the drain limit that\u0027s surprising; but nothing much more we can do about that here before we hand off to swob!\n\nI tried to pull it out and we leaked requests in ~24 tests; so I think it\u0027s necessary and suffcient (at least with the current iteration of swob) but maybe it could be better?","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d110631b6c6835cee843e209fde32c6bfefab186","unresolved":true,"context_lines":[{"line_number":968,"context_line":"                         replace_headers):"},{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"},{"line_number":973,"context_line":"            resp_iter \u003d b\u0027\u0027"},{"line_number":974,"context_line":"        resp_headers \u003d HeaderKeyDict(self._response_headers, **replace_headers)"}],"source_content_type":"text/x-python","patch_set":31,"id":"8f69408d_0d5a8585","line":971,"in_reply_to":"c14e1f50_40b01b26","updated":"2023-10-27 17:44:25.000000000","message":"right, but in swob we\u0027re saying it\u0027s *not* reasonable to *read* a conditional response body (just close it) but here we\u0027re reading a conditional response body?","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"a7d8c2fc64eea9e3cf9bd8860f52c8eb050f9bd2","unresolved":true,"context_lines":[{"line_number":968,"context_line":"                         replace_headers):"},{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"},{"line_number":973,"context_line":"            resp_iter \u003d b\u0027\u0027"},{"line_number":974,"context_line":"        resp_headers \u003d HeaderKeyDict(self._response_headers, **replace_headers)"}],"source_content_type":"text/x-python","patch_set":31,"id":"e7295d64_9ef07b25","line":971,"in_reply_to":"e396ad81_6a6d15d9","updated":"2023-11-01 23:33:21.000000000","message":"yeah maybe this comment is mis-leading - i\u0027m blaming swob to justify the behavior instead of just justifying the behavior:\n\n\u003e conditional errors don\u0027t have a body; we can read them\n\nwhere as in swob:\n\n\u003e this resp_iter was from a 200, but we\u0027re returning an unmet_condition; we don\u0027t want to read any of it","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"74de58a3ae58aceac9bd7ae9508506e58211d515","unresolved":false,"context_lines":[{"line_number":968,"context_line":"                         replace_headers):"},{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"},{"line_number":973,"context_line":"            resp_iter \u003d b\u0027\u0027"},{"line_number":974,"context_line":"        resp_headers \u003d HeaderKeyDict(self._response_headers, **replace_headers)"}],"source_content_type":"text/x-python","patch_set":31,"id":"10a3e6e2_501fd7ab","line":971,"in_reply_to":"e7295d64_9ef07b25","updated":"2023-11-02 15:55:22.000000000","message":"i\u0027ve reworded these comments (again); but should have probably just pulled them out.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"},{"line_number":973,"context_line":"            resp_iter \u003d b\u0027\u0027"},{"line_number":974,"context_line":"        resp_headers \u003d HeaderKeyDict(self._response_headers, **replace_headers)"},{"line_number":975,"context_line":"        resp \u003d Response("}],"source_content_type":"text/x-python","patch_set":31,"id":"a5b44efa_d21bf066","line":972,"range":{"start_line":972,"start_character":12,"end_line":972,"end_character":26},"updated":"2023-10-25 14:57:41.000000000","message":"...and swob.Response isn\u0027t going to do this for us i.e. a swob.Response(status\u003d412) is not going to close the resp_iter in the way that a Response(status\u003d200) would close it if it discovered that the status should actually be 412.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":969,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or is_conditional_error("},{"line_number":970,"context_line":"                self._response_status_int):"},{"line_number":971,"context_line":"            # swob won\u0027t let HEAD response or conditional errors have a body"},{"line_number":972,"context_line":"            friendly_close(resp_iter)"},{"line_number":973,"context_line":"            resp_iter \u003d b\u0027\u0027"},{"line_number":974,"context_line":"        resp_headers \u003d HeaderKeyDict(self._response_headers, **replace_headers)"},{"line_number":975,"context_line":"        resp \u003d Response("}],"source_content_type":"text/x-python","patch_set":31,"id":"72d8e958_b532298b","line":972,"range":{"start_line":972,"start_character":12,"end_line":972,"end_character":26},"in_reply_to":"a5b44efa_d21bf066","updated":"2023-10-26 00:15:45.000000000","message":"oh that\u0027s interesting... I think swob\u0027s behavior with conditional responses could be more uniform.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":987,"context_line":"        # now we want out.  But if the original client request included Range"},{"line_number":988,"context_line":"        # or Conditional headers we can trust swob to do the right conversion"},{"line_number":989,"context_line":"        # back into a 206/416/304/412 (as long as the response we have is a"},{"line_number":990,"context_line":"        # normal successful response and we respect any forwarding middleware\u0027s"},{"line_number":991,"context_line":"        # etag-is-at header that we stripped off for the refetch!)"},{"line_number":992,"context_line":"        resp \u003d Response("},{"line_number":993,"context_line":"            status\u003dself._response_status,"}],"source_content_type":"text/x-python","patch_set":31,"id":"40ee2354_00a35c2b","line":990,"range":{"start_line":990,"start_character":10,"end_line":990,"end_character":36},"updated":"2023-10-25 14:57:41.000000000","message":"is this true? meaning, swob.Response appears to call ``empty_resp \u003d self._get_conditional_response_status()`` whatever the status.\n\nOf course, if we don\u0027t have a 200 we\u0027re unlikely to have the etag needed to actually do conditional matches - is that what this comment means?","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":true,"context_lines":[{"line_number":987,"context_line":"        # now we want out.  But if the original client request included Range"},{"line_number":988,"context_line":"        # or Conditional headers we can trust swob to do the right conversion"},{"line_number":989,"context_line":"        # back into a 206/416/304/412 (as long as the response we have is a"},{"line_number":990,"context_line":"        # normal successful response and we respect any forwarding middleware\u0027s"},{"line_number":991,"context_line":"        # etag-is-at header that we stripped off for the refetch!)"},{"line_number":992,"context_line":"        resp \u003d Response("},{"line_number":993,"context_line":"            status\u003dself._response_status,"}],"source_content_type":"text/x-python","patch_set":31,"id":"af7392a5_8fc83738","line":990,"range":{"start_line":990,"start_character":10,"end_line":990,"end_character":36},"in_reply_to":"40ee2354_00a35c2b","updated":"2023-10-26 00:15:45.000000000","message":"I think this comment is ment to justify the values we pass to swob for the conditional_repsonse and conditional_etag arguments more than make any claims about the correctness or consistency of swob - this is just my best understanding of why these arguments make all the test cases assertions on the behaviors we want pass.\n\nif there\u0027s another scenario where these arguments to swob are WRONG - I want to know about it!\n\nif my lack of understanding of swob\u0027s internals makes this comment do more harm than good we should remove it.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"caed97b555062c33e39ca8c6e545607602204090","unresolved":false,"context_lines":[{"line_number":987,"context_line":"        # now we want out.  But if the original client request included Range"},{"line_number":988,"context_line":"        # or Conditional headers we can trust swob to do the right conversion"},{"line_number":989,"context_line":"        # back into a 206/416/304/412 (as long as the response we have is a"},{"line_number":990,"context_line":"        # normal successful response and we respect any forwarding middleware\u0027s"},{"line_number":991,"context_line":"        # etag-is-at header that we stripped off for the refetch!)"},{"line_number":992,"context_line":"        resp \u003d Response("},{"line_number":993,"context_line":"            status\u003dself._response_status,"}],"source_content_type":"text/x-python","patch_set":31,"id":"aef696d9_6e7b699c","line":990,"range":{"start_line":990,"start_character":10,"end_line":990,"end_character":36},"in_reply_to":"81f16a8a_ccf345d1","updated":"2023-10-31 11:27:24.000000000","message":"my \"refusal\" to offer counter-prose had more to do with it being 6.45pm on a Friday than any kind of rebellion","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d110631b6c6835cee843e209fde32c6bfefab186","unresolved":true,"context_lines":[{"line_number":987,"context_line":"        # now we want out.  But if the original client request included Range"},{"line_number":988,"context_line":"        # or Conditional headers we can trust swob to do the right conversion"},{"line_number":989,"context_line":"        # back into a 206/416/304/412 (as long as the response we have is a"},{"line_number":990,"context_line":"        # normal successful response and we respect any forwarding middleware\u0027s"},{"line_number":991,"context_line":"        # etag-is-at header that we stripped off for the refetch!)"},{"line_number":992,"context_line":"        resp \u003d Response("},{"line_number":993,"context_line":"            status\u003dself._response_status,"}],"source_content_type":"text/x-python","patch_set":31,"id":"bb769d38_1f0cfe17","line":990,"range":{"start_line":990,"start_character":10,"end_line":990,"end_character":36},"in_reply_to":"af7392a5_8fc83738","updated":"2023-10-27 17:44:25.000000000","message":"maybe gerrit isn\u0027t making it clear that my query was only of the \"normal successful response\" part\n\nAFAICT swob.Response will do the conversion for any response status.\n\nOh, wait, I\u0027m reading it differently now - \"it\u0027s OK for us to delegate this to swob as long as the response we have is a normal successful response\" rather than \"swob will do this as long as the response we have is a normal successful response\"\n\nNothing to see, move on.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96235704ef07bcf9f723add0d0358b7085dd4b06","unresolved":false,"context_lines":[{"line_number":987,"context_line":"        # now we want out.  But if the original client request included Range"},{"line_number":988,"context_line":"        # or Conditional headers we can trust swob to do the right conversion"},{"line_number":989,"context_line":"        # back into a 206/416/304/412 (as long as the response we have is a"},{"line_number":990,"context_line":"        # normal successful response and we respect any forwarding middleware\u0027s"},{"line_number":991,"context_line":"        # etag-is-at header that we stripped off for the refetch!)"},{"line_number":992,"context_line":"        resp \u003d Response("},{"line_number":993,"context_line":"            status\u003dself._response_status,"}],"source_content_type":"text/x-python","patch_set":31,"id":"81f16a8a_ccf345d1","line":990,"range":{"start_line":990,"start_character":10,"end_line":990,"end_character":36},"in_reply_to":"bb769d38_1f0cfe17","updated":"2023-10-28 01:32:43.000000000","message":"well maybe, again admiting that comments are a weakness I at least now understand better HOW you misinterpreted what I was trying to convey - not how to make what I was trying to convey more obvious.  😭\n\nmaybe your refrusal to offer counter prose is some sort of enlightened rebellion against my failed crusade to offer a refactor with \"well commented\" code.  I\u0027ll try again; but you should probably stop me at some point.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b7087e06b7d9a9377faee177f6472141f9fd8076","unresolved":true,"context_lines":[{"line_number":1046,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1047,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"},{"line_number":1048,"context_line":"                # frist segment on HEAD"},{"line_number":1049,"context_line":"                resp_iter \u003d self._build_resp_iter(req, segments, slo_attrs)"},{"line_number":1050,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1051,"context_line":"                                         slo_attrs)"},{"line_number":1052,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"fc97a139_3204be50","line":1049,"updated":"2023-10-25 17:04:35.000000000","message":"slo_attrs now has a ref to segments so there\u0027s no longer any need to pass segments as a separate arg","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":1046,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1047,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"},{"line_number":1048,"context_line":"                # frist segment on HEAD"},{"line_number":1049,"context_line":"                resp_iter \u003d self._build_resp_iter(req, segments, slo_attrs)"},{"line_number":1050,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1051,"context_line":"                                         slo_attrs)"},{"line_number":1052,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"442505fc_c604fce7","line":1049,"in_reply_to":"fc97a139_3204be50","updated":"2023-10-26 00:15:45.000000000","message":"Done","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b7087e06b7d9a9377faee177f6472141f9fd8076","unresolved":true,"context_lines":[{"line_number":1109,"context_line":"        ver, account, _junk \u003d req.split_path(3, 3, rest_with_last\u003dTrue)"},{"line_number":1110,"context_line":"        account \u003d wsgi_to_str(account)"},{"line_number":1111,"context_line":"        plain_listing_iter \u003d self._segment_listing_iterator("},{"line_number":1112,"context_line":"            req, ver, account, segments, byteranges)"},{"line_number":1113,"context_line":""},{"line_number":1114,"context_line":"        def ratelimit_predicate(seg_dict):"},{"line_number":1115,"context_line":"            if \u0027raw_data\u0027 in seg_dict:"}],"source_content_type":"text/x-python","patch_set":31,"id":"a9f616b1_4ebf6953","line":1112,"range":{"start_line":1112,"start_character":31,"end_line":1112,"end_character":39},"updated":"2023-10-25 17:04:35.000000000","message":"slo_attrs.segments","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":1109,"context_line":"        ver, account, _junk \u003d req.split_path(3, 3, rest_with_last\u003dTrue)"},{"line_number":1110,"context_line":"        account \u003d wsgi_to_str(account)"},{"line_number":1111,"context_line":"        plain_listing_iter \u003d self._segment_listing_iterator("},{"line_number":1112,"context_line":"            req, ver, account, segments, byteranges)"},{"line_number":1113,"context_line":""},{"line_number":1114,"context_line":"        def ratelimit_predicate(seg_dict):"},{"line_number":1115,"context_line":"            if \u0027raw_data\u0027 in seg_dict:"}],"source_content_type":"text/x-python","patch_set":31,"id":"b11c8b53_df5a34d7","line":1112,"range":{"start_line":1112,"start_character":31,"end_line":1112,"end_character":39},"in_reply_to":"a9f616b1_4ebf6953","updated":"2023-10-26 00:15:45.000000000","message":"Done","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d110631b6c6835cee843e209fde32c6bfefab186","unresolved":true,"context_lines":[{"line_number":581,"context_line":"        # in practice self.segments will be None until someone calls"},{"line_number":582,"context_line":"        # update_from_segments with a list of seg_dicts"},{"line_number":583,"context_line":"        self.segments \u003d segments"},{"line_number":584,"context_line":"        if self.segments is not None:"},{"line_number":585,"context_line":"            self.update_from_segments(self.segments)"},{"line_number":586,"context_line":""},{"line_number":587,"context_line":"    def _has_size_and_etag(self):"}],"source_content_type":"text/x-python","patch_set":33,"id":"17d5e7e9_370131d5","line":584,"updated":"2023-10-27 17:44:25.000000000","message":"nit: this seems to be at odds with the comment line 581 - we haven\u0027t called update_from_segments...so segments will be None. If segments is never passed to the constructor then does the constructor need to accept it as an arg?","commit_id":"8e316933e76147981b765c981e31f42592e1201c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96235704ef07bcf9f723add0d0358b7085dd4b06","unresolved":false,"context_lines":[{"line_number":581,"context_line":"        # in practice self.segments will be None until someone calls"},{"line_number":582,"context_line":"        # update_from_segments with a list of seg_dicts"},{"line_number":583,"context_line":"        self.segments \u003d segments"},{"line_number":584,"context_line":"        if self.segments is not None:"},{"line_number":585,"context_line":"            self.update_from_segments(self.segments)"},{"line_number":586,"context_line":""},{"line_number":587,"context_line":"    def _has_size_and_etag(self):"}],"source_content_type":"text/x-python","patch_set":33,"id":"2184263d_9394647f","line":584,"in_reply_to":"17d5e7e9_370131d5","updated":"2023-10-28 01:32:43.000000000","message":"I considered and rejected (as weird from OOP design) all of the following;\n\n1) only create the .segments attribute in update_from_segments\n2) always initilize self.segments \u003d None in the constructor with no way to override in with kwargs to `__init__`\n3) allow you to optionaly set self.segments; but don\u0027t call update_from_segments in-case it\u0027s None\n\nSo I compromised with the above, write some interface that follows principle of least surprise - but maybe isn\u0027t that useful in practice, which I admit in the comment.  But having selected that option I migth have either ditched the comment (my lack of conviction may be what you\u0027re reacting to more than the code itself) and/or exercised the interface at least in tests to justify having written it.\n\nIt sounds like you may have compromised on #2 - which is justifiable!  I\u0027m a fan of YAGNI, but over half of our daemons/servers accept `self.logger \u003d logger or get_logger()` because after you live with an object for awhile you re-discover it\u0027s useful if they accept their attributes as args to `__init__`!  (DiskFile.ext comes to mind as another recent example)\n\nI\u0027ll pull it out and hope I never get to say I told you so ;)","commit_id":"8e316933e76147981b765c981e31f42592e1201c"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":false,"context_lines":[{"line_number":608,"context_line":"        for seg_dict in segments:"},{"line_number":609,"context_line":"            if config_true_value(seg_dict.get(\u0027sub_slo\u0027)):"},{"line_number":610,"context_line":"                override_bytes_from_content_type(seg_dict,"},{"line_number":611,"context_line":"                                                 logger\u003dself.slo.logger)"},{"line_number":612,"context_line":""},{"line_number":613,"context_line":"        # We handle the range stuff here so that we can be smart about"},{"line_number":614,"context_line":"        # skipping unused submanifests. For example, if our first segment is a"}],"source_content_type":"text/x-python","patch_set":41,"id":"80b4ada0_ceb6c9be","side":"PARENT","line":611,"updated":"2023-11-03 18:50:26.000000000","message":"OK, pulled out to `_annotate_segments`","commit_id":"3dab88bdf83eba339cd1a2d391b9e421ff2c5cf0"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","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":41,"id":"04c77caa_308ca192","side":"PARENT","line":622,"updated":"2023-11-03 18:50:26.000000000","message":"Pulled out to `_build_resp_iter`","commit_id":"3dab88bdf83eba339cd1a2d391b9e421ff2c5cf0"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":651,"context_line":"            if \u0027data\u0027 in seg_dict:"},{"line_number":652,"context_line":"                seg_dict[\u0027raw_data\u0027] \u003d strict_b64decode(seg_dict.pop(\u0027data\u0027))"},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"            seg_length \u003d self._segment_length(seg_dict)"},{"line_number":655,"context_line":"            if first_byte \u003e\u003d seg_length:"},{"line_number":656,"context_line":"                # don\u0027t need any bytes from this segment"},{"line_number":657,"context_line":"                first_byte -\u003d seg_length"}],"source_content_type":"text/x-python","patch_set":41,"id":"97e48018_f219003e","side":"PARENT","line":654,"updated":"2023-11-03 18:50:26.000000000","message":"Right, so this is now handled in `_annotate_segments`, which we\u0027ll call in `_parse_segments` either when `self.segment_listing_needed` or right before returning from ` _fetch_sub_slo_segments`","commit_id":"3dab88bdf83eba339cd1a2d391b9e421ff2c5cf0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":651,"context_line":"            if \u0027data\u0027 in seg_dict:"},{"line_number":652,"context_line":"                seg_dict[\u0027raw_data\u0027] \u003d strict_b64decode(seg_dict.pop(\u0027data\u0027))"},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"            seg_length \u003d self._segment_length(seg_dict)"},{"line_number":655,"context_line":"            if first_byte \u003e\u003d seg_length:"},{"line_number":656,"context_line":"                # don\u0027t need any bytes from this segment"},{"line_number":657,"context_line":"                first_byte -\u003d seg_length"}],"source_content_type":"text/x-python","patch_set":41,"id":"17caff06_ae81f920","side":"PARENT","line":654,"in_reply_to":"97e48018_f219003e","updated":"2023-11-04 00:34:58.000000000","message":"Ack","commit_id":"3dab88bdf83eba339cd1a2d391b9e421ff2c5cf0"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":48,"context_line":"Or:"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":51,"context_line":"Key         Description"},{"line_number":52,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":53,"context_line":"data        base64-encoded data to be returned"},{"line_number":54,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-python","patch_set":41,"id":"844b2242_7bc7df47","line":51,"updated":"2023-11-03 18:50:26.000000000","message":"If we\u0027re getting rid of one set of table headers, we should get rid of the other one, too. Though I\u0027m not sure *why* we don\u0027t want it...","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":48,"context_line":"Or:"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":51,"context_line":"Key         Description"},{"line_number":52,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":53,"context_line":"data        base64-encoded data to be returned"},{"line_number":54,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-python","patch_set":41,"id":"8669fd26_5ff3a582","line":51,"in_reply_to":"844b2242_7bc7df47","updated":"2023-11-04 00:34:58.000000000","message":"I have no idea where that crept in or how it effects rendering.\n\nnice catch!  I\u0027ll pull it out.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":532,"context_line":""},{"line_number":533,"context_line":"def _annotate_segments(segments, logger\u003dNone):"},{"line_number":534,"context_line":"    \"\"\""},{"line_number":535,"context_line":"    Decode any inlined data and update sub_slo bytes from content-length;"},{"line_number":536,"context_line":"    then annotate segment dicts in segments list with \u0027segment_length\u0027"},{"line_number":537,"context_line":"    (raw_data and range segments don\u0027t have a bytes key, and sub_slo"},{"line_number":538,"context_line":"    segments will have their bytes updated from content-type, but"}],"source_content_type":"text/x-python","patch_set":41,"id":"fbad06f0_578b5579","line":535,"range":{"start_line":535,"start_character":58,"end_line":535,"end_character":72},"updated":"2023-11-03 18:50:26.000000000","message":"`content-type`, yeah?","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":532,"context_line":""},{"line_number":533,"context_line":"def _annotate_segments(segments, logger\u003dNone):"},{"line_number":534,"context_line":"    \"\"\""},{"line_number":535,"context_line":"    Decode any inlined data and update sub_slo bytes from content-length;"},{"line_number":536,"context_line":"    then annotate segment dicts in segments list with \u0027segment_length\u0027"},{"line_number":537,"context_line":"    (raw_data and range segments don\u0027t have a bytes key, and sub_slo"},{"line_number":538,"context_line":"    segments will have their bytes updated from content-type, but"}],"source_content_type":"text/x-python","patch_set":41,"id":"03e1f4c1_2539d17f","line":535,"range":{"start_line":535,"start_character":58,"end_line":535,"end_character":72},"in_reply_to":"fbad06f0_578b5579","updated":"2023-11-04 00:34:58.000000000","message":":nod: #willfix","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":534,"context_line":"    \"\"\""},{"line_number":535,"context_line":"    Decode any inlined data and update sub_slo bytes from content-length;"},{"line_number":536,"context_line":"    then annotate segment dicts in segments list with \u0027segment_length\u0027"},{"line_number":537,"context_line":"    (raw_data and range segments don\u0027t have a bytes key, and sub_slo"},{"line_number":538,"context_line":"    segments will have their bytes updated from content-type, but"},{"line_number":539,"context_line":"    afterwards all segments will have segment_length)."},{"line_number":540,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":41,"id":"99eeaca8_94cd5968","line":537,"range":{"start_line":537,"start_character":18,"end_line":537,"end_character":55},"updated":"2023-11-03 18:50:26.000000000","message":"You sure about that?\n```\n$ curl http://saio:8090/v1/AUTH_test/c/o?multipart-manifest\u003dput -X PUT -d \u0027[{\"path\":\"c/o2\", \"range\":\"-5\"}]\u0027 -i\nHTTP/1.1 201 Created\nContent-Type: text/html; charset\u003dUTF-8\nContent-Length: 0\nEtag: \"e89ba3fa3fc34ea3198ecc62b659fe63\"\nLast-Modified: Fri, 03 Nov 2023 17:30:12 GMT\nX-Trans-Id: tx30f68586a2644e4187cd7-0065452e23\nX-Openstack-Request-Id: tx30f68586a2644e4187cd7-0065452e23\nDate: Fri, 03 Nov 2023 17:30:11 GMT\n\n$ curl -s http://saio:8090/v1/AUTH_test/c/o?multipart-manifest\u003dget | python -m json.tool\n[\n    {\n        \"name\": \"/c/o2\",\n        \"bytes\": 524288000,\n        \"hash\": \"f65d935da53561ea662f6f3b233949e9\",\n        \"content_type\": \"application/octet-stream\",\n        \"last_modified\": \"2023-11-01T20:10:01.000000\",\n        \"range\": \"524287995-524287999\",\n        \"sub_slo\": true\n    }\n]\n```","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":534,"context_line":"    \"\"\""},{"line_number":535,"context_line":"    Decode any inlined data and update sub_slo bytes from content-length;"},{"line_number":536,"context_line":"    then annotate segment dicts in segments list with \u0027segment_length\u0027"},{"line_number":537,"context_line":"    (raw_data and range segments don\u0027t have a bytes key, and sub_slo"},{"line_number":538,"context_line":"    segments will have their bytes updated from content-type, but"},{"line_number":539,"context_line":"    afterwards all segments will have segment_length)."},{"line_number":540,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":41,"id":"b734737b_1606336c","line":537,"range":{"start_line":537,"start_character":18,"end_line":537,"end_character":55},"in_reply_to":"99eeaca8_94cd5968","updated":"2023-11-04 00:34:58.000000000","message":"yikes, probably had *some* justification when I wrote it, but I may have just been reading tests... obvs the segment_length isn\u0027t calculated from bytes on range-segments but the comment is misleading as written.  #willfix","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":535,"context_line":"    Decode any inlined data and update sub_slo bytes from content-length;"},{"line_number":536,"context_line":"    then annotate segment dicts in segments list with \u0027segment_length\u0027"},{"line_number":537,"context_line":"    (raw_data and range segments don\u0027t have a bytes key, and sub_slo"},{"line_number":538,"context_line":"    segments will have their bytes updated from content-type, but"},{"line_number":539,"context_line":"    afterwards all segments will have segment_length)."},{"line_number":540,"context_line":"    \"\"\""},{"line_number":541,"context_line":"    for seg_dict in segments:"}],"source_content_type":"text/x-python","patch_set":41,"id":"a4f4947b_21e9f686","line":538,"range":{"start_line":538,"start_character":13,"end_line":538,"end_character":17},"updated":"2023-11-03 18:50:26.000000000","message":"\"may\"","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":true,"context_lines":[{"line_number":535,"context_line":"    Decode any inlined data and update sub_slo bytes from content-length;"},{"line_number":536,"context_line":"    then annotate segment dicts in segments list with \u0027segment_length\u0027"},{"line_number":537,"context_line":"    (raw_data and range segments don\u0027t have a bytes key, and sub_slo"},{"line_number":538,"context_line":"    segments will have their bytes updated from content-type, but"},{"line_number":539,"context_line":"    afterwards all segments will have segment_length)."},{"line_number":540,"context_line":"    \"\"\""},{"line_number":541,"context_line":"    for seg_dict in segments:"}],"source_content_type":"text/x-python","patch_set":41,"id":"dfe270f0_bebf535c","line":538,"range":{"start_line":538,"start_character":13,"end_line":538,"end_character":17},"in_reply_to":"a4f4947b_21e9f686","updated":"2023-11-04 00:34:58.000000000","message":"hrmm.... right... so then maybe the old busted sub_slo-segments that have no representation in the manifest of their length neither in bytes nor content-type may not have a correct segment_length.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":false,"context_lines":[{"line_number":535,"context_line":"    Decode any inlined data and update sub_slo bytes from content-length;"},{"line_number":536,"context_line":"    then annotate segment dicts in segments list with \u0027segment_length\u0027"},{"line_number":537,"context_line":"    (raw_data and range segments don\u0027t have a bytes key, and sub_slo"},{"line_number":538,"context_line":"    segments will have their bytes updated from content-type, but"},{"line_number":539,"context_line":"    afterwards all segments will have segment_length)."},{"line_number":540,"context_line":"    \"\"\""},{"line_number":541,"context_line":"    for seg_dict in segments:"}],"source_content_type":"text/x-python","patch_set":41,"id":"d833bd50_d61b7e7f","line":538,"range":{"start_line":538,"start_character":13,"end_line":538,"end_character":17},"in_reply_to":"d929f87f_052990fe","updated":"2023-11-09 23:25:02.000000000","message":"current docstring looks better!","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":true,"context_lines":[{"line_number":535,"context_line":"    Decode any inlined data and update sub_slo bytes from content-length;"},{"line_number":536,"context_line":"    then annotate segment dicts in segments list with \u0027segment_length\u0027"},{"line_number":537,"context_line":"    (raw_data and range segments don\u0027t have a bytes key, and sub_slo"},{"line_number":538,"context_line":"    segments will have their bytes updated from content-type, but"},{"line_number":539,"context_line":"    afterwards all segments will have segment_length)."},{"line_number":540,"context_line":"    \"\"\""},{"line_number":541,"context_line":"    for seg_dict in segments:"}],"source_content_type":"text/x-python","patch_set":41,"id":"d929f87f_052990fe","line":538,"range":{"start_line":538,"start_character":13,"end_line":538,"end_character":17},"in_reply_to":"dfe270f0_bebf535c","updated":"2023-11-07 19:40:36.000000000","message":"My read on the history was that *either* `bytes` is accurate about the length and `content_type` has no `swift_bytes`, *or* `bytes` is referring to the manifest length but it\u0027s OK because `content_type` has the right value in `swift_bytes`. We should **always** have an accurate length *somewhere*.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":544,"context_line":"            segment_length \u003d len(seg_dict[\u0027raw_data\u0027])"},{"line_number":545,"context_line":"        else:"},{"line_number":546,"context_line":"            if config_true_value(seg_dict.get(\u0027sub_slo\u0027)):"},{"line_number":547,"context_line":"                override_bytes_from_content_type("},{"line_number":548,"context_line":"                    seg_dict, logger\u003dlogger)"},{"line_number":549,"context_line":"            seg_range \u003d seg_dict.get(\u0027range\u0027)"},{"line_number":550,"context_line":"            if seg_range is not None:"}],"source_content_type":"text/x-python","patch_set":41,"id":"4472af2e_f0d855c4","line":547,"range":{"start_line":547,"start_character":16,"end_line":547,"end_character":48},"updated":"2023-11-03 18:50:26.000000000","message":"Off-topic: it\u0027s a miracle this even works -- what was that you were saying the other day about polymorphism? Segment dict, container listing dict, w/e...","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":544,"context_line":"            segment_length \u003d len(seg_dict[\u0027raw_data\u0027])"},{"line_number":545,"context_line":"        else:"},{"line_number":546,"context_line":"            if config_true_value(seg_dict.get(\u0027sub_slo\u0027)):"},{"line_number":547,"context_line":"                override_bytes_from_content_type("},{"line_number":548,"context_line":"                    seg_dict, logger\u003dlogger)"},{"line_number":549,"context_line":"            seg_range \u003d seg_dict.get(\u0027range\u0027)"},{"line_number":550,"context_line":"            if seg_range is not None:"}],"source_content_type":"text/x-python","patch_set":41,"id":"9084baa1_b8d52bfc","line":547,"range":{"start_line":547,"start_character":16,"end_line":547,"end_character":48},"in_reply_to":"4472af2e_f0d855c4","updated":"2023-11-04 00:34:58.000000000","message":"heh, maybe the abstraction is kind of weird - it expects a dict with a \u0027content_type\u0027 it\u0027s going to write the calculated result in \u0027bytes\u0027\n\n\tdef override_bytes_from_content_type(listing_dict, logger\u003dNone):\n\t    \"\"\"\n\t    Takes a dict from a container listing and overrides the content_type,\n\t    bytes fields if swift_bytes is set.\n\t    \"\"\"\n\t    listing_dict[\u0027content_type\u0027], swift_bytes \u003d extract_swift_bytes(\n\t\tlisting_dict[\u0027content_type\u0027])\n\t    if swift_bytes is not None:\n\t\ttry:\n\t\t    listing_dict[\u0027bytes\u0027] \u003d int(swift_bytes)\n\t\texcept ValueError:\n\t\t    if logger:\n\t\t\tlogger.exception(\"Invalid swift_bytes\")","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":571,"context_line":"            # even though it\u0027s from sysmeta, we have to worry about empty"},{"line_number":572,"context_line":"            # values - see test_get_invalid_sysmeta_passthrough"},{"line_number":573,"context_line":"            self.slo_size \u003d int(slo_size)"},{"line_number":574,"context_line":"        except (ValueError, TypeError):"},{"line_number":575,"context_line":"            self.slo_size \u003d -1"},{"line_number":576,"context_line":"        self.is_legacy \u003d not self._has_size_and_etag()"},{"line_number":577,"context_line":"        self.segments \u003d None"}],"source_content_type":"text/x-python","patch_set":41,"id":"703df7c0_ab357610","line":574,"updated":"2023-11-03 18:50:26.000000000","message":"OK, so `TypeError` if it wasn\u0027t set (and so came in as `None`), and `ValueError` if it *was* set but blank. I vaguely wonder if it would be better to deal with it in `from_headers`, like\n```\n            elif header \u003d\u003d SYSMETA_SLO_SIZE:\n                slo_size \u003d value or None\n                if slo_size:\n                    slo_size \u003d int(slo_size)\n```\nand use `None` as our sentinel instead of `-1`","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":571,"context_line":"            # even though it\u0027s from sysmeta, we have to worry about empty"},{"line_number":572,"context_line":"            # values - see test_get_invalid_sysmeta_passthrough"},{"line_number":573,"context_line":"            self.slo_size \u003d int(slo_size)"},{"line_number":574,"context_line":"        except (ValueError, TypeError):"},{"line_number":575,"context_line":"            self.slo_size \u003d -1"},{"line_number":576,"context_line":"        self.is_legacy \u003d not self._has_size_and_etag()"},{"line_number":577,"context_line":"        self.segments \u003d None"}],"source_content_type":"text/x-python","patch_set":41,"id":"5f22ae85_8fe74585","line":574,"in_reply_to":"703df7c0_ab357610","updated":"2023-11-04 00:34:58.000000000","message":"since the type of the value when correct is an int I *think* I do prefer -1 to None as the sentinal; it\u0027s sufficiently \"not a valid length in bytes\" that hopefully callers can deal with it?\n\nWe could make the header parsing validation stronger but I\u0027m not sure it would be sufficient justification to make the validation in this context weaker?  I think the exception list was less about tayloring to specific values that might get pass in and more just recognizing the kinds of errors that int() can throw?  ValueError for \u0027foo\u0027 or TypeError for True - doesn\u0027t matter.\n\nMaybe worth consiering if we\u0027re happy with the behavior when someone calls it with slo_size\u003d\u002710.5\u0027?  Can you have half-a-byte?  Is round up reasonable?","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":true,"context_lines":[{"line_number":588,"context_line":"        :returns: an instance of SloAttrs to represent the response headers"},{"line_number":589,"context_line":"        \"\"\""},{"line_number":590,"context_line":"        is_slo \u003d False"},{"line_number":591,"context_line":"        timestamp \u003d 0"},{"line_number":592,"context_line":"        found_etag \u003d None"},{"line_number":593,"context_line":"        slo_etag \u003d None"},{"line_number":594,"context_line":"        slo_size \u003d None"}],"source_content_type":"text/x-python","patch_set":41,"id":"52150fbc_7e8ccb65","line":591,"updated":"2023-11-04 00:34:58.000000000","message":"now that you mention it, THIS is the one that stands out to me  #willfix","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"99258dd4f80f30281f9c6acc12d4fd0f86e9eb7f","unresolved":false,"context_lines":[{"line_number":588,"context_line":"        :returns: an instance of SloAttrs to represent the response headers"},{"line_number":589,"context_line":"        \"\"\""},{"line_number":590,"context_line":"        is_slo \u003d False"},{"line_number":591,"context_line":"        timestamp \u003d 0"},{"line_number":592,"context_line":"        found_etag \u003d None"},{"line_number":593,"context_line":"        slo_etag \u003d None"},{"line_number":594,"context_line":"        slo_size \u003d None"}],"source_content_type":"text/x-python","patch_set":41,"id":"b6422b74_ac727411","line":591,"in_reply_to":"52150fbc_7e8ccb65","updated":"2023-11-06 17:31:39.000000000","message":"Done","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":591,"context_line":"        timestamp \u003d 0"},{"line_number":592,"context_line":"        found_etag \u003d None"},{"line_number":593,"context_line":"        slo_etag \u003d None"},{"line_number":594,"context_line":"        slo_size \u003d None"},{"line_number":595,"context_line":"        for header, value in response_headers:"},{"line_number":596,"context_line":"            header \u003d header.lower()"},{"line_number":597,"context_line":"            if header \u003d\u003d \u0027x-static-large-object\u0027:"}],"source_content_type":"text/x-python","patch_set":41,"id":"c5dbd8b2_9a49f1b0","line":594,"updated":"2023-11-03 18:50:26.000000000","message":"If we stick with the `-1` sentinel, would it be better to have the default here be `-1`? Or maybe even `\u0027-1\u0027`?","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":591,"context_line":"        timestamp \u003d 0"},{"line_number":592,"context_line":"        found_etag \u003d None"},{"line_number":593,"context_line":"        slo_etag \u003d None"},{"line_number":594,"context_line":"        slo_size \u003d None"},{"line_number":595,"context_line":"        for header, value in response_headers:"},{"line_number":596,"context_line":"            header \u003d header.lower()"},{"line_number":597,"context_line":"            if header \u003d\u003d \u0027x-static-large-object\u0027:"}],"source_content_type":"text/x-python","patch_set":41,"id":"724437c4_af0fc828","line":594,"in_reply_to":"c5dbd8b2_9a49f1b0","updated":"2023-11-04 00:34:58.000000000","message":"I think in this context None is unambigous for a value we did not find; SloAttrs doesn\u0027t care what you pass it - tests say types will always be correct.  see TestSloAttrs.test_default_types","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":604,"context_line":"                slo_etag \u003d value"},{"line_number":605,"context_line":"            elif header \u003d\u003d SYSMETA_SLO_SIZE:"},{"line_number":606,"context_line":"                slo_size \u003d value"},{"line_number":607,"context_line":"        manifest_etag \u003d found_etag if is_slo else None"},{"line_number":608,"context_line":"        return cls(is_slo, timestamp, manifest_etag, slo_etag, slo_size)"},{"line_number":609,"context_line":""},{"line_number":610,"context_line":"    def update_from_segments(self, segments):"}],"source_content_type":"text/x-python","patch_set":41,"id":"a44f8bf9_125bd257","line":607,"updated":"2023-11-03 18:50:26.000000000","message":"It\u0027s a little funny to me that this is the only place in this class where we look at `is_slo`\n\nI\u0027m not trying to say we should raise some kind of error in `update_from_segments` if `not self.is_slo` (though that _would_ be some nonsense) -- but I find it ... curious.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":604,"context_line":"                slo_etag \u003d value"},{"line_number":605,"context_line":"            elif header \u003d\u003d SYSMETA_SLO_SIZE:"},{"line_number":606,"context_line":"                slo_size \u003d value"},{"line_number":607,"context_line":"        manifest_etag \u003d found_etag if is_slo else None"},{"line_number":608,"context_line":"        return cls(is_slo, timestamp, manifest_etag, slo_etag, slo_size)"},{"line_number":609,"context_line":""},{"line_number":610,"context_line":"    def update_from_segments(self, segments):"}],"source_content_type":"text/x-python","patch_set":41,"id":"b153c633_da9e6a00","line":607,"in_reply_to":"a44f8bf9_125bd257","updated":"2023-11-04 00:34:58.000000000","message":"I wonder why you find it curious?  is_slo is the main part of the public interface - it\u0027s more for callers than for us.\n\nI agree it would be strange to raise an error in update_from_segments if not self.is_slo - we can\u0027t assume someone wanting to use the class in a use-case we didn\u0027t imagine today is obviously a bug - if it works; it\u0027s a duck!","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":false,"context_lines":[{"line_number":604,"context_line":"                slo_etag \u003d value"},{"line_number":605,"context_line":"            elif header \u003d\u003d SYSMETA_SLO_SIZE:"},{"line_number":606,"context_line":"                slo_size \u003d value"},{"line_number":607,"context_line":"        manifest_etag \u003d found_etag if is_slo else None"},{"line_number":608,"context_line":"        return cls(is_slo, timestamp, manifest_etag, slo_etag, slo_size)"},{"line_number":609,"context_line":""},{"line_number":610,"context_line":"    def update_from_segments(self, segments):"}],"source_content_type":"text/x-python","patch_set":41,"id":"9b44bd3c_97500607","line":607,"in_reply_to":"b153c633_da9e6a00","updated":"2023-11-07 19:40:36.000000000","message":"\u003e I wonder why you find it curious?\n\nBecause none of the other attrs (short of `timestamp`) make any sense unless `is_slo` is true!\n\n\u003e I agree it would be strange to raise an error in update_from_segments if not self.is_slo\n\nThat wasn\u0027t what I was saying -- I was saying that calling `update_from_segments` at all when `not self.is_slo` is some nonsense -- and as a result, I wouldn\u0027t be *opposed* to us raising an error, though I don\u0027t care enough to push for it.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":623,"context_line":"        calculated_etag \u003d md5(usedforsecurity\u003dFalse)"},{"line_number":624,"context_line":""},{"line_number":625,"context_line":"        for seg_dict in segments:"},{"line_number":626,"context_line":"            calculated_size +\u003d seg_dict[\u0027segment_length\u0027]"},{"line_number":627,"context_line":""},{"line_number":628,"context_line":"            if \u0027raw_data\u0027 in seg_dict:"},{"line_number":629,"context_line":"                r \u003d md5(seg_dict[\u0027raw_data\u0027],"}],"source_content_type":"text/x-python","patch_set":41,"id":"da130c59_a318c63a","line":626,"updated":"2023-11-03 18:50:26.000000000","message":"Right; we call `_annotate_segments` straight away after parsing the JSON, so this should always be available.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":623,"context_line":"        calculated_etag \u003d md5(usedforsecurity\u003dFalse)"},{"line_number":624,"context_line":""},{"line_number":625,"context_line":"        for seg_dict in segments:"},{"line_number":626,"context_line":"            calculated_size +\u003d seg_dict[\u0027segment_length\u0027]"},{"line_number":627,"context_line":""},{"line_number":628,"context_line":"            if \u0027raw_data\u0027 in seg_dict:"},{"line_number":629,"context_line":"                r \u003d md5(seg_dict[\u0027raw_data\u0027],"}],"source_content_type":"text/x-python","patch_set":41,"id":"2d34d9ef_cbb7b9a3","line":626,"in_reply_to":"da130c59_a318c63a","updated":"2023-11-04 00:34:58.000000000","message":"hopefully tests cover that assumption, although perhaps it would be reasonable to move segment annotation inside of SLOAttrs (it would simplfy TestSloAttrs.test_update_from_segments et. al.)\n\n... but we\u0027d have to do some plumbing in _fetch_sub_slo_segments (which doesn\u0027t even check is_slo headers)\n\nmaybe we could push to clean this up a little more when take on:\n\nhttps://bugs.launchpad.net/swift/+bug/2037662 - SLO does not validate submanifests on read","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":823,"context_line":"        # e.g. Content-Range: bytes 0-14289/14290"},{"line_number":824,"context_line":"        match \u003d re.match(r\u0027bytes (\\d+)-(\\d+)/(\\d+)$\u0027, content_range)"},{"line_number":825,"context_line":"        if not match:"},{"line_number":826,"context_line":"            # Malformed or missing, so we don\u0027t know what we got."},{"line_number":827,"context_line":"            return False"},{"line_number":828,"context_line":"        first_byte, last_byte, length \u003d [int(x) for x in match.groups()]"},{"line_number":829,"context_line":"        # If and only if we actually got back the full manifest body, then"}],"source_content_type":"text/x-python","patch_set":41,"id":"76715c9f_1e10bb40","line":826,"range":{"start_line":826,"start_character":27,"end_line":826,"end_character":34},"updated":"2023-11-03 18:50:26.000000000","message":"Significantly, we only call this on 206, so we were *expecting* a `Content-Range`; its absence from the HTTP headers would indicate a multipart MIME doc.\n\nCompare that with the 200 case, where the absence is entirely expected yet we can be confident we (should) have the complete body.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":823,"context_line":"        # e.g. Content-Range: bytes 0-14289/14290"},{"line_number":824,"context_line":"        match \u003d re.match(r\u0027bytes (\\d+)-(\\d+)/(\\d+)$\u0027, content_range)"},{"line_number":825,"context_line":"        if not match:"},{"line_number":826,"context_line":"            # Malformed or missing, so we don\u0027t know what we got."},{"line_number":827,"context_line":"            return False"},{"line_number":828,"context_line":"        first_byte, last_byte, length \u003d [int(x) for x in match.groups()]"},{"line_number":829,"context_line":"        # If and only if we actually got back the full manifest body, then"}],"source_content_type":"text/x-python","patch_set":41,"id":"d85232e7_0d90c5d0","line":826,"range":{"start_line":826,"start_character":27,"end_line":826,"end_character":34},"in_reply_to":"76715c9f_1e10bb40","updated":"2023-11-04 00:34:58.000000000","message":"\u003e its absence from the HTTP headers would indicate a multipart MIME doc.\n\nthat\u0027s correct!  I didn\u0027t know when before i started working on this change.  Your HTTP knowledge is encyclopedic.\n\nIs this observation significant to the correctness?  I feel like it\u0027s unlikely a multi-range response would somehow have have the whole manifest, and even if it did it\u0027s unlikely/complex enough to warrent a \"just refetch it w/o range so we don\u0027t have to think about it\"\n\nperhaps the comment could more obviously convey \", regardless of what we might\u0027ve got: return False\"","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":false,"context_lines":[{"line_number":823,"context_line":"        # e.g. Content-Range: bytes 0-14289/14290"},{"line_number":824,"context_line":"        match \u003d re.match(r\u0027bytes (\\d+)-(\\d+)/(\\d+)$\u0027, content_range)"},{"line_number":825,"context_line":"        if not match:"},{"line_number":826,"context_line":"            # Malformed or missing, so we don\u0027t know what we got."},{"line_number":827,"context_line":"            return False"},{"line_number":828,"context_line":"        first_byte, last_byte, length \u003d [int(x) for x in match.groups()]"},{"line_number":829,"context_line":"        # If and only if we actually got back the full manifest body, then"}],"source_content_type":"text/x-python","patch_set":41,"id":"7c3ca2e1_67f2aef2","line":826,"range":{"start_line":826,"start_character":27,"end_line":826,"end_character":34},"in_reply_to":"d85232e7_0d90c5d0","updated":"2023-11-07 19:40:36.000000000","message":"The comment was all about my mild surprise at something called `_is_body_complete` assuming that a missing `Content-Range` should imply that the body is *not* complete when the happiest-path GET wouldn\u0027t include it. We\u0027re in a `WSGIContext`, we have the response status in hand -- why _wouldn\u0027t_ we this look at it? Something like https://paste.opendev.org/show/bMo6f9R0rmpc3Sj2TBus/ actually reads pretty well to me. It fails on your new `test_slo_sysmeta_on_error` but that was because it was making up nonsense responses anyway.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":false,"context_lines":[{"line_number":844,"context_line":"            return False"},{"line_number":845,"context_line":""},{"line_number":846,"context_line":"        if is_manifest_get:"},{"line_number":847,"context_line":"            # Any manifest json object response will do"},{"line_number":848,"context_line":"            return False"},{"line_number":849,"context_line":""},{"line_number":850,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027:"}],"source_content_type":"text/x-python","patch_set":41,"id":"742a1197_fbbd39fc","line":847,"updated":"2023-11-03 18:50:26.000000000","message":"I\u0027m not sure how true this is -- but we can leave it for https://review.opendev.org/c/openstack/swift/+/890246 to address.\n\nOh, but you\u0027re calling out the bug below, with the `HEAD`...","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":true,"context_lines":[{"line_number":844,"context_line":"            return False"},{"line_number":845,"context_line":""},{"line_number":846,"context_line":"        if is_manifest_get:"},{"line_number":847,"context_line":"            # Any manifest json object response will do"},{"line_number":848,"context_line":"            return False"},{"line_number":849,"context_line":""},{"line_number":850,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027:"}],"source_content_type":"text/x-python","patch_set":41,"id":"a84aaff5_110e5f48","line":847,"in_reply_to":"742a1197_fbbd39fc","updated":"2023-11-04 00:34:58.000000000","message":"i should respin that on this and see if re-ordering these conditions might make the diff in the follow on easier to read.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":861,"context_line":"        # likely that the submitted If-None-Match won\u0027t match the manifest"},{"line_number":862,"context_line":"        # object\u0027s etag, so we can avoid re-fetching the manifest if we got a"},{"line_number":863,"context_line":"        # successful response."},{"line_number":864,"context_line":"        if last_resp_status_int in (412, 304):"},{"line_number":865,"context_line":"            # a conditional response from a modern manifest would have an"},{"line_number":866,"context_line":"            # accurate SLO etag, AND comparison with the etag-is-at header, but"},{"line_number":867,"context_line":"            # for legacy manifests responses (who always need to calculate the"}],"source_content_type":"text/x-python","patch_set":41,"id":"a70fffb9_a639a1f2","line":864,"updated":"2023-11-03 18:50:26.000000000","message":"OK, no longer looking for `req.if_match or req.if_none_match`, which presumably was part of the fix for https://bugs.launchpad.net/swift/+bug/2040178","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":861,"context_line":"        # likely that the submitted If-None-Match won\u0027t match the manifest"},{"line_number":862,"context_line":"        # object\u0027s etag, so we can avoid re-fetching the manifest if we got a"},{"line_number":863,"context_line":"        # successful response."},{"line_number":864,"context_line":"        if last_resp_status_int in (412, 304):"},{"line_number":865,"context_line":"            # a conditional response from a modern manifest would have an"},{"line_number":866,"context_line":"            # accurate SLO etag, AND comparison with the etag-is-at header, but"},{"line_number":867,"context_line":"            # for legacy manifests responses (who always need to calculate the"}],"source_content_type":"text/x-python","patch_set":41,"id":"f22604c1_9bd1081c","line":864,"in_reply_to":"a70fffb9_a639a1f2","updated":"2023-11-04 00:34:58.000000000","message":"ahhh, `... or req.if_modified_since or req.if_unmodified_since` - well spotted!","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":933,"context_line":"            resp_iter \u003d [json_data]"},{"line_number":934,"context_line":"            replace_headers \u003d {"},{"line_number":935,"context_line":"                # test_get_raw_manifest asserts we return this json"},{"line_number":936,"context_line":"                # content-type as text/plain"},{"line_number":937,"context_line":"                \u0027Content-Length\u0027: len(json_data),"},{"line_number":938,"context_line":"                \u0027Etag\u0027: md5(json_data, usedforsecurity\u003dFalse).hexdigest(),"},{"line_number":939,"context_line":"            }"}],"source_content_type":"text/x-python","patch_set":41,"id":"61e68a4a_07d7fde1","line":936,"updated":"2023-11-03 18:50:26.000000000","message":"Well *that* seems unfortunate...","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":true,"context_lines":[{"line_number":933,"context_line":"            resp_iter \u003d [json_data]"},{"line_number":934,"context_line":"            replace_headers \u003d {"},{"line_number":935,"context_line":"                # test_get_raw_manifest asserts we return this json"},{"line_number":936,"context_line":"                # content-type as text/plain"},{"line_number":937,"context_line":"                \u0027Content-Length\u0027: len(json_data),"},{"line_number":938,"context_line":"                \u0027Etag\u0027: md5(json_data, usedforsecurity\u003dFalse).hexdigest(),"},{"line_number":939,"context_line":"            }"}],"source_content_type":"text/x-python","patch_set":41,"id":"a6110719_43295eef","line":936,"in_reply_to":"61e68a4a_07d7fde1","updated":"2023-11-04 00:34:58.000000000","message":"yeah, idk if we can change that - but it might be be reasonable to have the debate on a follow-up with an associated lp bug suggesting we should probably return a content-type matching the response","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":true,"context_lines":[{"line_number":933,"context_line":"            resp_iter \u003d [json_data]"},{"line_number":934,"context_line":"            replace_headers \u003d {"},{"line_number":935,"context_line":"                # test_get_raw_manifest asserts we return this json"},{"line_number":936,"context_line":"                # content-type as text/plain"},{"line_number":937,"context_line":"                \u0027Content-Length\u0027: len(json_data),"},{"line_number":938,"context_line":"                \u0027Etag\u0027: md5(json_data, usedforsecurity\u003dFalse).hexdigest(),"},{"line_number":939,"context_line":"            }"}],"source_content_type":"text/x-python","patch_set":41,"id":"ceae1556_8593fb6c","line":936,"in_reply_to":"a6110719_43295eef","updated":"2023-11-07 19:40:36.000000000","message":"Oh! Actually, this makes sense -- we\u0027re trying to mirror what a client must have sent on `PUT`. Probably worth updating the comment to be more like\n\n\u003e Note that we have to return the large object\u0027s content-type so server-side copy works.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":false,"context_lines":[{"line_number":933,"context_line":"            resp_iter \u003d [json_data]"},{"line_number":934,"context_line":"            replace_headers \u003d {"},{"line_number":935,"context_line":"                # test_get_raw_manifest asserts we return this json"},{"line_number":936,"context_line":"                # content-type as text/plain"},{"line_number":937,"context_line":"                \u0027Content-Length\u0027: len(json_data),"},{"line_number":938,"context_line":"                \u0027Etag\u0027: md5(json_data, usedforsecurity\u003dFalse).hexdigest(),"},{"line_number":939,"context_line":"            }"}],"source_content_type":"text/x-python","patch_set":41,"id":"d785ac55_651a143d","line":936,"in_reply_to":"ceae1556_8593fb6c","updated":"2023-11-09 23:25:02.000000000","message":"yeah, latest comment in _return_manifest_response is much better!","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":957,"context_line":""},{"line_number":958,"context_line":"    def _return_response(self, req, start_response, resp_iter,"},{"line_number":959,"context_line":"                         replace_headers):"},{"line_number":960,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or self._get_status_int() in (412, 304):"},{"line_number":961,"context_line":"            # we should drain HEAD and unmet condition responses since they"},{"line_number":962,"context_line":"            # don\u0027t have bodies"},{"line_number":963,"context_line":"            friendly_close(resp_iter)"}],"source_content_type":"text/x-python","patch_set":41,"id":"682528e6_558b5d51","line":960,"range":{"start_line":960,"start_character":62,"end_line":960,"end_character":70},"updated":"2023-11-03 18:50:26.000000000","message":"nit: I wonder if we should use some `http` constants...","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":957,"context_line":""},{"line_number":958,"context_line":"    def _return_response(self, req, start_response, resp_iter,"},{"line_number":959,"context_line":"                         replace_headers):"},{"line_number":960,"context_line":"        if req.method \u003d\u003d \u0027HEAD\u0027 or self._get_status_int() in (412, 304):"},{"line_number":961,"context_line":"            # we should drain HEAD and unmet condition responses since they"},{"line_number":962,"context_line":"            # don\u0027t have bodies"},{"line_number":963,"context_line":"            friendly_close(resp_iter)"}],"source_content_type":"text/x-python","patch_set":41,"id":"8058496d_e0f8aee0","line":960,"range":{"start_line":960,"start_character":62,"end_line":960,"end_character":70},"in_reply_to":"682528e6_558b5d51","updated":"2023-11-04 00:34:58.000000000","message":"heh, or even a helper function!  :rofl:","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":985,"context_line":"            headers\u003dself._response_headers,"},{"line_number":986,"context_line":"            app_iter\u003dresp_iter,"},{"line_number":987,"context_line":"            request\u003dreq,"},{"line_number":988,"context_line":"            conditional_response\u003dself._get_status_int() \u003d\u003d 200,"},{"line_number":989,"context_line":"            conditional_etag\u003dresolve_etag_is_at_header("},{"line_number":990,"context_line":"                req, self._response_headers)"},{"line_number":991,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":41,"id":"e478d88a_7eef8635","line":988,"updated":"2023-11-03 18:50:26.000000000","message":"This is the *one bit* that makes it so we can\u0027t use `_return_response`, yeah?","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":true,"context_lines":[{"line_number":985,"context_line":"            headers\u003dself._response_headers,"},{"line_number":986,"context_line":"            app_iter\u003dresp_iter,"},{"line_number":987,"context_line":"            request\u003dreq,"},{"line_number":988,"context_line":"            conditional_response\u003dself._get_status_int() \u003d\u003d 200,"},{"line_number":989,"context_line":"            conditional_etag\u003dresolve_etag_is_at_header("},{"line_number":990,"context_line":"                req, self._response_headers)"},{"line_number":991,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":41,"id":"597111a0_d223fd78","line":988,"in_reply_to":"e478d88a_7eef8635","updated":"2023-11-04 00:34:58.000000000","message":"maybe; I couldn\u0027t get them unified last time I tried\n\nbut also that method has some stuff that just doesn\u0027t seem needed in the non_slo case - like replace_headers","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":1002,"context_line":"                    large object manifest."},{"line_number":1003,"context_line":"        :param start_response: WSGI start_response callable"},{"line_number":1004,"context_line":"        \"\"\""},{"line_number":1005,"context_line":"        is_manifest_get \u003d get_param(req, \u0027multipart-manifest\u0027) \u003d\u003d \u0027get\u0027"},{"line_number":1006,"context_line":"        is_format_raw \u003d is_manifest_get and get_param(req, \u0027format\u0027) \u003d\u003d \u0027raw\u0027"},{"line_number":1007,"context_line":""},{"line_number":1008,"context_line":"        if not is_manifest_get:"}],"source_content_type":"text/x-python","patch_set":41,"id":"51f2f15f_aa63c9bc","line":1005,"range":{"start_line":1005,"start_character":26,"end_line":1005,"end_character":35},"updated":"2023-11-03 18:50:26.000000000","message":"... because we\u0027re concerned about client sending `?multipart-manifest\u003d☃`, I guess?\n\nI wonder sometimes if we should just go ahead and make `Request.params` handle unicode on py3 better...","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":1002,"context_line":"                    large object manifest."},{"line_number":1003,"context_line":"        :param start_response: WSGI start_response callable"},{"line_number":1004,"context_line":"        \"\"\""},{"line_number":1005,"context_line":"        is_manifest_get \u003d get_param(req, \u0027multipart-manifest\u0027) \u003d\u003d \u0027get\u0027"},{"line_number":1006,"context_line":"        is_format_raw \u003d is_manifest_get and get_param(req, \u0027format\u0027) \u003d\u003d \u0027raw\u0027"},{"line_number":1007,"context_line":""},{"line_number":1008,"context_line":"        if not is_manifest_get:"}],"source_content_type":"text/x-python","patch_set":41,"id":"407e3ca9_d5353eea","line":1005,"range":{"start_line":1005,"start_character":26,"end_line":1005,"end_character":35},"in_reply_to":"51f2f15f_aa63c9bc","updated":"2023-11-04 00:34:58.000000000","message":"Ack","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":1007,"context_line":""},{"line_number":1008,"context_line":"        if not is_manifest_get:"},{"line_number":1009,"context_line":"            # Tell the object server where to find the ETag to match for"},{"line_number":1010,"context_line":"            # conditional requests"},{"line_number":1011,"context_line":"            update_etag_is_at_header(req, SYSMETA_SLO_ETAG)"},{"line_number":1012,"context_line":"            # Tell the object server that if it\u0027s a manifest,"},{"line_number":1013,"context_line":"            # we want the whole thing"}],"source_content_type":"text/x-python","patch_set":41,"id":"9d6b1942_8f9cf7f1","line":1010,"updated":"2023-11-03 18:50:26.000000000","message":"... if it was written by new-enough Swift.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":1007,"context_line":""},{"line_number":1008,"context_line":"        if not is_manifest_get:"},{"line_number":1009,"context_line":"            # Tell the object server where to find the ETag to match for"},{"line_number":1010,"context_line":"            # conditional requests"},{"line_number":1011,"context_line":"            update_etag_is_at_header(req, SYSMETA_SLO_ETAG)"},{"line_number":1012,"context_line":"            # Tell the object server that if it\u0027s a manifest,"},{"line_number":1013,"context_line":"            # we want the whole thing"}],"source_content_type":"text/x-python","patch_set":41,"id":"7a27d4e0_307b85a6","line":1010,"in_reply_to":"9d6b1942_8f9cf7f1","updated":"2023-11-04 00:34:58.000000000","message":"yeah the original comment seems better #willfix","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":1016,"context_line":"        # process request and ensure response is from a SLO manifest"},{"line_number":1017,"context_line":"        resp_iter \u003d self._app_call(req.environ)"},{"line_number":1018,"context_line":"        slo_attrs \u003d SloAttrs.from_headers(self._response_headers)"},{"line_number":1019,"context_line":"        if self._need_to_refetch_manifest(req, slo_attrs, is_manifest_get):"},{"line_number":1020,"context_line":"            slo_attrs, resp_iter \u003d self._refetch_manifest("},{"line_number":1021,"context_line":"                req, resp_iter, slo_attrs)"},{"line_number":1022,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"b08bbf5e_96bc4fb4","line":1019,"range":{"start_line":1019,"start_character":16,"end_line":1019,"end_character":41},"updated":"2023-11-03 18:50:26.000000000","message":"I wonder if we should rename this to `_is_manifest_and_need_to_refetch` -- it reads a little funny (to me, anyway) to have\n```\nslo_attrs \u003d SloAttrs.from_headers(self._response_headers)\nif self._need_to_refetch_manifest(...):\n    slo_attrs, resp_iter \u003d self._refetch_manifest(...)\nif not slo_attrs.is_slo:\n    return self._return_non_slo_response(...)\n```\nIt feels like we\u0027ve not checked our assumptions properly (even though we have).","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":1016,"context_line":"        # process request and ensure response is from a SLO manifest"},{"line_number":1017,"context_line":"        resp_iter \u003d self._app_call(req.environ)"},{"line_number":1018,"context_line":"        slo_attrs \u003d SloAttrs.from_headers(self._response_headers)"},{"line_number":1019,"context_line":"        if self._need_to_refetch_manifest(req, slo_attrs, is_manifest_get):"},{"line_number":1020,"context_line":"            slo_attrs, resp_iter \u003d self._refetch_manifest("},{"line_number":1021,"context_line":"                req, resp_iter, slo_attrs)"},{"line_number":1022,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"f0567d97_d4cb4ee3","line":1019,"range":{"start_line":1019,"start_character":16,"end_line":1019,"end_character":41},"in_reply_to":"b08bbf5e_96bc4fb4","updated":"2023-11-04 00:34:58.000000000","message":"I think Al also got caught once missing the overwrite of slo_attrs in the conditional block!  The annoying thing is that we migth pass in slo_attrs.is_slo and get back not slo_attrs.is_slo after refetch\n\n    diff --git a/swift/common/middleware/slo.py b/swift/common/middleware/slo.py\n    index 6f89d1d1e..d1d52a4f5 100644\n    --- a/swift/common/middleware/slo.py\n    +++ b/swift/common/middleware/slo.py\n    @@ -1022,17 +1022,23 @@ class SloGetContext(WSGIContext):\n     \n             # process request and ensure response is from a SLO manifest\n             resp_iter \u003d self._app_call(req.environ)\n    -        slo_attrs \u003d SloAttrs.from_headers(self._response_headers)\n    -        if self._need_to_refetch_manifest(req, slo_attrs, is_manifest_get):\n    -            slo_attrs, resp_iter \u003d self._refetch_manifest(\n    -                req, resp_iter, slo_attrs)\n    +        first_slo_attrs \u003d SloAttrs.from_headers(self._response_headers)\n    +        if self._need_to_refetch_manifest(\n    +                req, first_slo_attrs, is_manifest_get):\n    +            maybe_slo_attrs, resp_iter \u003d self._refetch_manifest(\n    +                req, resp_iter, first_slo_attrs)\n    +        else:\n    +            maybe_slo_attrs \u003d first_slo_attrs\n     \n    -        if not slo_attrs.is_slo:\n    +        if not maybe_slo_attrs.is_slo:\n                 # even if the original slo_attrs maybe have been SLO we may have\n                 # refetched, this also handles the server error case\n                 return self._return_non_slo_response(\n                     req, start_response, resp_iter)\n    -        elif is_manifest_get:\n    +        else:\n    +            slo_attrs \u003d maybe_slo_attrs\n    +\n    +        if is_manifest_get:\n                 # manifest pass through doesn\u0027t require slo_attrs\n                 return self._return_manifest_response(req, start_response,\n                                                       resp_iter, is_format_raw)\n                                                       \n                                                       \nI\u0027m keen on making it more explict and obvious","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":false,"context_lines":[{"line_number":1016,"context_line":"        # process request and ensure response is from a SLO manifest"},{"line_number":1017,"context_line":"        resp_iter \u003d self._app_call(req.environ)"},{"line_number":1018,"context_line":"        slo_attrs \u003d SloAttrs.from_headers(self._response_headers)"},{"line_number":1019,"context_line":"        if self._need_to_refetch_manifest(req, slo_attrs, is_manifest_get):"},{"line_number":1020,"context_line":"            slo_attrs, resp_iter \u003d self._refetch_manifest("},{"line_number":1021,"context_line":"                req, resp_iter, slo_attrs)"},{"line_number":1022,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"34f8bd40_8a4f8369","line":1019,"range":{"start_line":1019,"start_character":16,"end_line":1019,"end_character":41},"in_reply_to":"f0567d97_d4cb4ee3","updated":"2023-11-07 19:40:36.000000000","message":"\u003e I think Al also got caught once missing the overwrite of slo_attrs in the conditional block!\n\nThat wasn\u0027t my trouble -- though I guess maybe the overwrite further complicated things.\n\nMy trouble was that we\u0027re asking this question (\"Do we need to refetch the manifest?\") which seems to embed an assumption (\"We\u0027re looking at a manifest.\") The awkwardness is even more pronounced since we later **do** need to check the assumption (`if not slo_attrs.is_slo:`) -- why didn\u0027t we check the assumption when deciding to refecth or not? So I need to hop up a couple hundred lines to realize that we actually *did*.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":1031,"context_line":"                                                  resp_iter, is_format_raw)"},{"line_number":1032,"context_line":""},{"line_number":1033,"context_line":"        # this a GET/HEAD response for the SLO object (not the manifest)"},{"line_number":1034,"context_line":"        if self.segment_listing_needed:"},{"line_number":1035,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1036,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"}],"source_content_type":"text/x-python","patch_set":41,"id":"49a0c49b_a73adecb","line":1034,"updated":"2023-11-03 18:50:26.000000000","message":"OK, so this condition is the whole reason for the new attribute.\n\nI don\u0027t love the action-at-a-distance (first set in `__init__`, finalized in `_need_to_refetch_manifest`, just so we can read it here) but I also don\u0027t have a better idea.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":1031,"context_line":"                                                  resp_iter, is_format_raw)"},{"line_number":1032,"context_line":""},{"line_number":1033,"context_line":"        # this a GET/HEAD response for the SLO object (not the manifest)"},{"line_number":1034,"context_line":"        if self.segment_listing_needed:"},{"line_number":1035,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1036,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"}],"source_content_type":"text/x-python","patch_set":41,"id":"feaeae2d_59844d21","line":1034,"in_reply_to":"49a0c49b_a73adecb","updated":"2023-11-04 00:34:58.000000000","message":"YES!  Al and I struggled quite a bit to come up with even *this*!\n\nLuckily the spooky action is just a boolean and the the the distance is still just a few methods away in the SAME class and all the mutation is happens in the one method.\n\nIf future maintainers want to understand who sets segment_listing_needed and why it\u0027s a quick grep to find _need_to_refetch_manifest and they may even have some sympathy using object state instead of multiple return - assuming they forgive self._response_status they can\u0027t be TOO mad about it ;)","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":1032,"context_line":""},{"line_number":1033,"context_line":"        # this a GET/HEAD response for the SLO object (not the manifest)"},{"line_number":1034,"context_line":"        if self.segment_listing_needed:"},{"line_number":1035,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1036,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1038,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"}],"source_content_type":"text/x-python","patch_set":41,"id":"21c7a553_81596f9a","line":1035,"updated":"2023-11-03 18:50:26.000000000","message":"OK, after this `resp_iter` is exhausted, so `HEAD`s get a zero-byte body. I might\u0027ve gone for an explicit `resp_iter \u003d []`, but w/e","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":1032,"context_line":""},{"line_number":1033,"context_line":"        # this a GET/HEAD response for the SLO object (not the manifest)"},{"line_number":1034,"context_line":"        if self.segment_listing_needed:"},{"line_number":1035,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1036,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1038,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"}],"source_content_type":"text/x-python","patch_set":41,"id":"ed50f19e_55173bd9","line":1035,"in_reply_to":"21c7a553_81596f9a","updated":"2023-11-04 00:34:58.000000000","message":"you\u0027d have to show me in code what you mean; like an elif HEAD on the GET block?  _return_slo_response needs a resp_iter, sometimes we want the one we have, sometimes we parse it and _build_resp_iter","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":false,"context_lines":[{"line_number":1032,"context_line":""},{"line_number":1033,"context_line":"        # this a GET/HEAD response for the SLO object (not the manifest)"},{"line_number":1034,"context_line":"        if self.segment_listing_needed:"},{"line_number":1035,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1036,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1038,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"}],"source_content_type":"text/x-python","patch_set":41,"id":"dde3548f_fb7818e5","line":1035,"in_reply_to":"ed50f19e_55173bd9","updated":"2023-11-07 19:40:36.000000000","message":"Yeah, something like\n```\nif req.method \u003d \u0027GET\u0027:\n    resp_iter \u003d self._build_resp_iter(req, slo_attrs)\nelse:\n    # HEAD\n    resp_iter \u003d []\n```","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":1035,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1036,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1038,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"},{"line_number":1039,"context_line":"                # first segment on HEAD"},{"line_number":1040,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1041,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1042,"context_line":"                                         slo_attrs)"}],"source_content_type":"text/x-python","patch_set":41,"id":"94b36c68_54a20d0d","line":1039,"range":{"start_line":1038,"start_character":50,"end_line":1039,"end_character":39},"updated":"2023-11-03 18:50:26.000000000","message":"I\u0027m not sure what to make of this part.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":1035,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1036,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1038,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"},{"line_number":1039,"context_line":"                # first segment on HEAD"},{"line_number":1040,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1041,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1042,"context_line":"                                         slo_attrs)"}],"source_content_type":"text/x-python","patch_set":41,"id":"9c085b29_efd0c823","line":1039,"range":{"start_line":1038,"start_character":50,"end_line":1039,"end_character":39},"in_reply_to":"94b36c68_54a20d0d","updated":"2023-11-04 00:34:58.000000000","message":"it\u0027s just a statement of why this is conditional - if you _build_resp_iter we\u0027ll call validate_first_segment regardless and tests will fail because they don\u0027t expect HEAD requests to do that.\n\nI wasn\u0027t trying to make it sound judgemental","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":false,"context_lines":[{"line_number":1035,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1036,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1038,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"},{"line_number":1039,"context_line":"                # first segment on HEAD"},{"line_number":1040,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1041,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1042,"context_line":"                                         slo_attrs)"}],"source_content_type":"text/x-python","patch_set":41,"id":"6e303436_fda5fee3","line":1039,"range":{"start_line":1038,"start_character":50,"end_line":1039,"end_character":39},"in_reply_to":"9c085b29_efd0c823","updated":"2023-11-07 19:40:36.000000000","message":"I meant more that it seems self-evident that if we\u0027re doing a HEAD, the response body *must* be empty, so there\u0027s no point in building a resp iter. IDK that I\u0027d ever expect a HEAD to do that sort of validation.\n\nOTOH, I *do* sometimes get annoyed that EC HEADs don\u0027t validate that there are enough frags to actually rebuild... maybe my position isn\u0027t terribly consistent...","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1038,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"},{"line_number":1039,"context_line":"                # first segment on HEAD"},{"line_number":1040,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1041,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1042,"context_line":"                                         slo_attrs)"},{"line_number":1043,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"b75f70d3_fe2cea0d","line":1040,"range":{"start_line":1040,"start_character":55,"end_line":1040,"end_character":64},"updated":"2023-11-03 18:50:26.000000000","message":"I think I\u0027d feel better about the flow if we nixed the `segments` attr from `SloAttrs` and just pass it explicitly to `_build_resp_iter` -- as it is, there\u0027s this unstated requirement: you **must** call `update_from_segments` before calling `_build_resp_iter`.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":true,"context_lines":[{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1038,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"},{"line_number":1039,"context_line":"                # first segment on HEAD"},{"line_number":1040,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1041,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1042,"context_line":"                                         slo_attrs)"},{"line_number":1043,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"f5273d46_a1793cb8","line":1040,"range":{"start_line":1040,"start_character":55,"end_line":1040,"end_character":64},"in_reply_to":"17686a66_846f0ebe","updated":"2023-11-07 19:40:36.000000000","message":"OK, just needed to get further down the chain I guess.\n\n\u003e what assumptions does _build_resp_iter have about the req object you pass in?\n\nEh? It doesn\u0027t -- but it _does_ have assumptions about the `slo_attrs` passed in. Specifically, that you\u0027ve called `update_from_segments` on it -- and you have to do that even when you\u0027re looking at a modern manifest with the etag/length sysmeta.\n\nMainly, it was that the early return in `update_from_segments` stuck out to me. If we didn\u0027t have the `segments` attr, it\u0027d be more like a guard return and I wouldn\u0027t have thought too hard about it. Doing *some* things but not *all* the things gave me pause, but I can take it on faith that this will make things easier later.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":true,"context_lines":[{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1038,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"},{"line_number":1039,"context_line":"                # first segment on HEAD"},{"line_number":1040,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1041,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1042,"context_line":"                                         slo_attrs)"},{"line_number":1043,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"17686a66_846f0ebe","line":1040,"range":{"start_line":1040,"start_character":55,"end_line":1040,"end_character":64},"in_reply_to":"b75f70d3_fe2cea0d","updated":"2023-11-04 00:34:58.000000000","message":"unfortunately having segments coupled with slo_attrs comes in handy for plumbing later when we need to return x-parts-count headers\n\nleaving them decoupled bcomes annoying when to have to pass around (slo-attrs, segments) - esp when sometimes we you don\u0027t have segments, but you ALWAYS have slo-attrs.\n\nIs there anyway we could make the expectation more explicit?  \n\nwith a diff like:\n\n    diff --git a/swift/common/middleware/slo.py b/swift/common/middleware/slo.py\n    index d1d52a4f5..3d9b97995 100644\n    --- a/swift/common/middleware/slo.py\n    +++ b/swift/common/middleware/slo.py\n    @@ -1046,7 +1046,7 @@ class SloGetContext(WSGIContext):\n             # this a GET/HEAD response for the SLO object (not the manifest)\n             if self.segment_listing_needed:\n                 segments \u003d self._parse_segments(resp_iter)\n    -            slo_attrs.update_from_segments(segments)\n    +            # slo_attrs.update_from_segments(segments)\n                 if req.method \u003d\u003d \u0027GET\u0027:\n                     # we\u0027ll need a slo response body, and we don\u0027t validate the\n                     # first segment on HEAD\n\n\nI get `122 failed, 170 passed` from test_slo\n\nThe majority of failures look like:\n\n```\n\u003e       for seg_dict in segments:\nE       TypeError: \u0027NoneType\u0027 object is not iterable\n```\n\nwhat assumptions does `_build_resp_iter` have about the req object you pass in?","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":true,"context_lines":[{"line_number":1037,"context_line":"            if req.method \u003d\u003d \u0027GET\u0027:"},{"line_number":1038,"context_line":"                # we\u0027ll need a slo response body, and we don\u0027t validate the"},{"line_number":1039,"context_line":"                # first segment on HEAD"},{"line_number":1040,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1041,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"},{"line_number":1042,"context_line":"                                         slo_attrs)"},{"line_number":1043,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"808f1743_c33a03de","line":1040,"range":{"start_line":1040,"start_character":55,"end_line":1040,"end_character":64},"in_reply_to":"f5273d46_a1793cb8","updated":"2023-11-09 23:25:02.000000000","message":"\u003e but it does have assumptions about the slo_attrs passed in\n\nMaybe I wasn\u0027t clear when I started with \"unfortunately\" or asked explicitly \"Is there anyway we could make the expectation more explicit?\" that I understood EXACTLY what you were calling out and consider it useful feedback.  You don\u0027t have to justfiy or elaborate your perspective on a review comment you open with: \n\n\"I think I\u0027d feel better about the flow if \"\n\n\u003e  Eh? It doesn\u0027t -- \n\n:rofl:\n\n\t@@ -1063,7 +1063,8 @@ class SloGetContext(WSGIContext):\n\t\t     if req.method \u003d\u003d \u0027HEAD\u0027:\n\t\t\t resp_iter \u003d []\n\t\t     else:\n\t-                resp_iter \u003d self._build_resp_iter(req, resp_attrs)\n\t+                resp_iter \u003d self._build_resp_iter(\n\t+                    Request.blank(\u0027/\u0027), resp_attrs)\n\t\t return self._return_slo_response(req, start_response, resp_iter,\n\t\t\t\t\t\t  resp_attrs)\n\nOMM that\u0027s `116 failed, 176 passed` in `test_slo`.  I wasn\u0027t saying the two arguments to _build_resp_iter have the *same* assumptions.  I recognize the second param is a bit wonky but hoped you might appreciate that since tests cover this assumption - perhaps it\u0027s not *unreasonably* so?  Please appreciate I offer most of my diffs \"with apologies\" and would only rarely come to their defense lacking a clear better path forward.\n\n\u003e but I can take it on faith that this will make things easier later.\n\nLOL, you\u0027re on fire!  I don\u0027t want you faith.  I need your help.  If you are open and honest about what you like and dislike when you\u0027re looking at a diff I\u0027ve shared - I will continue to WANT to try to respond with an update that I hope we will BOTH like better - the goal is the best we can possibly do!  And since I value your experience and reaction, if you make a suggestion and I push back, what I would find MOST helpful is either \"thanks for the consideration/input, this is fine\" or \"have you considered this: \u003cworking diff\u003e\".\n\nFWIW the assumption _build_resp_iter makes about having called update_from_segments actually bugs me MORE now we name it RespAttrs.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":1046,"context_line":"        Converts the manifest data to match with the format"},{"line_number":1047,"context_line":"        that was put in through ?multipart-manifest\u003dput"},{"line_number":1048,"context_line":""},{"line_number":1049,"context_line":"        :param resp_iter: a response iterable"},{"line_number":1050,"context_line":""},{"line_number":1051,"context_line":"        :returns: the unencoded raw format data"},{"line_number":1052,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":41,"id":"5dd8030a_056b54af","line":1049,"updated":"2023-11-03 18:50:26.000000000","message":"As long as we\u0027re updating docstrings:\n```\n:raises HTTPServerError:\n```","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":1046,"context_line":"        Converts the manifest data to match with the format"},{"line_number":1047,"context_line":"        that was put in through ?multipart-manifest\u003dput"},{"line_number":1048,"context_line":""},{"line_number":1049,"context_line":"        :param resp_iter: a response iterable"},{"line_number":1050,"context_line":""},{"line_number":1051,"context_line":"        :returns: the unencoded raw format data"},{"line_number":1052,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":41,"id":"4bc8f0e6_58a3a1c7","line":1049,"in_reply_to":"5dd8030a_056b54af","updated":"2023-11-04 00:34:58.000000000","message":"Done","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":1048,"context_line":""},{"line_number":1049,"context_line":"        :param resp_iter: a response iterable"},{"line_number":1050,"context_line":""},{"line_number":1051,"context_line":"        :returns: the unencoded raw format data"},{"line_number":1052,"context_line":"        \"\"\""},{"line_number":1053,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":1054,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"1b4671a2_f50cf82e","line":1051,"range":{"start_line":1051,"start_character":22,"end_line":1051,"end_character":31},"updated":"2023-11-03 18:50:26.000000000","message":"?\n```\n        if six.PY3:\n            json_data \u003d json_data.encode(\u0027utf-8\u0027)\n```\nAnd, of course, on py2 it\u0027s already `bytes`.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":1048,"context_line":""},{"line_number":1049,"context_line":"        :param resp_iter: a response iterable"},{"line_number":1050,"context_line":""},{"line_number":1051,"context_line":"        :returns: the unencoded raw format data"},{"line_number":1052,"context_line":"        \"\"\""},{"line_number":1053,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":1054,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"d39967d5_06a982de","line":1051,"range":{"start_line":1051,"start_character":22,"end_line":1051,"end_character":31},"in_reply_to":"1b4671a2_f50cf82e","updated":"2023-11-04 00:34:58.000000000","message":"looks like chatgpt doc string update to me!\n\n#willfix","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":1069,"context_line":""},{"line_number":1070,"context_line":"    def _get_manifest_read(self, resp_iter):"},{"line_number":1071,"context_line":"        with closing_if_possible(resp_iter):"},{"line_number":1072,"context_line":"            resp_body \u003d b\u0027\u0027.join(resp_iter)"},{"line_number":1073,"context_line":"        try:"},{"line_number":1074,"context_line":"            segments \u003d json.loads(resp_body)"},{"line_number":1075,"context_line":"        except ValueError:"}],"source_content_type":"text/x-python","patch_set":41,"id":"e977693a_cee711a2","line":1072,"updated":"2023-11-03 18:50:26.000000000","message":"Off-topic: We should probably have a length-check here, and 500 if it\u0027s wrong. Then I *think* we could feel pretty good responding 409 if the `json.loads` fails.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":false,"context_lines":[{"line_number":1069,"context_line":""},{"line_number":1070,"context_line":"    def _get_manifest_read(self, resp_iter):"},{"line_number":1071,"context_line":"        with closing_if_possible(resp_iter):"},{"line_number":1072,"context_line":"            resp_body \u003d b\u0027\u0027.join(resp_iter)"},{"line_number":1073,"context_line":"        try:"},{"line_number":1074,"context_line":"            segments \u003d json.loads(resp_body)"},{"line_number":1075,"context_line":"        except ValueError:"}],"source_content_type":"text/x-python","patch_set":41,"id":"59b346a8_7f3558c7","line":1072,"in_reply_to":"6e04bc68_50e78e02","updated":"2023-11-07 19:40:36.000000000","message":"I\u0027ve definitely run into it in my VSAIO: write an SLO via the (encryption-enabled) auth-ful proxy, then try to read it from the no-auth proxy. No amount of retrying will ever make that work...","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":1069,"context_line":""},{"line_number":1070,"context_line":"    def _get_manifest_read(self, resp_iter):"},{"line_number":1071,"context_line":"        with closing_if_possible(resp_iter):"},{"line_number":1072,"context_line":"            resp_body \u003d b\u0027\u0027.join(resp_iter)"},{"line_number":1073,"context_line":"        try:"},{"line_number":1074,"context_line":"            segments \u003d json.loads(resp_body)"},{"line_number":1075,"context_line":"        except ValueError:"}],"source_content_type":"text/x-python","patch_set":41,"id":"6e04bc68_50e78e02","line":1072,"in_reply_to":"e977693a_cee711a2","updated":"2023-11-04 00:34:58.000000000","message":"oh i like that!  I wonder how often we actually have an is_slo manifest that\u0027s really invalid json as opposed to read error...","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":true,"context_lines":[{"line_number":1074,"context_line":"            segments \u003d json.loads(resp_body)"},{"line_number":1075,"context_line":"        except ValueError:"},{"line_number":1076,"context_line":"            msg \u003d \u0027Unable to load SLO manifest\u0027"},{"line_number":1077,"context_line":"            self.slo.logger.exception(msg)"},{"line_number":1078,"context_line":"            raise HTTPServerError(msg)"},{"line_number":1079,"context_line":"        return segments"},{"line_number":1080,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"6c9ac743_c66bb897","line":1077,"updated":"2023-11-03 18:50:26.000000000","message":"Do we really need a traceback here? We already know it\u0027s going to point to `json.loads` -- would it be better to just\n```\nself.logger.error(\u0027%s: %s\u0027, msg, err)\n```\n? OTOH, I suppose it\u0027s weird to have us 500 *without* a traceback...","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":1074,"context_line":"            segments \u003d json.loads(resp_body)"},{"line_number":1075,"context_line":"        except ValueError:"},{"line_number":1076,"context_line":"            msg \u003d \u0027Unable to load SLO manifest\u0027"},{"line_number":1077,"context_line":"            self.slo.logger.exception(msg)"},{"line_number":1078,"context_line":"            raise HTTPServerError(msg)"},{"line_number":1079,"context_line":"        return segments"},{"line_number":1080,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"84fa5db3_f7805a44","line":1077,"in_reply_to":"6c9ac743_c66bb897","updated":"2023-11-04 00:34:58.000000000","message":"yeah I was hoping the traceback might include context from the json deserializer about the document it had and where it broke:\n\n    \u003e\u003e\u003e json.loads(\u0027{\"object\": \"foo\u0027)\n    Traceback (most recent call last):\n      File \"\u003cstdin\u003e\", line 1, in \u003cmodule\u003e\n      File \"/usr/lib/python3.8/json/__init__.py\", line 357, in loads\n        return _default_decoder.decode(s)\n      File \"/usr/lib/python3.8/json/decoder.py\", line 337, in decode\n        obj, end \u003d self.raw_decode(s, idx\u003d_w(s, 0).end())\n      File \"/usr/lib/python3.8/json/decoder.py\", line 353, in raw_decode\n        obj, end \u003d self.scan_once(s, idx)\n    json.decoder.JSONDecodeError: Unterminated string starting at: line 1 column 12 (char 11)\n    \nBut I guess we get as much as we\u0027re going to get from the ValueError as a string:\n\n    \u003e\u003e\u003e e\n    JSONDecodeError(\u0027Unterminated string starting at: line 1 column 12 (char 11)\u0027)\n    \u003e\u003e\u003e \u0027%s\u0027 % e\n    \u0027Unterminated string starting at: line 1 column 12 (char 11)\u0027\n    \nProbably the most useful piece of information in absense of that is the path of the manifest (but we can pull that from the transaction id).\n\n\u003e ? OTOH, I suppose it\u0027s weird to have us 500 without a traceback...\n\nI\u0027d like to check how often this comes up in prod, but I guess we don\u0027t currently log anything!  I guess since the error log line has as much info as the traceback and is less bytes; i\u0027ll change it.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e7588e1a5939c6c9416763fe0363af473f000241","unresolved":false,"context_lines":[{"line_number":1139,"context_line":"            # their Etag/Content Length no longer match the connection"},{"line_number":1140,"context_line":"            # will drop. In this case a 409 Conflict will be logged in"},{"line_number":1141,"context_line":"            # the proxy logs and the user will receive incomplete results."},{"line_number":1142,"context_line":"            raise HTTPConflict(request\u003dreq)"},{"line_number":1143,"context_line":"        return segmented_iter"},{"line_number":1144,"context_line":""},{"line_number":1145,"context_line":""}],"source_content_type":"text/x-python","patch_set":41,"id":"c5a03185_87f5db51","line":1142,"updated":"2023-11-03 18:50:26.000000000","message":"OK so this bubbles up from `_build_resp_iter` through `handle_slo_get_or_head`, through `handle_multipart_get_or_head`, to finally get handled in `__call__` -- but those were basically all tail calls anyway.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":34892,"name":"ASHWIN A NAIR","display_name":"indianwhocodes","email":"nairashwin952013@gmail.com","username":"indianwhocodes","status":"Nvidia"},"change_message_id":"99258dd4f80f30281f9c6acc12d4fd0f86e9eb7f","unresolved":true,"context_lines":[{"line_number":534,"context_line":""},{"line_number":535,"context_line":"def _annotate_segments(segments, logger\u003dNone):"},{"line_number":536,"context_line":"    \"\"\""},{"line_number":537,"context_line":"    Decode any inlined data and update sub_slo-segemtns bytes from content-type"},{"line_number":538,"context_line":"    when available; then annotate segment dicts in segments list with"},{"line_number":539,"context_line":"    \u0027segment_length\u0027"},{"line_number":540,"context_line":""}],"source_content_type":"text/x-python","patch_set":42,"id":"c00a9df5_ef2a79ca","line":537,"updated":"2023-11-06 17:31:39.000000000","message":"nit:?","commit_id":"2c71d8f1302d2618f3efd3ee96e52c2a820c0900"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":true,"context_lines":[{"line_number":534,"context_line":""},{"line_number":535,"context_line":"def _annotate_segments(segments, logger\u003dNone):"},{"line_number":536,"context_line":"    \"\"\""},{"line_number":537,"context_line":"    Decode any inlined data and update sub_slo-segemtns bytes from content-type"},{"line_number":538,"context_line":"    when available; then annotate segment dicts in segments list with"},{"line_number":539,"context_line":"    \u0027segment_length\u0027"},{"line_number":540,"context_line":""}],"source_content_type":"text/x-python","patch_set":42,"id":"7c09e59e_ebe9dcd5","line":537,"in_reply_to":"c00a9df5_ef2a79ca","updated":"2023-11-09 23:25:02.000000000","message":"I can\u0027t tell for sure what you\u0027re nitting.\n\nI\u0027m *guessing* maybe the mixed under score and hyphen in sub_slo-segments?\n\nThat wasn\u0027t exactly unintentional; although I hadn\u0027t considered some people might find it sufficiently asteticly jarring for it to be a distraction.\n\nI prose I found it useful to be able to refer to \"types\" of segments.  I came up the following types with based on their dictionary key:\n\n * data\n * range\n * sub_slo\n \nSo when I wanted to refer unambigously to a segment of a specific type, I\u0027d use a hyphen and call it a:\n\n  * data-segment\n  * range-segment\n  * sub_slo-segment\n  \n... or at least that was the intention; I may not have been consistent.  Maybe your nit was something else entirely?  Regarldess I\u0027d prefer you tell me explicitly how you think this change could be better.","commit_id":"2c71d8f1302d2618f3efd3ee96e52c2a820c0900"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":true,"context_lines":[{"line_number":1062,"context_line":"        :param resp_iter: a response iterable"},{"line_number":1063,"context_line":""},{"line_number":1064,"context_line":"        :raises HTTPServerError:"},{"line_number":1065,"context_line":"        :returns: the json encoded raw format bytes"},{"line_number":1066,"context_line":"        \"\"\""},{"line_number":1067,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":1068,"context_line":""}],"source_content_type":"text/x-python","patch_set":42,"id":"ccc7688c_ce2278c5","line":1065,"range":{"start_line":1065,"start_character":22,"end_line":1065,"end_character":34},"updated":"2023-11-07 19:40:36.000000000","message":"nit: JSON isn\u0027t an encoding; maybe better as \"json-serialized\"?","commit_id":"2c71d8f1302d2618f3efd3ee96e52c2a820c0900"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":false,"context_lines":[{"line_number":1062,"context_line":"        :param resp_iter: a response iterable"},{"line_number":1063,"context_line":""},{"line_number":1064,"context_line":"        :raises HTTPServerError:"},{"line_number":1065,"context_line":"        :returns: the json encoded raw format bytes"},{"line_number":1066,"context_line":"        \"\"\""},{"line_number":1067,"context_line":"        segments \u003d self._get_manifest_read(resp_iter)"},{"line_number":1068,"context_line":""}],"source_content_type":"text/x-python","patch_set":42,"id":"5976fb11_fc7ae1c1","line":1065,"range":{"start_line":1065,"start_character":22,"end_line":1065,"end_character":34},"in_reply_to":"ccc7688c_ce2278c5","updated":"2023-11-09 23:25:02.000000000","message":"Done","commit_id":"2c71d8f1302d2618f3efd3ee96e52c2a820c0900"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a5ca7fb4a7212517b469a6eca7b2aef29f7422e1","unresolved":true,"context_lines":[{"line_number":1038,"context_line":"            return self._return_non_slo_response("},{"line_number":1039,"context_line":"                req, start_response, resp_iter)"},{"line_number":1040,"context_line":"        else:"},{"line_number":1041,"context_line":"            slo_attrs \u003d maybe_slo_attrs"},{"line_number":1042,"context_line":""},{"line_number":1043,"context_line":"        if is_manifest_get:"},{"line_number":1044,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"}],"source_content_type":"text/x-python","patch_set":46,"id":"71377a7f_9c6b2956","line":1041,"updated":"2023-11-09 12:53:46.000000000","message":"So IIUC the renaming correctly, we\u0027re not allowed to *call* it slo_attrs until we tested if is_slo. If we can\u0027t name an instance of SloAttrs ``slo_attrs``, then perhaps the class needs to be renamed to something that sounds less committed to the response being an SLO, like RespAttrs or RespCtxt?\n\nAlternative idea here https://review.opendev.org/c/openstack/swift/+/900518.\nBut, FWIW I was OK with vanilla slo_attrs naming, I don\u0027t want to re-ignite a debate that has been and gone.\n\nThe ``if not maybe_...`` gave me pause :) but we could at least switch the sense of the if/else to avoid that.","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":false,"context_lines":[{"line_number":1038,"context_line":"            return self._return_non_slo_response("},{"line_number":1039,"context_line":"                req, start_response, resp_iter)"},{"line_number":1040,"context_line":"        else:"},{"line_number":1041,"context_line":"            slo_attrs \u003d maybe_slo_attrs"},{"line_number":1042,"context_line":""},{"line_number":1043,"context_line":"        if is_manifest_get:"},{"line_number":1044,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"}],"source_content_type":"text/x-python","patch_set":46,"id":"c185c3c9_81eac8cc","line":1041,"in_reply_to":"71377a7f_9c6b2956","updated":"2023-11-09 23:25:02.000000000","message":"I don\u0027t *think* it was so much about slo_attrs as name, I *think* it was about the easy to miss over-write and the easy to mis-understand double-duty `if not slo_attrs.is_slo` that we explicitly choose NOT to evaulate until after a potential refetch (i.e. guard return noop in need_to_refetch)","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a5ca7fb4a7212517b469a6eca7b2aef29f7422e1","unresolved":true,"context_lines":[{"line_number":1043,"context_line":"        if is_manifest_get:"},{"line_number":1044,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"},{"line_number":1045,"context_line":"            return self._return_manifest_response(req, start_response,"},{"line_number":1046,"context_line":"                                                  resp_iter, is_format_raw)"},{"line_number":1047,"context_line":""},{"line_number":1048,"context_line":"        # this a GET/HEAD response for the SLO object (not the manifest)"},{"line_number":1049,"context_line":"        if self.segment_listing_needed:"}],"source_content_type":"text/x-python","patch_set":46,"id":"57d6133c_ca3c500f","line":1046,"updated":"2023-11-09 12:53:46.000000000","message":"nit: we\u0027re inconsistent in use of ``else:`` after a ``return`` - cf. line 1040\n\nI have *slight* preference to not use the else, but rather leave an empty line to emphasise the return.","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":false,"context_lines":[{"line_number":1043,"context_line":"        if is_manifest_get:"},{"line_number":1044,"context_line":"            # manifest pass through doesn\u0027t require slo_attrs"},{"line_number":1045,"context_line":"            return self._return_manifest_response(req, start_response,"},{"line_number":1046,"context_line":"                                                  resp_iter, is_format_raw)"},{"line_number":1047,"context_line":""},{"line_number":1048,"context_line":"        # this a GET/HEAD response for the SLO object (not the manifest)"},{"line_number":1049,"context_line":"        if self.segment_listing_needed:"}],"source_content_type":"text/x-python","patch_set":46,"id":"aad52c32_20bbb0fa","line":1046,"in_reply_to":"57d6133c_ca3c500f","updated":"2023-11-09 23:25:02.000000000","message":"oic, yeah \"return else:\" does muddy the exits - i\u0027ll watch out for that.","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a5ca7fb4a7212517b469a6eca7b2aef29f7422e1","unresolved":true,"context_lines":[{"line_number":1050,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1051,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1052,"context_line":"            if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":1053,"context_line":"                resp_iter \u003d []"},{"line_number":1054,"context_line":"            else:"},{"line_number":1055,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1056,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"}],"source_content_type":"text/x-python","patch_set":46,"id":"d2ce791c_617c610f","line":1053,"updated":"2023-11-09 12:53:46.000000000","message":"ok! take responsibility for doing the right thing","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5010bd301bd1ddfd82fef5ea47b84e51a1b69fa7","unresolved":true,"context_lines":[{"line_number":1050,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1051,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1052,"context_line":"            if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":1053,"context_line":"                resp_iter \u003d []"},{"line_number":1054,"context_line":"            else:"},{"line_number":1055,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1056,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"}],"source_content_type":"text/x-python","patch_set":46,"id":"fb60db6e_869316ac","line":1053,"in_reply_to":"610e486e_e0a4b7e9","updated":"2023-11-10 15:25:21.000000000","message":"We replace resp_iter at line 1055 as well, with _build_resp_iter return value, so doing it here as well feels \"consistent\" and perhaps helpfully explicit? Meaning, it\u0027s not *necessary* but if I\u0027m wondering what resp_iter is for a HEAD, I either dig into _parse_segments and see that it\u0027s an already closed iter, or I see right here that it\u0027s an empty list.\n\nA comment might not hurt to deal with any smell\n\nat line 1052 (applies to both HEAD and GET)\n```\n# the original resp_iter was closed during _parse_segments\n```","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c8928a5df2a2ec0c0d7ba9e4b67d8dd498e1a793","unresolved":false,"context_lines":[{"line_number":1050,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1051,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1052,"context_line":"            if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":1053,"context_line":"                resp_iter \u003d []"},{"line_number":1054,"context_line":"            else:"},{"line_number":1055,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1056,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"}],"source_content_type":"text/x-python","patch_set":46,"id":"610e486e_e0a4b7e9","line":1053,"in_reply_to":"65166d6c_bc0c5045","updated":"2023-11-09 23:56:31.000000000","message":"But we *have* closed the existing `resp_iter` -- it\u0027s dead to us! It was done a few layers down the stack (in `_get_manifest_read`) but it\u0027s done.","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":false,"context_lines":[{"line_number":1050,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1051,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1052,"context_line":"            if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":1053,"context_line":"                resp_iter \u003d []"},{"line_number":1054,"context_line":"            else:"},{"line_number":1055,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1056,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"}],"source_content_type":"text/x-python","patch_set":46,"id":"65166d6c_bc0c5045","line":1053,"in_reply_to":"d2ce791c_617c610f","updated":"2023-11-09 23:25:02.000000000","message":"honestly at this point replacing resp_iter and not calling friendly_close on our existing resp_iter smells - which is weird since I know swob will just all friendly close on this list anyway.","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"31cda479eb1467047c09f4f607952d82753286f1","unresolved":false,"context_lines":[{"line_number":1050,"context_line":"            segments \u003d self._parse_segments(resp_iter)"},{"line_number":1051,"context_line":"            slo_attrs.update_from_segments(segments)"},{"line_number":1052,"context_line":"            if req.method \u003d\u003d \u0027HEAD\u0027:"},{"line_number":1053,"context_line":"                resp_iter \u003d []"},{"line_number":1054,"context_line":"            else:"},{"line_number":1055,"context_line":"                resp_iter \u003d self._build_resp_iter(req, slo_attrs)"},{"line_number":1056,"context_line":"        return self._return_slo_response(req, start_response, resp_iter,"}],"source_content_type":"text/x-python","patch_set":46,"id":"aed6aecc_77165bc3","line":1053,"in_reply_to":"fb60db6e_869316ac","updated":"2023-11-10 21:45:17.000000000","message":"yes, this is great - the only time resp_iter is the original resp_iter is not segment_listing_needed","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0613b48919984be31da8dc33dd2f62fe81eb8e15","unresolved":true,"context_lines":[{"line_number":1043,"context_line":"        if self._is_manifest_and_need_to_refetch(req, resp_attrs,"},{"line_number":1044,"context_line":"                                                 is_manifest_get):"},{"line_number":1045,"context_line":"            resp_attrs, resp_iter \u003d self._refetch_manifest("},{"line_number":1046,"context_line":"                req, resp_iter, resp_attrs)"},{"line_number":1047,"context_line":""},{"line_number":1048,"context_line":"        if not resp_attrs.is_slo:"},{"line_number":1049,"context_line":"            # even if the original resp_attrs maybe have been SLO we may have"}],"source_content_type":"text/x-python","patch_set":47,"id":"112b9fa6_72943738","line":1046,"updated":"2023-11-10 15:40:45.000000000","message":"if we want to highlight that resp_attrs could be replaced, we could write\n\n```\ndiff --git a/swift/common/middleware/slo.py b/swift/common/middleware/slo.py\nindex b3f50ece6..0f0d4e4f4 100644\n--- a/swift/common/middleware/slo.py\n+++ b/swift/common/middleware/slo.py\n@@ -1039,11 +1039,13 @@ class SloGetContext(WSGIContext):\n\n         # process request and ensure response is from a SLO manifest\n         resp_iter \u003d self._app_call(req.environ)\n-        resp_attrs \u003d RespAttrs.from_headers(self._response_headers)\n-        if self._is_manifest_and_need_to_refetch(req, resp_attrs,\n+        provisional_resp_attrs \u003d RespAttrs.from_headers(self._response_headers)\n+        if self._is_manifest_and_need_to_refetch(req, provisional_resp_attrs,\n                                                  is_manifest_get):\n             resp_attrs, resp_iter \u003d self._refetch_manifest(\n-                req, resp_iter, resp_attrs)\n+                req, resp_iter, provisional_resp_attrs)\n+        else:\n+            resp_attrs \u003d provisional_resp_attrs\n\n         if not resp_attrs.is_slo:\n             # even if the original resp_attrs maybe have been SLO we may have\n```","commit_id":"113d265df0d4c0a0afefce8ed1e813ae71972e96"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"31cda479eb1467047c09f4f607952d82753286f1","unresolved":false,"context_lines":[{"line_number":1043,"context_line":"        if self._is_manifest_and_need_to_refetch(req, resp_attrs,"},{"line_number":1044,"context_line":"                                                 is_manifest_get):"},{"line_number":1045,"context_line":"            resp_attrs, resp_iter \u003d self._refetch_manifest("},{"line_number":1046,"context_line":"                req, resp_iter, resp_attrs)"},{"line_number":1047,"context_line":""},{"line_number":1048,"context_line":"        if not resp_attrs.is_slo:"},{"line_number":1049,"context_line":"            # even if the original resp_attrs maybe have been SLO we may have"}],"source_content_type":"text/x-python","patch_set":47,"id":"296c6cd7_8fdefaf5","line":1046,"in_reply_to":"112b9fa6_72943738","updated":"2023-11-10 21:45:17.000000000","message":"maybe provision_resp_iter!?  Or we could could use a NamedTuple!?\n\nI\u0027m going to write a copy - there\u0027s no way to make those those two calls and their side effects obvious from first reading - we did our best.","commit_id":"113d265df0d4c0a0afefce8ed1e813ae71972e96"}],"swift/common/request_helpers.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"caed97b555062c33e39ca8c6e545607602204090","unresolved":true,"context_lines":[{"line_number":744,"context_line":"            # Spliterator and multi_range_iterator can\u0027t possibly know we\u0027ve"},{"line_number":745,"context_line":"            # consumed the whole of the app_iter, but we want to read/close the"},{"line_number":746,"context_line":"            # final segment response"},{"line_number":747,"context_line":"            friendly_close(self.app_iter)"},{"line_number":748,"context_line":"            self.close()"},{"line_number":749,"context_line":""},{"line_number":750,"context_line":"    def validate_first_segment(self):"}],"source_content_type":"text/x-python","patch_set":36,"id":"016c2bb7_17a9cf0c","line":747,"updated":"2023-10-31 11:27:24.000000000","message":"ok, and we expect nothing to read (just need to trigger the StopIteration), so friendly_close does the job","commit_id":"b351e47b30c7629e2ec28ad838b5745bc88fd21a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"37105331a48b3933ecc80ebb2f908aca1ed077bd","unresolved":true,"context_lines":[{"line_number":744,"context_line":"            # Spliterator and multi_range_iterator can\u0027t possibly know we\u0027ve"},{"line_number":745,"context_line":"            # consumed the whole of the app_iter, but we want to read/close the"},{"line_number":746,"context_line":"            # final segment response"},{"line_number":747,"context_line":"            friendly_close(self.app_iter)"},{"line_number":748,"context_line":"            self.close()"},{"line_number":749,"context_line":""},{"line_number":750,"context_line":"    def validate_first_segment(self):"}],"source_content_type":"text/x-python","patch_set":36,"id":"05d47f92_e41e257f","line":747,"in_reply_to":"016c2bb7_17a9cf0c","updated":"2023-11-02 00:04:11.000000000","message":"...and won\u0027t consume *too much* if there\u0027s some exception that bubbles through us during the `yield`\n\nDo we still need the `self.close()` call, though?\n\nAlternatively, should `SegmentedIterable.close` use `friendly_close` rather than `close_if_possible`? (Would it ever _not_ be possible?)","commit_id":"b351e47b30c7629e2ec28ad838b5745bc88fd21a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"a7d8c2fc64eea9e3cf9bd8860f52c8eb050f9bd2","unresolved":false,"context_lines":[{"line_number":744,"context_line":"            # Spliterator and multi_range_iterator can\u0027t possibly know we\u0027ve"},{"line_number":745,"context_line":"            # consumed the whole of the app_iter, but we want to read/close the"},{"line_number":746,"context_line":"            # final segment response"},{"line_number":747,"context_line":"            friendly_close(self.app_iter)"},{"line_number":748,"context_line":"            self.close()"},{"line_number":749,"context_line":""},{"line_number":750,"context_line":"    def validate_first_segment(self):"}],"source_content_type":"text/x-python","patch_set":36,"id":"80bd191e_c890cce0","line":747,"in_reply_to":"016c2bb7_17a9cf0c","updated":"2023-11-01 23:33:21.000000000","message":"Ack","commit_id":"b351e47b30c7629e2ec28ad838b5745bc88fd21a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"62162178405ef6b8397eca0d015f2ffcab86d1fc","unresolved":false,"context_lines":[{"line_number":744,"context_line":"            # Spliterator and multi_range_iterator can\u0027t possibly know we\u0027ve"},{"line_number":745,"context_line":"            # consumed the whole of the app_iter, but we want to read/close the"},{"line_number":746,"context_line":"            # final segment response"},{"line_number":747,"context_line":"            friendly_close(self.app_iter)"},{"line_number":748,"context_line":"            self.close()"},{"line_number":749,"context_line":""},{"line_number":750,"context_line":"    def validate_first_segment(self):"}],"source_content_type":"text/x-python","patch_set":36,"id":"eba7a1b8_bc8350b5","line":747,"in_reply_to":"05d47f92_e41e257f","updated":"2023-11-02 15:36:53.000000000","message":"the close is totally redundant (and harmless) after adding friendly_close #willfix\n\nI don\u0027t think we should use friendly_close in close because we may be in the middle of the SLO but at the end of the segment and reading a \"just a few more bytes\" could trigger another request for the next segment.","commit_id":"b351e47b30c7629e2ec28ad838b5745bc88fd21a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":744,"context_line":"            # Spliterator and multi_range_iterator can\u0027t possibly know we\u0027ve"},{"line_number":745,"context_line":"            # consumed the whole of the app_iter, but we want to read/close the"},{"line_number":746,"context_line":"            # final segment response"},{"line_number":747,"context_line":"            friendly_close(self.app_iter)"},{"line_number":748,"context_line":"            self.close()"},{"line_number":749,"context_line":""},{"line_number":750,"context_line":"    def validate_first_segment(self):"}],"source_content_type":"text/x-python","patch_set":36,"id":"7ee9002a_22267f2b","line":747,"in_reply_to":"06413409_66d92028","updated":"2023-11-04 00:34:58.000000000","message":"heh, *probably* - unless friendly_close had the good sense to use with_closing?","commit_id":"b351e47b30c7629e2ec28ad838b5745bc88fd21a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"abea0fae72ecac6935e8550c7cf2f114f1190db1","unresolved":true,"context_lines":[{"line_number":744,"context_line":"            # Spliterator and multi_range_iterator can\u0027t possibly know we\u0027ve"},{"line_number":745,"context_line":"            # consumed the whole of the app_iter, but we want to read/close the"},{"line_number":746,"context_line":"            # final segment response"},{"line_number":747,"context_line":"            friendly_close(self.app_iter)"},{"line_number":748,"context_line":"            self.close()"},{"line_number":749,"context_line":""},{"line_number":750,"context_line":"    def validate_first_segment(self):"}],"source_content_type":"text/x-python","patch_set":36,"id":"06413409_66d92028","line":747,"in_reply_to":"eba7a1b8_bc8350b5","updated":"2023-11-03 04:57:24.000000000","message":"\u003e I don\u0027t think we should use friendly_close in close because we may be in the middle of the SLO but at the end of the segment and reading a \"just a few more bytes\" could trigger another request for the next segment.\n\nIn that light, should we write it as\n```\n        try:\n            for x in mri:\n                yield x\n            # Spliterator and multi_range_iterator can\u0027t possibly know we\u0027ve\n            # consumed the whole of the app_iter, but we want to read/close the\n            # final segment response\n            friendly_close(self.app_iter)\n        finally:\n            self.close()\n```\n? With the separation between try/finally, I don\u0027t really mind the double-close.","commit_id":"b351e47b30c7629e2ec28ad838b5745bc88fd21a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"62162178405ef6b8397eca0d015f2ffcab86d1fc","unresolved":true,"context_lines":[{"line_number":496,"context_line":"        self.name \u003d name"},{"line_number":497,"context_line":"        self.response_body_length \u003d response_body_length"},{"line_number":498,"context_line":"        self.peeked_chunk \u003d None"},{"line_number":499,"context_line":"        self.app_iter \u003d self._internal_iter()"},{"line_number":500,"context_line":"        self.validated_first_segment \u003d False"},{"line_number":501,"context_line":"        self.current_resp \u003d None"},{"line_number":502,"context_line":""}],"source_content_type":"text/x-python","patch_set":39,"id":"2a4a65a7_31c9520e","line":499,"updated":"2023-11-02 15:36:53.000000000","message":"for a minute I totally lost where set set app_iter!","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"74de58a3ae58aceac9bd7ae9508506e58211d515","unresolved":false,"context_lines":[{"line_number":496,"context_line":"        self.name \u003d name"},{"line_number":497,"context_line":"        self.response_body_length \u003d response_body_length"},{"line_number":498,"context_line":"        self.peeked_chunk \u003d None"},{"line_number":499,"context_line":"        self.app_iter \u003d self._internal_iter()"},{"line_number":500,"context_line":"        self.validated_first_segment \u003d False"},{"line_number":501,"context_line":"        self.current_resp \u003d None"},{"line_number":502,"context_line":""}],"source_content_type":"text/x-python","patch_set":39,"id":"487ccec3_a550a726","line":499,"in_reply_to":"2a4a65a7_31c9520e","updated":"2023-11-02 15:55:22.000000000","message":"* where we set self.app_iter \u003d _internal_iter","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"}],"swift/common/swob.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"37105331a48b3933ecc80ebb2f908aca1ed077bd","unresolved":true,"context_lines":[{"line_number":1395,"context_line":"            if empty_resp is not None:"},{"line_number":1396,"context_line":"                self.status \u003d empty_resp"},{"line_number":1397,"context_line":"                self.content_length \u003d 0"},{"line_number":1398,"context_line":"                # it\u0027s not obviously reasonable to use friendly_close here, in"},{"line_number":1399,"context_line":"                # the case of a SegmentedIterable reading even a small amount"},{"line_number":1400,"context_line":"                # could trigger additional backend requests."},{"line_number":1401,"context_line":"                close_if_possible(app_iter)"}],"source_content_type":"text/x-python","patch_set":39,"id":"60387567_95edb922","line":1398,"updated":"2023-11-02 00:04:11.000000000","message":"I wonder if it would be possible to enumerate at least *some* cases where it *would* be obviously reasonable to use `friendly_close` -- `self.request.method \u003d\u003d \u0027HEAD\u0027` comes to mind.","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"62162178405ef6b8397eca0d015f2ffcab86d1fc","unresolved":false,"context_lines":[{"line_number":1395,"context_line":"            if empty_resp is not None:"},{"line_number":1396,"context_line":"                self.status \u003d empty_resp"},{"line_number":1397,"context_line":"                self.content_length \u003d 0"},{"line_number":1398,"context_line":"                # it\u0027s not obviously reasonable to use friendly_close here, in"},{"line_number":1399,"context_line":"                # the case of a SegmentedIterable reading even a small amount"},{"line_number":1400,"context_line":"                # could trigger additional backend requests."},{"line_number":1401,"context_line":"                close_if_possible(app_iter)"}],"source_content_type":"text/x-python","patch_set":39,"id":"68b353c7_17fa3d64","line":1398,"in_reply_to":"60387567_95edb922","updated":"2023-11-02 15:36:53.000000000","message":"oh maybe we could make a friendly_close_if_possible that tkaes req \u0026 a resp-iter!?","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"}],"swift/common/utils/__init__.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"37105331a48b3933ecc80ebb2f908aca1ed077bd","unresolved":true,"context_lines":[{"line_number":174,"context_line":"# running that unreasonably small they may find this number inefficient, but in"},{"line_number":175,"context_line":"# the more likely case they\u0027ve increased the value to optimize high througput"},{"line_number":176,"context_line":"# transfers this will still cut off the transfer after the first chunk."},{"line_number":177,"context_line":"DEFAULT_DRAIN_LIMIT \u003d 65536"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"class InvalidHashPathConfigError(ValueError):"}],"source_content_type":"text/x-python","patch_set":39,"id":"7a243276_dd3e73af","line":177,"updated":"2023-11-02 00:04:11.000000000","message":"nit: I\u0027d be partial toward spelling it out a little more -- it\u0027s all the same in the bytecode:\n```\n\u003e\u003e\u003e dis.dis(\u0027x \u003d 65536\u0027)\n  1           0 LOAD_CONST               0 (65536)\n              2 STORE_NAME               0 (x)\n              4 LOAD_CONST               1 (None)\n              6 RETURN_VALUE\n\u003e\u003e\u003e dis.dis(\u0027x \u003d 64 * 2**10\u0027)\n  1           0 LOAD_CONST               0 (65536)\n              2 STORE_NAME               0 (x)\n              4 LOAD_CONST               1 (None)\n              6 RETURN_VALUE\n\u003e\u003e\u003e dis.dis(\u0027x \u003d 2**16\u0027)\n  1           0 LOAD_CONST               0 (65536)\n              2 STORE_NAME               0 (x)\n              4 LOAD_CONST               1 (None)\n              6 RETURN_VALUE\n```","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"62162178405ef6b8397eca0d015f2ffcab86d1fc","unresolved":false,"context_lines":[{"line_number":174,"context_line":"# running that unreasonably small they may find this number inefficient, but in"},{"line_number":175,"context_line":"# the more likely case they\u0027ve increased the value to optimize high througput"},{"line_number":176,"context_line":"# transfers this will still cut off the transfer after the first chunk."},{"line_number":177,"context_line":"DEFAULT_DRAIN_LIMIT \u003d 65536"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"class InvalidHashPathConfigError(ValueError):"}],"source_content_type":"text/x-python","patch_set":39,"id":"5bc732d8_94a6e3f1","line":177,"in_reply_to":"7a243276_dd3e73af","updated":"2023-11-02 15:36:53.000000000","message":"I\u0027m not opposed to defining constants with math, but this style was chosen for consistency:\n\n\t(vagrant-swift-all-in-one) clayg@banana:~/Workspace/vagrant-swift-all-in-one/swift$ grep -R \"64 \\* \" swift\n\tswift/cli/info.py:                data \u003d fp.read(64 * 1024)\n\t(vagrant-swift-all-in-one) clayg@banana:~/Workspace/vagrant-swift-all-in-one/swift$ grep -R \"2 \\*\\* 10 \" swift\n\t(vagrant-swift-all-in-one) clayg@banana:~/Workspace/vagrant-swift-all-in-one/swift$ grep -R 65536 swift\n\tswift/obj/replicator.py:        self.network_chunk_size \u003d int(conf.get(\u0027network_chunk_size\u0027, 65536))\n\tswift/obj/server.py:        self.disk_chunk_size \u003d int(conf.get(\u0027disk_chunk_size\u0027, 65536))\n\tswift/obj/server.py:        self.network_chunk_size \u003d int(conf.get(\u0027network_chunk_size\u0027, 65536))\n\tswift/obj/diskfile.py:def write_metadata(fd, metadata, xattr_size\u003d65536):\n\tswift/obj/diskfile.py:        self.disk_chunk_size \u003d int(conf.get(\u0027disk_chunk_size\u0027, 65536))\n\tswift/obj/reconstructor.py:        self.network_chunk_size \u003d int(conf.get(\u0027network_chunk_size\u0027, 65536))\n\tswift/obj/reconstructor.py:        self.disk_chunk_size \u003d int(conf.get(\u0027disk_chunk_size\u0027, 65536))\n\tswift/proxy/server.py:        self.object_chunk_size \u003d int(conf.get(\u0027object_chunk_size\u0027, 65536))\n\tswift/proxy/server.py:        self.client_chunk_size \u003d int(conf.get(\u0027client_chunk_size\u0027, 65536))\n\tswift/common/middleware/crypto/decrypter.py:DECRYPT_CHUNK_SIZE \u003d 65536\n\tswift/common/utils/__init__.py:        yield (chunk for chunk in iter(lambda: body.read(65536), b\u0027\u0027))\n\tswift/common/ring/ring.py:        inc \u003d int(parts / 65536) or 1","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"abea0fae72ecac6935e8550c7cf2f114f1190db1","unresolved":true,"context_lines":[{"line_number":4034,"context_line":"    if app_iter is None:  # for example, if we used the Response.body property"},{"line_number":4035,"context_line":"        return"},{"line_number":4036,"context_line":"    bytes_read \u003d 0"},{"line_number":4037,"context_line":"    for chunk in app_iter:"},{"line_number":4038,"context_line":"        bytes_read +\u003d len(chunk)"},{"line_number":4039,"context_line":"        if read_limit is not None and bytes_read \u003e\u003d read_limit:"},{"line_number":4040,"context_line":"            break"}],"source_content_type":"text/x-python","patch_set":41,"id":"beee3610_e401d187","line":4037,"updated":"2023-11-03 04:57:24.000000000","message":"So this is pre-existing -- don\u0027t feel like you *have* to address it in this patch -- but I wonder if we\u0027d be happier with something like\n```\ntry:\n    for chunk in app_iter:\n        ...\nfinally:\n    close_if_possible(app_iter)\n```","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":4034,"context_line":"    if app_iter is None:  # for example, if we used the Response.body property"},{"line_number":4035,"context_line":"        return"},{"line_number":4036,"context_line":"    bytes_read \u003d 0"},{"line_number":4037,"context_line":"    for chunk in app_iter:"},{"line_number":4038,"context_line":"        bytes_read +\u003d len(chunk)"},{"line_number":4039,"context_line":"        if read_limit is not None and bytes_read \u003e\u003d read_limit:"},{"line_number":4040,"context_line":"            break"}],"source_content_type":"text/x-python","patch_set":41,"id":"b5c5543e_7b515257","line":4037,"in_reply_to":"beee3610_e401d187","updated":"2023-11-04 00:34:58.000000000","message":"yes, absolutely - good catch","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b66d97c2022dfb90a5c4fd1fdf3644c26b07d4f4","unresolved":true,"context_lines":[{"line_number":4041,"context_line":"    This ensures we don\u0027t log a 499 in the proxy just because we realized we"},{"line_number":4042,"context_line":"    don\u0027t care about the body of an error."},{"line_number":4043,"context_line":"    \"\"\""},{"line_number":4044,"context_line":"    with closing_if_possible(response_or_app_iter):"},{"line_number":4045,"context_line":"        _drain(response_or_app_iter, read_limit\u003dread_limit)"},{"line_number":4046,"context_line":""},{"line_number":4047,"context_line":""}],"source_content_type":"text/x-python","patch_set":42,"id":"352a40ed_109c9113","line":4044,"updated":"2023-11-07 19:40:36.000000000","message":"`swob.Response` doesn\u0027t have a `close` method (maybe it should?)\n\nBut this is why we\u0027ve got all those test failures.","commit_id":"2c71d8f1302d2618f3efd3ee96e52c2a820c0900"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":false,"context_lines":[{"line_number":4041,"context_line":"    This ensures we don\u0027t log a 499 in the proxy just because we realized we"},{"line_number":4042,"context_line":"    don\u0027t care about the body of an error."},{"line_number":4043,"context_line":"    \"\"\""},{"line_number":4044,"context_line":"    with closing_if_possible(response_or_app_iter):"},{"line_number":4045,"context_line":"        _drain(response_or_app_iter, read_limit\u003dread_limit)"},{"line_number":4046,"context_line":""},{"line_number":4047,"context_line":""}],"source_content_type":"text/x-python","patch_set":42,"id":"9651fb25_5fdc345d","line":4044,"in_reply_to":"352a40ed_109c9113","updated":"2023-11-09 23:25:02.000000000","message":"oic, so drain_and_close takes a resonse_or_app_iter, but closing_if_possible takes a maybe_closeable - those are different type unions.  Thank you!","commit_id":"2c71d8f1302d2618f3efd3ee96e52c2a820c0900"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"488fa1a643780c4859325f54d3dc8ffc0336f9ff","unresolved":false,"context_lines":[{"line_number":4034,"context_line":"    if app_iter is None:  # for example, if we used the Response.body property"},{"line_number":4035,"context_line":"        return"},{"line_number":4036,"context_line":"    bytes_read \u003d 0"},{"line_number":4037,"context_line":"    with closing_if_possible(app_iter):"},{"line_number":4038,"context_line":"        for chunk in app_iter:"},{"line_number":4039,"context_line":"            bytes_read +\u003d len(chunk)"},{"line_number":4040,"context_line":"            if read_limit is not None and bytes_read \u003e\u003d read_limit:"}],"source_content_type":"text/x-python","patch_set":46,"id":"9fae0271_c73c6e44","line":4037,"updated":"2023-11-09 23:25:02.000000000","message":"yeah!  that\u0027s what I ment!  😊","commit_id":"16ba57fbfbde518d162e9d02846d494946650e15"}],"swift/common/wsgi.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d4e4d7f773724d659a16a5abd7595cb9b08f7623","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":9,"id":"1b37ffc2_0ff5b86b","line":1115,"updated":"2023-09-17 20:18:06.000000000","message":"this still needs a targeted test","commit_id":"4a376d73d9fd3543ebde5f170f273320122963a5"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9eb6094092ad00e8ec20f41851d54d9c0c7feaa1","unresolved":false,"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":9,"id":"461c45dc_ff1fbe5d","line":1115,"in_reply_to":"1b37ffc2_0ff5b86b","updated":"2023-09-27 20:44:30.000000000","message":"Done","commit_id":"4a376d73d9fd3543ebde5f170f273320122963a5"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e0b850f47ed36970aa6b2e4318b93a0a491e1175","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":21,"id":"8fd01bf6_dc178dbf","line":1115,"updated":"2023-09-29 14:29:51.000000000","message":"+1","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"642a827330c9b11031ca1648cbe62e98fffaefda","unresolved":false,"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":21,"id":"7a072970_6af10eff","line":1115,"in_reply_to":"8fd01bf6_dc178dbf","updated":"2023-09-29 19:52:06.000000000","message":"Ack","commit_id":"a4172f2d7e293c19215426bd8a9112319410d79f"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"37105331a48b3933ecc80ebb2f908aca1ed077bd","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":39,"id":"f88a0b34_643ba230","line":1115,"updated":"2023-11-02 00:04:11.000000000","message":"This feels a little funny -- is there any reason callers *can\u0027t* just call `_get_status_int()`? Alternatively, it doesn\u0027t seem *so* expensive that it can\u0027t be a `@property`...\n\nI guess I\u0027m thinking about someone wanting to get a response, then change the status before returning -- but I guess something like\n```\nctx \u003d WSGIContext(self.app)\napp_iter \u003d ctx._app_call(env)\nctx._response_status \u003d ...\n# ctx._response_status_int is now decoupled!\nstart_response(ctx._response_status, ctx.response_headers)\nreturn app_iter\n```\n*is* kinda awkward...","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"62162178405ef6b8397eca0d015f2ffcab86d1fc","unresolved":false,"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":39,"id":"5d7cbf33_e14cbf05","line":1115,"in_reply_to":"f88a0b34_643ba230","updated":"2023-11-02 15:36:53.000000000","message":"WSGIContext is sort of weird; it holds onto the \"last resp\" values for you - but seems to expect you can keep using it over and over again to _app_call and it just modifies it self each call.  And EVERYTHING seems to be private!?  If someone overwrites _response_headers they become decoupled from _response_status too, and while that\u0027s not obviously good either - I\u0027m not sure I understand the use-case for overwriting *any* of the _response_* attributes?  If you want to return something different than what your last call captured; just return it - why modify the *internal* state first?  Isn\u0027t the leading _ trying to express \"you can read these; don\u0027t change them\"?\n\nThis looked the most consistent to me.  A private *property* feels worse and even easier to miss than the private helper function.\n\nI went ahead and pulled it out (drive-by\u0027s suck) - but now we call _get_status_int() 5 times total and 3 times in the same function over in SLO.  I\u0027ll use a local variable so we only call self._get_status_int() once per-function; but I\u0027m not going to plumb passing around the objects own internal state - if we want to only call self._get_status_int() once we can put it back in here in a follow-up.  Thanks for the discouragemnt!","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"}],"test/unit/common/middleware/test_slo.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":2490,"context_line":"        self._setup_manifest_abcdefghijkl()"},{"line_number":2491,"context_line":""},{"line_number":2492,"context_line":"    def tearDown(self):"},{"line_number":2493,"context_line":"        self.assertEqual(self.app.unclosed_requests, {})"},{"line_number":2494,"context_line":""},{"line_number":2495,"context_line":"    def test_get_manifest_passthrough(self):"},{"line_number":2496,"context_line":"        req \u003d Request.blank("}],"source_content_type":"text/x-python","patch_set":31,"id":"03561402_5c615c16","line":2493,"updated":"2023-10-25 14:57:41.000000000","message":"are we deliberately NOT testing for unread requests here? we\u0027re not calling super.tearDown","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"caed97b555062c33e39ca8c6e545607602204090","unresolved":false,"context_lines":[{"line_number":2490,"context_line":"        self._setup_manifest_abcdefghijkl()"},{"line_number":2491,"context_line":""},{"line_number":2492,"context_line":"    def tearDown(self):"},{"line_number":2493,"context_line":"        self.assertEqual(self.app.unclosed_requests, {})"},{"line_number":2494,"context_line":""},{"line_number":2495,"context_line":"    def test_get_manifest_passthrough(self):"},{"line_number":2496,"context_line":"        req \u003d Request.blank("}],"source_content_type":"text/x-python","patch_set":31,"id":"98528b8e_a2df020c","line":2493,"in_reply_to":"03561402_5c615c16","updated":"2023-10-31 11:27:24.000000000","message":"Done","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6422746d841db395a64231fa2dc9968614731861","unresolved":false,"context_lines":[{"line_number":2490,"context_line":"        self._setup_manifest_abcdefghijkl()"},{"line_number":2491,"context_line":""},{"line_number":2492,"context_line":"    def tearDown(self):"},{"line_number":2493,"context_line":"        self.assertEqual(self.app.unclosed_requests, {})"},{"line_number":2494,"context_line":""},{"line_number":2495,"context_line":"    def test_get_manifest_passthrough(self):"},{"line_number":2496,"context_line":"        req \u003d Request.blank("}],"source_content_type":"text/x-python","patch_set":31,"id":"a4101910_f47f3b7a","line":2493,"in_reply_to":"03561402_5c615c16","updated":"2023-10-31 16:07:22.000000000","message":"i don\u0027t know why i missed this!?  #fixed","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":3088,"context_line":"        # swob is converting the successful non-slo response to conditional"},{"line_number":3089,"context_line":"        # error and closing our unconditionally refetched resp_iter"},{"line_number":3090,"context_line":"        self.expected_unread_requests["},{"line_number":3091,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/big_manifest\u0027)] \u003d 1"},{"line_number":3092,"context_line":""},{"line_number":3093,"context_line":"    def test_old_swift_range_get_beyond_manifest_refetch_big_non_slo(self):"},{"line_number":3094,"context_line":"        # new swift would have ignored the range and got the whole"}],"source_content_type":"text/x-python","patch_set":31,"id":"02feec95_6dd7d6bb","line":3091,"updated":"2023-10-25 14:57:41.000000000","message":"hmmm, this has been added since I last looked at patchset 23, but I can\u0027t see why it wasn\u0027t already true in patchset 23\n\nok, I get it, since patchset 23 this test was moved into a new test case that does NOT override the superclass teardown, so now unread requests are actually being checked in the superclass tearDown()\n\n``TestOldSwiftWithRanges(SloGETorHEADTestCase)``","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":false,"context_lines":[{"line_number":3088,"context_line":"        # swob is converting the successful non-slo response to conditional"},{"line_number":3089,"context_line":"        # error and closing our unconditionally refetched resp_iter"},{"line_number":3090,"context_line":"        self.expected_unread_requests["},{"line_number":3091,"context_line":"            (\u0027GET\u0027, \u0027/v1/AUTH_test/gettest/big_manifest\u0027)] \u003d 1"},{"line_number":3092,"context_line":""},{"line_number":3093,"context_line":"    def test_old_swift_range_get_beyond_manifest_refetch_big_non_slo(self):"},{"line_number":3094,"context_line":"        # new swift would have ignored the range and got the whole"}],"source_content_type":"text/x-python","patch_set":31,"id":"ce1226ec_ee71e332","line":3091,"in_reply_to":"02feec95_6dd7d6bb","updated":"2023-10-26 00:15:45.000000000","message":"the addition of leak track and all the assertions on unread reqeusts have now been moved to the parent patch\n\nhere we \"fix\" the XXX by just changing the unread count from 2 to only 1","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"}],"test/unit/common/test_http.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f0bebf8f36a5c1db603ef76fa667d600be21506","unresolved":true,"context_lines":[{"line_number":18,"context_line":"from swift.common import swob, http"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"class TestHttpHelpers(unittest.TestCase):"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    def test_if_match_mismatch(self):"},{"line_number":24,"context_line":"        req \u003d swob.Request.blank(\u0027/path\u0027, headers\u003d{\u0027If-Match\u0027: \u0027foo\u0027})"}],"source_content_type":"text/x-python","patch_set":31,"id":"3112d697_0defbce9","line":21,"updated":"2023-10-25 14:57:41.000000000","message":"These tests seem to largely cover swob behavior, and possibly duplicate/add to coverage in test_swob. I\u0027d rather see the bulk of these tests in test_swob - that\u0027s where I\u0027d go to understand/verify what swob does.\n\nThe is_* methods in http end up being tested by passing them status ints which doesn\u0027t need the swob req/resp preamble.\n\nIn this module I\u0027d expect to see tests like\n\n```\n    \ndef test_unsatisfiable_range_is_not_conditional_error(self):\n    self.assertFalse(http.is_conditional_error(416))\n    self.assertTrue(http.is_client_error(416))\n\n    \n\n```","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"abb6d41787b43bc1ccf26483e1f0f2f03a98a3cd","unresolved":true,"context_lines":[{"line_number":18,"context_line":"from swift.common import swob, http"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"class TestHttpHelpers(unittest.TestCase):"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    def test_if_match_mismatch(self):"},{"line_number":24,"context_line":"        req \u003d swob.Request.blank(\u0027/path\u0027, headers\u003d{\u0027If-Match\u0027: \u0027foo\u0027})"}],"source_content_type":"text/x-python","patch_set":31,"id":"dbdc2d69_d38aa703","line":21,"in_reply_to":"3112d697_0defbce9","updated":"2023-10-26 00:15:45.000000000","message":"I\u0027m sorry if you found these tests more complicated than you expected at first glance.  I found it useful to include the swob behaviors to \"surround\" the assetsions so it was easier to understand where these status codes really come from.\n\ni.e. what headers get sent, what is considered matching or not - i appreicate that doing so expands the coverage of these behaviors beyond merely the *implementation* of \"is_conditional_error\" - but they were ment to justify the WHY way more than how.\n\nI considered not adding any tests at all - the http module is currently untested;, and I would say reasonably so if all we\u0027ll doing is testing of the most basic implementations - what would be the point?\n\nBut I think \"is_conditional_error\" is a tricky beast, and WHY a 304 is like a 412 shows up when you understand them in the context of how swob\u0027s behavior with them is related.  I had hoped these tests would be useful context for why I want them to live together.\n\nIf these tests aren\u0027t *useful*; we should get rid of them.  If you think because they use swob they can\u0027t exist in this new module; where would you move them?  i.e. why can swob tests import http?  If you think assertTrue(is_success(200)) is a useful unittest for a developer to write we may disagree.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"caed97b555062c33e39ca8c6e545607602204090","unresolved":true,"context_lines":[{"line_number":18,"context_line":"from swift.common import swob, http"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"class TestHttpHelpers(unittest.TestCase):"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    def test_if_match_mismatch(self):"},{"line_number":24,"context_line":"        req \u003d swob.Request.blank(\u0027/path\u0027, headers\u003d{\u0027If-Match\u0027: \u0027foo\u0027})"}],"source_content_type":"text/x-python","patch_set":31,"id":"ae152b0b_bcb4a8e2","line":21,"in_reply_to":"a0aaa270_82000138","updated":"2023-10-31 11:27:24.000000000","message":"I\u0027m not sure how to de-escalate this! I\u0027ve already said it\u0027s not a big deal. It\u0027s not stopping me voting on the patch (the patch had your -1 when I last reviewed).\n\nI also already said I understand how you came to write the tests. They are useful, your effort is not wasted, I have not suggested breaking them apart, I don\u0027t have better tests.\n\nWhen I say \"the \"meat\" of TestHttpHelpers is about swob, I mean, for example: it\u0027s interesting (and not immediately obvious, to me at least, until I\u0027d grokked what behaviours are delegated to swob.Response) that when I construct a swob.Response with status\u003d200 and then use it as an application, I may get back 412 or 304. It\u0027s less interesting that 412 is between 400 and 499 😊. It\u0027s a very significant concept that http.is_unmet_condition(412|304) is True, the tests illustrate/document why, but the code covered by that assertion isn\u0027t so \"meaty\". \n\nLet\u0027s move on.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"a7d8c2fc64eea9e3cf9bd8860f52c8eb050f9bd2","unresolved":false,"context_lines":[{"line_number":18,"context_line":"from swift.common import swob, http"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"class TestHttpHelpers(unittest.TestCase):"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    def test_if_match_mismatch(self):"},{"line_number":24,"context_line":"        req \u003d swob.Request.blank(\u0027/path\u0027, headers\u003d{\u0027If-Match\u0027: \u0027foo\u0027})"}],"source_content_type":"text/x-python","patch_set":31,"id":"bb706415_c743726b","line":21,"in_reply_to":"ae152b0b_bcb4a8e2","updated":"2023-11-01 23:33:21.000000000","message":"Ack","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96235704ef07bcf9f723add0d0358b7085dd4b06","unresolved":true,"context_lines":[{"line_number":18,"context_line":"from swift.common import swob, http"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"class TestHttpHelpers(unittest.TestCase):"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    def test_if_match_mismatch(self):"},{"line_number":24,"context_line":"        req \u003d swob.Request.blank(\u0027/path\u0027, headers\u003d{\u0027If-Match\u0027: \u0027foo\u0027})"}],"source_content_type":"text/x-python","patch_set":31,"id":"a0aaa270_82000138","line":21,"in_reply_to":"c5d50364_b215ddda","updated":"2023-10-28 01:32:43.000000000","message":"ok, I think I hear you now: (re-phrasing)\n\n\u003e the number of \"asserts on swob\" ~\u003d \"asserts on http\"; and obviously the code in http is trivially understood as \"by definition\", so what are the \"asserts on swob\" for?\n\nSomething like that?\n\nWhen I wrote:\n\n        self.assertEqual(304, swob_resp.status_int)  # sanity\n        self.assertTrue(http.is_unmet_condition(swob_resp.status_int))  # explination\n        self.assertEqual(b\u0027\u0027, swob_resp.body)  # justification\n        # N.B.\"304 Not Modified\" is not a \"client_error\"\n        self.assertFalse(http.is_client_error(swob_resp.status_int))  # explination\n\nI hadn\u0027t intended for the \"asserts on swob\" to be \"protecting the behavior of swob\" in anyway, I assume that\u0027s test_swob\u0027s job:\n\nhttps://github.com/NVIDIA/swift/blob/master/test/unit/common/test_swob.py#L1714-L1990\n\nIf swob breaks, swob\u0027s tests should break (if you\u0027re maintaining swob you hopefully wouldn\u0027t even notice if test_http broke until you\u0027ve got test_swob passig).\n\nSimilarlly if someone decides: \"304 isn\u0027t AN *error* WTF!?\" then http\u0027s tests should break - and hopefully guide them to understand the context in which the definition was created before they make the change.\n\nIn this context, the use of swob in setup is designed with non-http experts in mind to ramp up quickly; i.e. \"please accept as a given\"\n\n    If-Match: foo !\u003d Etag: bar \u003d\u003e 412\n\n... hoping to lend such assumptions more authority by using a \"bedrock of ground truth for HTTP\" in swob.  \n\nMaybe I have too much faith in swob.\n\n\u003e I\u0027d rather see the bulk of these tests in test_swob - that\u0027s where I\u0027d go to understand/verify what swob does.\n\nThis seemed to indicate a misundestanding of what I was trying to achive in these tests.  Which in my mind are *entirely* about future maintainers understanding and caring for the defintion I\u0027ve made up about the inherent relationship of 304 and 412 in the http module.  Perhaps my motives (or methods) are questionable - but I\u0027d like to hope they are understandable.\n\n\u003e It\u0027s not a big deal, I was just surprised to find that the \"meat\" of TestHttpHelpers is about swob, and a subset of the helpers.\n\nThis seems to indicate you STILL think these tests are about swob, OR that the other http is_* definitions deserve equal/similar justification.  Again, I\u0027m left feeling my efforts are either wasted or misguided.  If I understand the entirety of your current suggestion: \"move these tests to swob and assert on the ints here\" - I\u0027ll counter that neither moving these tests to swob as is, nor restating the defintions I\u0027ve made up as \"tests\" i.e. `assert 412 in (412, 304)` really helps maintain the definitions in the http module - so I don\u0027t understand the value behind the reason for your suggestion.\n\nI tell what; since it\u0027s not a big deal, I\u0027m going to leave them here mostly as-is for now.  I can see 3 ways I\u0027d want to change them:\n\n1) suggest you understand what I\u0027m trying to do AND show me how to do it better (look if you litter calls to it all over test base it\u0027ll make it *harder* to change!  if the test here is so obvious it looks naive - they\u0027ll think you must REALLY mean it!)\n\n2) suggest you understand what I\u0027m trying to do BUT assure me I don\u0027t need to do it (this is way too much code, the doc strig is sufficient, working slo code is the justification, let the next guy go read the RFCs)\n\nOr 3) tell me you won\u0027t +A unless I put them in a follow-up for further discussion 😜  it\u0027s not like the *code* in is_unmet_condition is going to break unless someone decides the *defintion* is wrong.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d110631b6c6835cee843e209fde32c6bfefab186","unresolved":true,"context_lines":[{"line_number":18,"context_line":"from swift.common import swob, http"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"class TestHttpHelpers(unittest.TestCase):"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    def test_if_match_mismatch(self):"},{"line_number":24,"context_line":"        req \u003d swob.Request.blank(\u0027/path\u0027, headers\u003d{\u0027If-Match\u0027: \u0027foo\u0027})"}],"source_content_type":"text/x-python","patch_set":31,"id":"c5d50364_b215ddda","line":21,"in_reply_to":"dbdc2d69_d38aa703","updated":"2023-10-27 17:44:25.000000000","message":"\u003e I\u0027m sorry if you found these tests more complicated than you expected at first glance.\n\nI haven\u0027t said the tests were complicated.\n\n\u003e If these tests aren\u0027t useful; we should get rid of them. If you think because they use swob they can\u0027t exist in this new module; where would you move them?\n\n\"I\u0027d rather see the bulk of these tests in test_swob - that\u0027s where I\u0027d go to understand/verify what swob does.\"\n\n\u003e why can swob tests import http?\n\nThe tests have to be in one or the other, I have no argument based on what\u0027s imported where. They seem to be making some important assertions about swob, and arguably trivial assertions about http, so on that basis I expected them to be in test_swob.\n\n\u003e If you think assertTrue(is_success(200)) is a useful unittest for a developer to write we may disagree\n\nI haven\u0027t suggested that. But you are effectively here writing ``self.assertTrue(http.is_client_error(412))`` and I have no problem with that.\n\nIt\u0027s not a big deal, I was just surprised to find that the \"meat\" of TestHttpHelpers is about swob, and a subset of the helpers.","commit_id":"6f349861be2cd2caf47f60ea3f02f2fc79cd225a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"37105331a48b3933ecc80ebb2f908aca1ed077bd","unresolved":true,"context_lines":[{"line_number":70,"context_line":"        self.assertFalse(http.is_client_error(swob_resp.status_int))"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def test_if_unmodified_since_modified(self):"},{"line_number":73,"context_line":"        # I can\u0027t think of a use-case for this header on GET?"},{"line_number":74,"context_line":"        req \u003d swob.Request.blank(\u0027/path\u0027, headers\u003d{"},{"line_number":75,"context_line":"            \u0027If-Unmodified-Since\u0027: \u0027Wed, 21 Oct 2015 07:28:00 GMT\u0027})"},{"line_number":76,"context_line":"        resp \u003d swob.Response("}],"source_content_type":"text/x-python","patch_set":39,"id":"a592dd90_58358763","line":73,"updated":"2023-11-02 00:04:11.000000000","message":"Think about a resuming download, if you couldn\u0027t use(/trust) `ETag`s. `If-Unmodified-Since` support is better than nothing.","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"62162178405ef6b8397eca0d015f2ffcab86d1fc","unresolved":false,"context_lines":[{"line_number":70,"context_line":"        self.assertFalse(http.is_client_error(swob_resp.status_int))"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def test_if_unmodified_since_modified(self):"},{"line_number":73,"context_line":"        # I can\u0027t think of a use-case for this header on GET?"},{"line_number":74,"context_line":"        req \u003d swob.Request.blank(\u0027/path\u0027, headers\u003d{"},{"line_number":75,"context_line":"            \u0027If-Unmodified-Since\u0027: \u0027Wed, 21 Oct 2015 07:28:00 GMT\u0027})"},{"line_number":76,"context_line":"        resp \u003d swob.Response("}],"source_content_type":"text/x-python","patch_set":39,"id":"f4b5ec6e_bc4e40ea","line":73,"in_reply_to":"a592dd90_58358763","updated":"2023-11-02 15:36:53.000000000","message":"good one!  #removed","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"37105331a48b3933ecc80ebb2f908aca1ed077bd","unresolved":true,"context_lines":[{"line_number":94,"context_line":"            headers\u003d{\u0027Content-Length\u0027: len(body)},"},{"line_number":95,"context_line":"            # swob can get fancy with bytes or lists of bytes; use iter to"},{"line_number":96,"context_line":"            # force it to trust Content-Length headers"},{"line_number":97,"context_line":"            app_iter\u003diter([body]),"},{"line_number":98,"context_line":"            request\u003dreq,"},{"line_number":99,"context_line":"            # this *is* required to 416; so it\u0027s *kind* of related"},{"line_number":100,"context_line":"            conditional_response\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":39,"id":"9c7a3088_b8ab39c8","line":97,"updated":"2023-11-02 00:04:11.000000000","message":"I don\u0027t get why we care about whether swob has gotten fancy and computed its own `Content-Length` header -- test passes just fine with\n```\ndiff --git a/test/unit/common/test_http.py b/test/unit/common/test_http.py\nindex 1bf094aed..0fdfa0d20 100644\n--- a/test/unit/common/test_http.py\n+++ b/test/unit/common/test_http.py\n@@ -91,10 +91,7 @@ class TestHttpHelpers(unittest.TestCase):\n         body \u003d b\u0027body\u0027\n         resp \u003d swob.Response(\n             status\u003d200,\n-            headers\u003d{\u0027Content-Length\u0027: len(body)},\n-            # swob can get fancy with bytes or lists of bytes; use iter to\n-            # force it to trust Content-Length headers\n-            app_iter\u003diter([body]),\n+            app_iter\u003d[body],\n             request\u003dreq,\n             # this *is* required to 416; so it\u0027s *kind* of related\n             conditional_response\u003dTrue,\n```\napplied and the convolutions are immaterial to the code this file is supposed to be testing.","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"abea0fae72ecac6935e8550c7cf2f114f1190db1","unresolved":false,"context_lines":[{"line_number":94,"context_line":"            headers\u003d{\u0027Content-Length\u0027: len(body)},"},{"line_number":95,"context_line":"            # swob can get fancy with bytes or lists of bytes; use iter to"},{"line_number":96,"context_line":"            # force it to trust Content-Length headers"},{"line_number":97,"context_line":"            app_iter\u003diter([body]),"},{"line_number":98,"context_line":"            request\u003dreq,"},{"line_number":99,"context_line":"            # this *is* required to 416; so it\u0027s *kind* of related"},{"line_number":100,"context_line":"            conditional_response\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":39,"id":"7fb10bd2_89576b41","line":97,"in_reply_to":"3924d923_542edb8d","updated":"2023-11-03 04:57:24.000000000","message":"\u003e The convolutions were ment to make it *more obvoius* this isn\u0027t about \"how swob works\"\n\nThen what is swob doing in here *at all*? I don\u0027t really *want* to re-litigate your thread with Al, but...\n\n\u003e I wanted to demonstrate the range-satisfiable calculation looks at the content-legnth header we (slo) pass into the response object\n\nis **all about** swob and how it works.","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":94,"context_line":"            headers\u003d{\u0027Content-Length\u0027: len(body)},"},{"line_number":95,"context_line":"            # swob can get fancy with bytes or lists of bytes; use iter to"},{"line_number":96,"context_line":"            # force it to trust Content-Length headers"},{"line_number":97,"context_line":"            app_iter\u003diter([body]),"},{"line_number":98,"context_line":"            request\u003dreq,"},{"line_number":99,"context_line":"            # this *is* required to 416; so it\u0027s *kind* of related"},{"line_number":100,"context_line":"            conditional_response\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":39,"id":"4c60c929_15c79ee8","line":97,"in_reply_to":"7fb10bd2_89576b41","updated":"2023-11-04 00:34:58.000000000","message":"AFAIK this test doesn\u0027t exist anymore; so I agree we don\u0027t have ao re-litigate.","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"62162178405ef6b8397eca0d015f2ffcab86d1fc","unresolved":false,"context_lines":[{"line_number":94,"context_line":"            headers\u003d{\u0027Content-Length\u0027: len(body)},"},{"line_number":95,"context_line":"            # swob can get fancy with bytes or lists of bytes; use iter to"},{"line_number":96,"context_line":"            # force it to trust Content-Length headers"},{"line_number":97,"context_line":"            app_iter\u003diter([body]),"},{"line_number":98,"context_line":"            request\u003dreq,"},{"line_number":99,"context_line":"            # this *is* required to 416; so it\u0027s *kind* of related"},{"line_number":100,"context_line":"            conditional_response\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":39,"id":"3924d923_542edb8d","line":97,"in_reply_to":"9c7a3088_b8ab39c8","updated":"2023-11-02 15:36:53.000000000","message":"well, \"immaterial\" WRT to \"how is 412 and 304 related\" - but perhaps relevant to \"why does 416 require conditional_response\u003dTrue but is NOT condition_unmet\" ... and to be fair I don\u0027t know exaclty why conditional_response\u003dTrue is required for range responses?\n\nI guess the reason I wrote it this way is because I didn\u0027t want to dig into how reasonable the swob content-length learning behavior is in order to justify why this test still passes (returns 416):\n\n\tdiff --git a/test/unit/common/test_http.py b/test/unit/common/test_http.py\n\tindex b3af0a969..3de73d95f 100644\n\t--- a/test/unit/common/test_http.py\n\t+++ b/test/unit/common/test_http.py\n\t@@ -90,10 +90,8 @@ class TestHttpHelpers(unittest.TestCase):\n\t\t body \u003d b\u0027body\u0027\n\t\t resp \u003d swob.Response(\n\t\t     status\u003d200,\n\t-            headers\u003d{\u0027Content-Length\u0027: len(body)},\n\t-            # swob can get fancy with bytes or lists of bytes; use iter to\n\t-            # force it to trust Content-Length headers\n\t-            app_iter\u003diter([body]),\n\t+            headers\u003d{\u0027Content-Length\u0027: \u00275050\u0027},\n\t+            body\u003dbody,\n\t\t     request\u003dreq,\n\t\t     # this *is* required to 416; so it\u0027s *kind* of related\n\t\t     conditional_response\u003dTrue,\n\n... but it *seems* that you\u0027re right that:\n\n\tdiff --git a/test/unit/common/test_http.py b/test/unit/common/test_http.py\n\tindex b3af0a969..b3412f93f 100644\n\t--- a/test/unit/common/test_http.py\n\t+++ b/test/unit/common/test_http.py\n\t@@ -90,10 +90,8 @@ class TestHttpHelpers(unittest.TestCase):\n\t\t body \u003d b\u0027body\u0027\n\t\t resp \u003d swob.Response(\n\t\t     status\u003d200,\n\t-            headers\u003d{\u0027Content-Length\u0027: len(body)},\n\t-            # swob can get fancy with bytes or lists of bytes; use iter to\n\t-            # force it to trust Content-Length headers\n\t-            app_iter\u003diter([body]),\n\t+            headers\u003d{\u0027Content-Length\u0027: \u00275050\u0027},\n\t+            app_iter\u003d[body],\n\t\t     request\u003dreq,\n\t\t     # this *is* required to 416; so it\u0027s *kind* of related\n\t\t     conditional_response\u003dTrue,\n\n... would fail in exactly the same way (200 !\u003d 416) had I not wrapped it in iter!?\n\nI was probably being paranoid because I knew swob had code like:\n\nhttps://github.com/NVIDIA/swift/blob/master/swift/common/swob.py#L480\n\n\u003e the convolutions are immaterial\n\nThe convolutions were ment to make it *more obvoius* this isn\u0027t about \"how swob works\" - obviously if we give swob a generator it has to compare the range request header to content-length header - what else could it do!?\n\nThe fact that swob ignores content-length when it calculates it from _body and not when it calculates it from `app_iter\u003d\u003clist\u003e|\u003ctuple\u003e` seems brittle - and I\u0027d like the test to fail if you change the content length or range headers such that they *would* be satisfiable.\n\nI\u0027m not sure you\u0027re really calling for me to remove the iter?  The comment was supposed to justify it.  Do you think passing the iterator instance seems *incorrect*!?  An app_iter from real swift is pretty much *always* a generator; swob accepting a body or learning content_length is just a convienence for tests.  Here I wanted to demonstrate the range-satisfiable calculation looks at the content-legnth header we (slo) pass into the response object; so the way I wrote it felt the \"most real\".","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"37105331a48b3933ecc80ebb2f908aca1ed077bd","unresolved":true,"context_lines":[{"line_number":103,"context_line":"        # I keep getting 416 mixed up with 412"},{"line_number":104,"context_line":"        self.assertEqual(416, swob_resp.status_int)"},{"line_number":105,"context_line":"        # ... but here we do *not* define \"Requested Range Not Satisfiable\""},{"line_number":106,"context_line":"        # as a \"unmet_condition\""},{"line_number":107,"context_line":"        self.assertFalse(http.is_unmet_condition(swob_resp.status_int))"},{"line_number":108,"context_line":"        # for one, it\u0027ll have a body"},{"line_number":109,"context_line":"        self.assertIn(b\u0027Requested Range Not Satisfiable\u0027, swob_resp.body)"}],"source_content_type":"text/x-python","patch_set":39,"id":"2da4e642_6a586118","line":106,"updated":"2023-11-02 00:04:11.000000000","message":"Alternatively, we go pointing at https://www.rfc-editor.org/rfc/rfc9110#section-13.1 for our justification -- I find adherence to a spec way more compelling than comparing against the code we happen to have currently running.\n\nTo that end, it\u0027s probably worth pointing out https://www.rfc-editor.org/rfc/rfc9110#section-15.4.5\n\n\u003e A 304 response is terminated by the end of the header section; it cannot contain content or trailers.\n\nOn a related note, I\u0027m not convinced that 412s MUST return 0-byte bodies -- swob-generated ones do today, but I don\u0027t (yet) see *why*...","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"62162178405ef6b8397eca0d015f2ffcab86d1fc","unresolved":false,"context_lines":[{"line_number":103,"context_line":"        # I keep getting 416 mixed up with 412"},{"line_number":104,"context_line":"        self.assertEqual(416, swob_resp.status_int)"},{"line_number":105,"context_line":"        # ... but here we do *not* define \"Requested Range Not Satisfiable\""},{"line_number":106,"context_line":"        # as a \"unmet_condition\""},{"line_number":107,"context_line":"        self.assertFalse(http.is_unmet_condition(swob_resp.status_int))"},{"line_number":108,"context_line":"        # for one, it\u0027ll have a body"},{"line_number":109,"context_line":"        self.assertIn(b\u0027Requested Range Not Satisfiable\u0027, swob_resp.body)"}],"source_content_type":"text/x-python","patch_set":39,"id":"7524d289_3418cef8","line":106,"in_reply_to":"2da4e642_6a586118","updated":"2023-11-02 15:36:53.000000000","message":"As an \"alternative\" to what exactly?  Where do you want me to add these links?\n\n\u003e On a related note, I\u0027m not convinced that 412s MUST return 0-byte bodies\n\nthat\u0027s a good point; and a big part of my justification for why it\u0027s reasonable to define {412, 304} as \"unmet_condtion\" - maybe this is just something I should do in swob and leave the test_http definition out of it?","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":103,"context_line":"        # I keep getting 416 mixed up with 412"},{"line_number":104,"context_line":"        self.assertEqual(416, swob_resp.status_int)"},{"line_number":105,"context_line":"        # ... but here we do *not* define \"Requested Range Not Satisfiable\""},{"line_number":106,"context_line":"        # as a \"unmet_condition\""},{"line_number":107,"context_line":"        self.assertFalse(http.is_unmet_condition(swob_resp.status_int))"},{"line_number":108,"context_line":"        # for one, it\u0027ll have a body"},{"line_number":109,"context_line":"        self.assertIn(b\u0027Requested Range Not Satisfiable\u0027, swob_resp.body)"}],"source_content_type":"text/x-python","patch_set":39,"id":"324d6472_7ae1b829","line":106,"in_reply_to":"44f50506_d2c0983f","updated":"2023-11-04 00:34:58.000000000","message":"I\u0027m no longer trying to make that definition; the effort to justify and maintain it somehow wasn\u0027t worth the convenience?  If anyone ever again wants to re-learn how 412 and 304 work they\u0027re own their own ;)\n\nThe whole thing may have just been personal learning journey for myself with nothing useful for me to contribute back or pay it forward.  GLHF!","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"abea0fae72ecac6935e8550c7cf2f114f1190db1","unresolved":false,"context_lines":[{"line_number":103,"context_line":"        # I keep getting 416 mixed up with 412"},{"line_number":104,"context_line":"        self.assertEqual(416, swob_resp.status_int)"},{"line_number":105,"context_line":"        # ... but here we do *not* define \"Requested Range Not Satisfiable\""},{"line_number":106,"context_line":"        # as a \"unmet_condition\""},{"line_number":107,"context_line":"        self.assertFalse(http.is_unmet_condition(swob_resp.status_int))"},{"line_number":108,"context_line":"        # for one, it\u0027ll have a body"},{"line_number":109,"context_line":"        self.assertIn(b\u0027Requested Range Not Satisfiable\u0027, swob_resp.body)"}],"source_content_type":"text/x-python","patch_set":39,"id":"44f50506_d2c0983f","line":106,"in_reply_to":"7524d289_3418cef8","updated":"2023-11-03 04:57:24.000000000","message":"\u003e As an \"alternative\" to what exactly?\n\nAs an alternative to having some swob-based justification for `is_unmet_condition` and the tests here!\n\n\u003e  Where do you want me to add these links?\n\nReally, the docstring for `is_unmet_condition` is probably the best place. Honestly, IDK that it even *needs* tests; it\u0027s definitional -- so all the better that they\u0027re gone.","commit_id":"fc94b8004176cc0a1d9cdacdd8e395a2cc1999d2"}],"test/unit/common/test_request_helpers.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"caed97b555062c33e39ca8c6e545607602204090","unresolved":true,"context_lines":[{"line_number":723,"context_line":"        self.app.register(\u0027GET\u0027, \u0027/a/c/seg2\u0027, HTTPOk, {}, \u0027segment2\u0027)"},{"line_number":724,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/mpu\u0027)"},{"line_number":725,"context_line":"        listing_iter \u003d ["},{"line_number":726,"context_line":"            # docstring suggests this is 5-tuple; but this works better"},{"line_number":727,"context_line":"            {\u0027path\u0027: \u0027/a/c/seg1\u0027, \u0027first_byte\u0027: None, \u0027last_byte\u0027: None},"},{"line_number":728,"context_line":"            {\u0027path\u0027: \u0027/a/c/seg2\u0027, \u0027first_byte\u0027: None, \u0027last_byte\u0027: None},"},{"line_number":729,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":36,"id":"3847ec58_c6e1ad55","line":726,"updated":"2023-10-31 11:27:24.000000000","message":"maybe we should fix the docstring","commit_id":"b351e47b30c7629e2ec28ad838b5745bc88fd21a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"a7d8c2fc64eea9e3cf9bd8860f52c8eb050f9bd2","unresolved":false,"context_lines":[{"line_number":723,"context_line":"        self.app.register(\u0027GET\u0027, \u0027/a/c/seg2\u0027, HTTPOk, {}, \u0027segment2\u0027)"},{"line_number":724,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/mpu\u0027)"},{"line_number":725,"context_line":"        listing_iter \u003d ["},{"line_number":726,"context_line":"            # docstring suggests this is 5-tuple; but this works better"},{"line_number":727,"context_line":"            {\u0027path\u0027: \u0027/a/c/seg1\u0027, \u0027first_byte\u0027: None, \u0027last_byte\u0027: None},"},{"line_number":728,"context_line":"            {\u0027path\u0027: \u0027/a/c/seg2\u0027, \u0027first_byte\u0027: None, \u0027last_byte\u0027: None},"},{"line_number":729,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":36,"id":"eb16de86_a6c0b0d6","line":726,"in_reply_to":"1178176a_7d7d3dde","updated":"2023-11-01 23:33:21.000000000","message":"Thank you!","commit_id":"b351e47b30c7629e2ec28ad838b5745bc88fd21a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b98358373ae4bc24388fbed809f94c54751beb6b","unresolved":false,"context_lines":[{"line_number":723,"context_line":"        self.app.register(\u0027GET\u0027, \u0027/a/c/seg2\u0027, HTTPOk, {}, \u0027segment2\u0027)"},{"line_number":724,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/mpu\u0027)"},{"line_number":725,"context_line":"        listing_iter \u003d ["},{"line_number":726,"context_line":"            # docstring suggests this is 5-tuple; but this works better"},{"line_number":727,"context_line":"            {\u0027path\u0027: \u0027/a/c/seg1\u0027, \u0027first_byte\u0027: None, \u0027last_byte\u0027: None},"},{"line_number":728,"context_line":"            {\u0027path\u0027: \u0027/a/c/seg2\u0027, \u0027first_byte\u0027: None, \u0027last_byte\u0027: None},"},{"line_number":729,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":36,"id":"1178176a_7d7d3dde","line":726,"in_reply_to":"3847ec58_c6e1ad55","updated":"2023-10-31 12:28:36.000000000","message":"Done","commit_id":"b351e47b30c7629e2ec28ad838b5745bc88fd21a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"caed97b555062c33e39ca8c6e545607602204090","unresolved":true,"context_lines":[{"line_number":758,"context_line":"            b\u0027segment2\u0027,"},{"line_number":759,"context_line":"            b\u0027--bound--\u0027,"},{"line_number":760,"context_line":"        ])"},{"line_number":761,"context_line":"        self.assertEqual(expected, body)"}],"source_content_type":"text/x-python","patch_set":36,"id":"5bf2e35e_ef86c580","line":761,"updated":"2023-10-31 11:27:24.000000000","message":"nice","commit_id":"b351e47b30c7629e2ec28ad838b5745bc88fd21a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"a7d8c2fc64eea9e3cf9bd8860f52c8eb050f9bd2","unresolved":false,"context_lines":[{"line_number":758,"context_line":"            b\u0027segment2\u0027,"},{"line_number":759,"context_line":"            b\u0027--bound--\u0027,"},{"line_number":760,"context_line":"        ])"},{"line_number":761,"context_line":"        self.assertEqual(expected, body)"}],"source_content_type":"text/x-python","patch_set":36,"id":"233afb45_6d028d42","line":761,"in_reply_to":"5bf2e35e_ef86c580","updated":"2023-11-01 23:33:21.000000000","message":"Ack","commit_id":"b351e47b30c7629e2ec28ad838b5745bc88fd21a"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"abea0fae72ecac6935e8550c7cf2f114f1190db1","unresolved":true,"context_lines":[{"line_number":574,"context_line":"        utils.drain_and_close(g, read_limit\u003d12)"},{"line_number":575,"context_line":"        # this would need *one more* call to next"},{"line_number":576,"context_line":"        self.assertFalse(drained[0])"},{"line_number":577,"context_line":"        self.assertIsNone(g.gi_frame)"},{"line_number":578,"context_line":""},{"line_number":579,"context_line":"        drained \u003d [False]"},{"line_number":580,"context_line":"        # not even close to the whole thing"}],"source_content_type":"text/x-python","patch_set":41,"id":"80536e55_f01d261f","line":577,"updated":"2023-11-03 04:57:24.000000000","message":"I wonder if we could use a helper, for clarity\u0027s sake:\n```\ndef assertGeneratorClosed(self, gen):\n    self.assertIsNone(gen.gi_frame)\n```","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"96ee46711af5982ca5790d4d53bc39b42f46517e","unresolved":false,"context_lines":[{"line_number":574,"context_line":"        utils.drain_and_close(g, read_limit\u003d12)"},{"line_number":575,"context_line":"        # this would need *one more* call to next"},{"line_number":576,"context_line":"        self.assertFalse(drained[0])"},{"line_number":577,"context_line":"        self.assertIsNone(g.gi_frame)"},{"line_number":578,"context_line":""},{"line_number":579,"context_line":"        drained \u003d [False]"},{"line_number":580,"context_line":"        # not even close to the whole thing"}],"source_content_type":"text/x-python","patch_set":41,"id":"00b1bc83_3c12ff40","line":577,"in_reply_to":"80536e55_f01d261f","updated":"2023-11-04 00:34:58.000000000","message":"that\u0027s not bad!  Or have a self.leak_tracking_wrapper(iter) that will will install a CloseCapturingIterator and make sure it gets closed.","commit_id":"03687398a3b2934327377d804e96f9f83fa49257"}]}
