)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"d5a3d0b48159dc830e35c57a8ac7582e8997d901","unresolved":true,"context_lines":[{"line_number":56,"context_line":"See AWS Docs:"},{"line_number":57,"context_line":"https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity-upload.html"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"APIImpact"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Change-Id: I9f6725868019ced6b3b04699c9d7f2649560f036"},{"line_number":62,"context_line":"Co-Authored-by: Clay Gerrard \u003cclay.gerrard@gmail.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":53,"id":"25e1bc53_f30a7ef9","line":59,"updated":"2026-07-23 21:29:19.000000000","message":"during offline discussion, @nmartes@NVIDIA.com brought up a point that MPU upload with checksum specified could run into issue during upgrade \"if a proxy server defines a MPU to have some checksum, then every part uploaded there after must have checksum metadata attached to the parts which is done by the proxy. If a proxy does not know about the requirement of this specific MPU (older version during upgrade), then that proxy won\u0027t put any checksum sysmeta, therefore breaking the MPU\".\n\nOne way to cope with this failure is that MPU completion could report errors back to user and have user to retry it, but user has to upload all the parts for the retry since user doesn\u0027t know which part doesn\u0027t have the checksum. This retry approach is probably acceptable, since s3 checksum is not a popular use case yet. Let\u0027s add this to UpgradeImpact in the commit message.","commit_id":"79f00498f41b051f77303d11504b59676be5fc80"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c3983e2a16b756de8109d90cc8535dcc05e056e1","unresolved":false,"context_lines":[{"line_number":56,"context_line":"See AWS Docs:"},{"line_number":57,"context_line":"https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity-upload.html"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"APIImpact"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Change-Id: I9f6725868019ced6b3b04699c9d7f2649560f036"},{"line_number":62,"context_line":"Co-Authored-by: Clay Gerrard \u003cclay.gerrard@gmail.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":53,"id":"d5856f92_7b0ddfa6","line":59,"in_reply_to":"25e1bc53_f30a7ef9","updated":"2026-07-24 18:24:25.000000000","message":"To ensure that we don\u0027t break legacy clients, we have decided that is it best to NOT enforce checksum metadata when currently in states when a client should be enforced, they are not. I\u0027ll take out the enforcement in this patch, and add another patch that adds a config flag that can add optional enforcement.","commit_id":"79f00498f41b051f77303d11504b59676be5fc80"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8ff438c2b150ab545e4183434c5ee41d79d9653a","unresolved":true,"context_lines":[{"line_number":11,"context_line":"S3API manifest hook. The hook validates the stored values against the"},{"line_number":12,"context_line":"request and calculates a COMPOSITE or FULL_OBJECT checksum."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Use the existing allow_store_checksums option, which defaults to false,"},{"line_number":15,"context_line":"to control final checksum metadata and checksum fields in the completion"},{"line_number":16,"context_line":"response. Keep validation of stored MPU settings active when writes are"},{"line_number":17,"context_line":"disabled. GET and HEAD can still return stored checksums when the client"},{"line_number":18,"context_line":"requests x-amz-checksum-mode: ENABLED."},{"line_number":19,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":155,"id":"c94d0798_bd92fc26","line":16,"range":{"start_line":14,"start_character":0,"end_line":16,"end_character":9},"updated":"2026-11-04 17:27:35.000000000","message":"this needs updating","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":false,"context_lines":[{"line_number":11,"context_line":"S3API manifest hook. The hook validates the stored values against the"},{"line_number":12,"context_line":"request and calculates a COMPOSITE or FULL_OBJECT checksum."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Use the existing allow_store_checksums option, which defaults to false,"},{"line_number":15,"context_line":"to control final checksum metadata and checksum fields in the completion"},{"line_number":16,"context_line":"response. Keep validation of stored MPU settings active when writes are"},{"line_number":17,"context_line":"disabled. GET and HEAD can still return stored checksums when the client"},{"line_number":18,"context_line":"requests x-amz-checksum-mode: ENABLED."},{"line_number":19,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":155,"id":"7c57be4a_f945904d","line":16,"range":{"start_line":14,"start_character":0,"end_line":16,"end_character":9},"in_reply_to":"c94d0798_bd92fc26","updated":"2026-11-06 16:03:43.000000000","message":"Done","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"beb155f5561f41c782c8652a2671e7c06518d34d","unresolved":true,"context_lines":[{"line_number":28,"context_line":"HTTP 400."},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"Read the canonical S3API checksum-value sysmeta name through the existing"},{"line_number":31,"context_line":"sensitive-sysmeta registry. Do not use a checksum-upload-id sentinel. A"},{"line_number":32,"context_line":"part with a missing or empty stored checksum keeps the compatibility"},{"line_number":33,"context_line":"path: complete without a final checksum. Keep the stored lookup"},{"line_number":34,"context_line":"non-raising so that S3 error precedence is preserved."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":155,"id":"76fb9069_240054d9","line":31,"range":{"start_line":31,"start_character":28,"end_line":31,"end_character":69},"updated":"2026-11-05 16:25:23.000000000","message":"This reference to sentinel makes no sense in *git history*.","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":false,"context_lines":[{"line_number":28,"context_line":"HTTP 400."},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"Read the canonical S3API checksum-value sysmeta name through the existing"},{"line_number":31,"context_line":"sensitive-sysmeta registry. Do not use a checksum-upload-id sentinel. A"},{"line_number":32,"context_line":"part with a missing or empty stored checksum keeps the compatibility"},{"line_number":33,"context_line":"path: complete without a final checksum. Keep the stored lookup"},{"line_number":34,"context_line":"non-raising so that S3 error precedence is preserved."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":155,"id":"022ddbb7_f3b69650","line":31,"range":{"start_line":31,"start_character":28,"end_line":31,"end_character":69},"in_reply_to":"76fb9069_240054d9","updated":"2026-11-06 16:03:43.000000000","message":"Done","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"beb155f5561f41c782c8652a2671e7c06518d34d","unresolved":true,"context_lines":[{"line_number":48,"context_line":"UploadPartCopy does not store a checksum for the part it writes, so"},{"line_number":49,"context_line":"CompleteMultipartUpload cannot calculate the final checksum of a"},{"line_number":50,"context_line":"checksum-aware MPU that contains a copied part. The request\u0027s"},{"line_number":51,"context_line":"x-amz-checksum-crc32 header is thus not verified: a correct and a bogus"},{"line_number":52,"context_line":"value both complete with 200, and the object is stored without a"},{"line_number":53,"context_line":"checksum."},{"line_number":54,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":155,"id":"2c3edcac_81ed2932","line":51,"range":{"start_line":51,"start_character":0,"end_line":51,"end_character":21},"updated":"2026-11-05 16:25:23.000000000","message":"inappropriate citation of a specific algorithm","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":false,"context_lines":[{"line_number":48,"context_line":"UploadPartCopy does not store a checksum for the part it writes, so"},{"line_number":49,"context_line":"CompleteMultipartUpload cannot calculate the final checksum of a"},{"line_number":50,"context_line":"checksum-aware MPU that contains a copied part. The request\u0027s"},{"line_number":51,"context_line":"x-amz-checksum-crc32 header is thus not verified: a correct and a bogus"},{"line_number":52,"context_line":"value both complete with 200, and the object is stored without a"},{"line_number":53,"context_line":"checksum."},{"line_number":54,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":155,"id":"48bc8458_f384276a","line":51,"range":{"start_line":51,"start_character":0,"end_line":51,"end_character":21},"in_reply_to":"2c3edcac_81ed2932","updated":"2026-11-06 16:03:43.000000000","message":"Done","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8446d5c28527f906b68ab3bdce4f72c15a7e258d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"f6bbd02a_f7892182","updated":"2026-06-17 23:01:52.000000000","message":"Mainly looking at checksum and schema changes so far, but wanted to post some questions so far.","commit_id":"4a1b6c4dab7d6c288fb59a05129353a0d01e2355"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"feda87b53af26feadcd2f13637ecfc04f382570b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":39,"id":"a467bdaa_2e55ea27","updated":"2026-07-18 01:42:01.000000000","message":"please make sure all the s3api compat tests pass against aws s3 - let me know if you need help getting a session token","commit_id":"65e4364e0b6ff406ca68c14b920a01655b6e9c6c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"121caad55e479d22d843eb8687856636c089e4ac","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":45,"id":"f294a4d3_fd0d6ff0","updated":"2026-07-21 21:06:12.000000000","message":"I don\u0027t think we should add the new interface in the dependend pre-req change if we\u0027re not going to use it.\n\n\n```\n  The mechanism is already there in instances/vsaio-1/swift/swift/common/middleware/slo.py:1519:\n\n  - SLO does its segment HEADs\n  - it calls hook(data_for_storage, segment_head_headers)\n  - if the hook returns problems, SLO appends them to problem_segments\n  - then SLO returns 400 Bad Request instead of storing the manifest at instances/vsaio-1/swift/swift/common/middleware/slo.py:1526\n```\n\nmaybe somethign like:\n\n```\n  callback_error \u003d None\n\n  def checksum_validator(manifest, segment_head_headers):\n      nonlocal callback_error\n      ...\n      if bad_part:\n          callback_error \u003d InvalidPart(upload_id\u003dupload_id, part_number\u003dpn)\n          return [(manifest_item[\u0027name\u0027], \u0027S3API-Callback-InvalidPart\u0027)]\n      return []\n\n  Then in the existing SLO response handling at instances/vsaio-1/swift/swift/common/middleware/s3api/controllers/multi_upload.py:1284, add a branch for the sentinel:\n\n  elif err \u003d\u003d \u0027S3API-Callback-InvalidPart\u0027:\n      raise callback_error\n```\n\n```\n  Right now instances/vsaio-1/swift/swift/common/middleware/s3api/controllers/multi_upload.py:1284 only has explicit remaps for:\n\n  - too-small\n  - Etag Mismatch\n  - 404 Not Found\n\n  Everything else falls through to generic InvalidRequest.\n\n  So if you introduce S3API-Callback-InvalidPart, only s3api needs to be updated to interpret it. SLO can remain oblivious.\n```","commit_id":"ea5a5b85390d0993c07b4b894088921892c89738"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"0cced6023445a9cc3af5e6ed5245765e9953dbb0","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":71,"id":"251483f3_ff1d911b","updated":"2026-08-03 03:51:31.000000000","message":"I had offline discussions with @clay.gerrard@gmail.com and @nmartes@NVIDIA.com, regarding the support of ranged UploadPartCopy in this patch. Basically I found below two cases which would require “recompute checksum for CopyObject|Part\" for MPU checksum persistence to function correctly.\n\n1.  new MPU initiated with checksum:\n current implementation (patchset #58) can’t calculate checksum for UploadPartCopy with s3 x-amz-copy-source-range header, so a ranged UploadPartCopy has to be rejected with 501 NotImplemented as currently implemented, otherwise it would create a new part with wrong inherited checksum. But this also break the backward compatibility: existing users who are doing this got success on prod, but would get 501 back; patchset #71 removed ``501 NotImplemented``, but then this case would run into same issue as case 2.\n \n2. new ordinary MPU initiated without checksum:\nif the source object has stored checksum metadata (created by new checksum full object upload), a ranged UploadPartCopy is allowed with current implementation, and copy middleware copies that full-source checksum metadata onto the partial part. so new MPU could complete without error and it would include a new part with wrong checksum.\n\nplease see those two test cases at: https://review.opendev.org/c/openstack/swift/+/999512, both fail with patchset #71.\n\nsince @nmartes@NVIDIA.com is working on a new follow-up patch to recalculate the checksum for the CopyObject and CopyPart, if we want merge to this patch without checksum re-calculation on copy yet, maybe we can clear checksum sysmeta after a ranged server-side copy and accept ``501 NotImplemented`` for the case 1.","commit_id":"14e87c7e89f8f0c055f5ce74977937d55c8588ad"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"65819a6194cd47a03da59a3ef48271d6ad409bb3","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":71,"id":"89df6247_2da6c1d8","in_reply_to":"251483f3_ff1d911b","updated":"2026-08-03 15:57:27.000000000","message":"I agree with this, if we know we cannot trust the data, then we ought to delete said data. This could also avoid (in the far future) bad listing checksum metadata once we get around to that. I\u0027ll squash these 2 test cases in and purge the checksum metadata on parts that enter an MPU via a UploadPartCopy.","commit_id":"14e87c7e89f8f0c055f5ce74977937d55c8588ad"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c9f6e66eae71acbd0fd46babe8db3ab2931ef7c7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":71,"id":"4ffb6603_3c4dc9f5","in_reply_to":"89df6247_2da6c1d8","updated":"2026-08-03 21:37:20.000000000","message":"I only kept the test cases that handles the approval path but yet still has checksum metadata. The 501 was old behavior. Thanks for it though!","commit_id":"14e87c7e89f8f0c055f5ce74977937d55c8588ad"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"45e2843772a83ce91bb1b21c7897f3f09e8a3c08","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":82,"id":"19dc60fa_209c5863","updated":"2026-08-07 11:23:34.000000000","message":"recheck\n\nUnrelated to this change: 2026-08-07 00:14:51.779897 | controller | {0} openstack.tests.functional.cloud.test_project_cleanup.TestProjectCleanup.test_block_storage_cleanup [96.581629s] ... FAILED","commit_id":"8bf0276dd2a491a1aec9d9d593a189db47331444"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"e77db9068446174a5eef0915dadd1e1b8790f3d7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":85,"id":"a06b7736_7d038a6a","updated":"2026-08-07 22:26:34.000000000","message":"recheck\nopenstacksdk-functional-devstack https://zuul.opendev.org/t/openstack/build/5151b1b04adb454d8f6cbdc2fb642d75 : FAILURE in 50m 17s","commit_id":"c637ac5198af53cc638ba916dc750cadee9bd98b"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"6beb8672d82037259a6fc1bb23f34cf84be83293","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":87,"id":"38af2cdd_c8d5e444","updated":"2026-08-10 11:36:43.000000000","message":"recheck\n\nopenstacksdk-functional-devstack failed due to https://bugs.launchpad.net/cinder/+bug/2163042","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":87,"id":"da82c995_9d1926e9","updated":"2026-08-10 16:59:30.000000000","message":"review-in-progress, comments so far","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":89,"id":"99774789_0dfcfaa6","updated":"2026-08-11 01:06:16.000000000","message":"The changes so far:\n\n- MPU-specific behavior moved into multi_upload.py\n- One ChecksummingInput, checksum_source\u003dNone enables calculation-only mode\n- Controllers explicitly call `persist_request_checksum(checksum_type)`, so validation for MPU specific `S3Request`s lives in the specific application instead of the `S3Request`","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":91,"id":"3423ea46_38ffb54c","updated":"2026-08-12 01:33:28.000000000","message":"Some of a big changes from this new patchset:\n- Encapsulate alot of code into functions to make reading easier\n- Add a MPUChecksumAttrs class to encapulaste checksum rules better\n- Add a _CompleteMultiPartUploadSLOManifestHook class to move the validation closure outside of the inline code\n- Remove redundant usage of `checksum-algorithm` as we can just use the `checksum-header` instead","commit_id":"ae4f90c3e9836e6b397ac84817e1f195cd560cbc"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"eb4ff861e36b482c3709e329ddc204bb2ba75b55","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":93,"id":"43fd868a_51cf0360","updated":"2026-08-13 01:18:56.000000000","message":"Big changes so far:\n- Add more tests\n- Reduce looping in SLO Callback\n- Clean up part checksum lists and make them into dicts\n- Setup the SLO Callback better\n- Add wrapper around get_checksum_hasher","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3e05b45c3062aeed117e41f50c3cdb33487a532d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":94,"id":"f85c5e05_38935849","updated":"2026-08-13 23:44:17.000000000","message":"Added some more tests for heartbeat things and just general compat tests too. Also noticed that we cannot do GetObject with ?partNumber and return checksum meta. This is will be out of this patch because it will need ANOTHER slo hook to get the sysmeta, somewhere later in the chain for sure.","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"010621ef8337f9eae1cb8e1ddaebffafe261c28b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":97,"id":"446e3a8c_6e310d63","updated":"2026-08-14 23:44:06.000000000","message":"Made some small changes and general cleanup,\nstill need to consolidate the compat tests a bit","commit_id":"6a702820d367d1d38e619ed87c00ca19787b0fd5"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"86ec044b89b13c3ed5b751e7f46fe39a7386d858","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":98,"id":"d4093674_001877be","updated":"2026-08-17 15:16:54.000000000","message":"Refactor the compat test suite for MPUs a small bit, throwing some things in classes to make reading eaiser.\n\nAlso added more unit tests too","commit_id":"a3c3c8aab342416d520a57f8787140e525bc3744"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"d537978e6b62f6d030d81d7f58c998e1da51b8dd","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":110,"id":"4c654288_9e70776a","updated":"2026-08-20 21:57:54.000000000","message":"PS109 added some more testing... but... it was really really nitpicky... and it kinda just made our code slower for a not really blocking AWS error handling of BadDigest Vs InvalidRequest...","commit_id":"7430c3b01abc0b05e6fb7b50aa6d18f2a30c43f9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"4005da456d907bb205948b2d39a1e5f5f6595870","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":111,"id":"035020dd_05f365fd","updated":"2026-08-21 00:11:05.000000000","message":"recheck Got some POST_FAILURE","commit_id":"c267f845d6a9aabf1c77afa0ee0008f0aea962a3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"f54331e64f3e82f0fde84e5d6ec5bb8985659ef0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":115,"id":"41b8cd4c_46c36e60","updated":"2026-08-24 22:46:56.000000000","message":"PS 115 clears up some clutter from the compat tests to make sure to only focus on what the test is actually testing, abstracting some setup that happens before the actual tests happens","commit_id":"d306f9c6dea355b3037fe2ef4d5fdeb55d60b70f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"72db134c2bb850d00ef30558ce3f46f441ab5fc9","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":126,"id":"d739ef51_7d871b73","updated":"2026-08-27 22:16:45.000000000","message":"Moved some refactoring of tests out to 1002697: tests: clean up s3api/test_object_checksums | https://review.opendev.org/c/openstack/swift/+/1002697","commit_id":"d4f2f9b2161b37e71f97e29c6f137ff92df5ceda"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"f028158457adc7a1125c30f800ca93156a2011f1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":129,"id":"3b6c2742_93838140","updated":"2026-09-01 15:18:10.000000000","message":"No blockers from my side.\n\nStill thinking about a few minor things, thus only +1 for now - with a tendency for a +2.","commit_id":"3eb67c54ef1b8b8c6ca539c7683e7d5d0cff9657"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0685a51f81f74568ad61287222cdb7a7e76dccdc","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":139,"id":"8792a645_205cea9a","updated":"2026-09-18 10:39:31.000000000","message":"I\u0027m not sure the sentinel is needed, but if it is needed I\u0027d like us to have a single place where the reason is documented","commit_id":"20c59d9bd2d964045ef583798f5b5a931492ffe3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"9644d383c0222ce7513adaa2bcab84934d38a9aa","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":142,"id":"fb893bc7_159f85d4","updated":"2026-09-20 03:20:51.000000000","message":"recheck","commit_id":"78724b28a6a38feb4040ed3edbbdf110e2cbe234"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"752bb337b60f948b147a9d69ad8284f7b5102c0b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":142,"id":"1929f451_7c1c9398","updated":"2026-09-19 21:25:09.000000000","message":"reheck","commit_id":"78724b28a6a38feb4040ed3edbbdf110e2cbe234"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"90eeada1e41b3d853021561a50c4a984dbde8d7c","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":143,"id":"6b0fe34d_1b3be2c3","updated":"2026-10-19 05:06:37.000000000","message":"enabled feature flag and rebased.\nFound two issues with feature flag, will push up fixes after tests passed.","commit_id":"6e458defdb216fff3bffb90fc3c3eb81a0a5e6cb"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"a447c98253911aad8cef2b35b62c79559b2ee787","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":146,"id":"5863b5c1_8b1830a6","updated":"2026-10-22 14:42:53.000000000","message":"Should have been a +1! Close to a +2 though.","commit_id":"3f4cf669533f582ee88099cfe083458a4762a72f"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"927b34a1c220b54026f959fa134b7c082dda9979","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":146,"id":"f912adab_6156530a","updated":"2026-10-22 14:47:18.000000000","message":"Small sq-patch to fix the previous inline comment: 1011887: sq? s3api: Store checksums for CompleteMultipartUpload | https://review.opendev.org/c/openstack/swift/+/1011887","commit_id":"3f4cf669533f582ee88099cfe083458a4762a72f"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"24401abc2518083e871cd82cb108bcbf58ffe20b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":146,"id":"a623db2d_e7e32cff","updated":"2026-10-22 14:42:01.000000000","message":"Tested this patch (and the five parent patches) today on a SAIO, with `allow_store_checksums \u003d true` set and boto3.\n\nLGTM. Each run executed the following tests:\n- put_object\n- upload_file, no checksum arg\n- upload_file, full CRC32 in ExtraArgs\n- upload_file, wrong CRC32\n- put_object, wrong trailer value\n\nTested multiple cases with the following SAIO confics\n- without encryption, http\n- with encryption enabled, http\n- with encryption enabled, https (boto3 sends aws-chunked with a checksum trailer then, not using headers) -\u003e important for prod!","commit_id":"3f4cf669533f582ee88099cfe083458a4762a72f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":146,"id":"18e0faf1_2b6d10c9","updated":"2026-10-22 03:38:52.000000000","message":"refactored lots of test cases to remove duplicates and merge related tests, ~1250 line of code removed.\n```\n7 files changed, 718 insertions(+), 1966 deletions(-)\n```","commit_id":"3f4cf669533f582ee88099cfe083458a4762a72f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"896acfac2d011c73986addab97edae7821a50fe4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":151,"id":"9748b5aa_98d330a0","updated":"2026-11-02 17:03:46.000000000","message":"I\u0027ve mostly started with validating the interaction of the feature flag and end-to-end testing so I can make sure I understand how to use the feature/capabilities.\n\nRegular objects:\n\n```\n# upload\naws s3 cp test s3://s3test/ --checksum-algorithm CRC32C\n# view stored checksum\naws s3api head-object --bucket s3test --key test --checksum-mode ENABLED\n```\n\nMPU:\n```\n# full_object\naws s3 cp prometheus-2.48.1.linux-amd64.tar.gz s3://s3test/ --checksum-algorithm CRC64NVME\n# enabled\nvagrant@vsaio:~$ aws s3api head-object --bucket s3test --key prometheus-2.48.1.linux-amd64.tar.gz --checksum-mode ENABLED                                                                                                                               \n{                                                                                                                                                                                                                                                       \n    \"AcceptRanges\": \"bytes\",                                                                                                                                                                                                                            \n    \"LastModified\": \"Wed, 28 Oct 2026 22:02:38 GMT\",                                                                                                                                                                                                    \n    \"ContentLength\": 96267926,                                                                                                                                                                                                                          \n    \"ChecksumCRC64NVME\": \"Aft6R2+s6QA\u003d\",                                                                                                                                                                                                                \n    \"ChecksumType\": \"FULL_OBJECT\",                                                                                                                                                                                                                      \n    \"ETag\": \"\\\"d69495f99ca81b3982bb679e90eb216b-12\\\"\",                                                                                                                                                                                                  \n    \"ContentType\": \"application/x-tar\",                                                                                                                                                                                                                 \n    \"ServerSideEncryption\": \"AES256\",                                                                                                                                                                                                                   \n    \"Metadata\": {}                                                                                                                                                                                                                                      \n}                                                                                                                                                                                                                                                       \nvagrant@vsaio:~$ anycrc-64nvme \u003c prometheus-2.48.1.linux-amd64.tar.gz | base64                                                                                                                                                                          \nAft6R2+s6QA\u003d                                                                                                                                                                                                                                            \nvagrant@vsaio:~$ type anycrc-64nvme                                                                                                                                                                                                                     \nanycrc-64nvme is aliased to `python3 -c \u0027import anycrc,sys; sys.stdout.buffer.write(anycrc.Model(\"CRC64-NVME\").calc(sys.stdin.buffer.read()).to_bytes(8,\"big\"))\u0027\u0027                                                                                       \n```\n\nchecksums still visible for stored object after disable (if they were originally uploaded with enabled)\n\n```\nvagrant@vsaio:~$ aws s3api head-object --bucket s3test --key prometheus-2.48.1.linux-amd64.tar.gz --checksum-mode ENABLED                                                                                                                               \n{                                                                                                                                                                                                                                                       \n    \"AcceptRanges\": \"bytes\",                                                                                                                                                                                                                            \n    \"LastModified\": \"Wed, 28 Oct 2026 22:02:38 GMT\",                                                                                                                                                                                                    \n    \"ContentLength\": 96267926,                                                                                                                                                                                                                          \n    \"ChecksumCRC64NVME\": \"Aft6R2+s6QA\u003d\",                                                                                    \n    \"ChecksumType\": \"FULL_OBJECT\",                            \n    \"ETag\": \"\\\"d69495f99ca81b3982bb679e90eb216b-12\\\"\",                                                                      \n    \"ContentType\": \"application/x-tar\",                                                                                     \n    \"ServerSideEncryption\": \"AES256\",                                                                                       \n    \"Metadata\": {}                                            \n}                                                             \n```\n\nafter disable, new uploads do not get checksums:\n```\nvagrant@vsaio:~$ aws s3 cp prometheus-2.48.1.linux-amd64.tar.gz s3://s3test/new.tar.gz --checksum-algorithm CRC64NVME                                                                                                                                   \nupload: ./prometheus-2.48.1.linux-amd64.tar.gz to s3://s3test/new.tar.gz                                                                                                                                                                                \nvagrant@vsaio:~$ aws s3api head-object --bucket s3test --key new.tar.gz --checksum-mode ENABLED                                                                                                                                                         \n{                                                             \n    \"AcceptRanges\": \"bytes\",                                  \n    \"LastModified\": \"Mon, 02 Nov 2026 13:23:35 GMT\",                                                                        \n    \"ContentLength\": 96267926,                                \n    \"ETag\": \"\\\"d69495f99ca81b3982bb679e90eb216b-12\\\"\",                                                                      \n    \"ContentType\": \"application/x-tar\",                                                                                     \n    \"ServerSideEncryption\": \"AES256\",                                                                                       \n    \"Metadata\": {}                                            \n}                                                             \n```\n\n\nthe stored checksum only go away after downgrade\n\n```\nvagrant@vsaio:~$ aws s3api head-object --bucket s3test --key test --checksum-mode ENABLED\n{\n    \"AcceptRanges\": \"bytes\",\n    \"LastModified\": \"Wed, 28 Oct 2026 22:01:45 GMT\",\n    \"ContentLength\": 8,\n    \"ETag\": \"\\\"70c1db56f301c9e337b0099bd4174b28\\\"\",\n    \"ContentType\": \"binary/octet-stream\",\n    \"ServerSideEncryption\": \"AES256\",\n    \"Metadata\": {}\n}\n```\n\nand come back after upgrade (even with allow_store_checksums disabled)\n\n```\nvagrant@vsaio:~$ aws s3api head-object --bucket s3test --key test --checksum-mode ENABLED\n{\n    \"AcceptRanges\": \"bytes\",\n    \"LastModified\": \"Wed, 28 Oct 2026 22:01:45 GMT\",\n    \"ContentLength\": 8,\n    \"ChecksumCRC32C\": \"KeWngQ\u003d\u003d\",\n    \"ChecksumType\": \"FULL_OBJECT\",\n    \"ETag\": \"\\\"70c1db56f301c9e337b0099bd4174b28\\\"\",\n    \"ContentType\": \"binary/octet-stream\",\n    \"ServerSideEncryption\": \"AES256\",\n    \"Metadata\": {}\n}\n```\n\nthis gives me a strong sense of confidence in the reasonablness of the approach and the design of the feature-flag as I begin to work through the code more closely.  Very excited about the MPU full_object feature; KUDOS.\n\nN.B. with `allow_store_checksums\u003dtrue` \u0026 aws-cli 1.46.2 I\u0027m getting a stored CRC32 checksum - which I think is just honoring the sdk default:\n\n```\nvagrant@vsaio:~$ aws s3 cp test s3://s3test/test2\nupload: ./test to s3://s3test/test2                            \nvagrant@vsaio:~$ aws s3api head-object --bucket s3test --key test2 --checksum-mode ENABLED\n{\n    \"AcceptRanges\": \"bytes\",\n    \"LastModified\": \"Mon, 02 Nov 2026 13:41:41 GMT\",\n    \"ContentLength\": 8,\n    \"ChecksumCRC32\": \"bfJcxQ\u003d\u003d\",\n    \"ChecksumType\": \"FULL_OBJECT\",\n    \"ETag\": \"\\\"70c1db56f301c9e337b0099bd4174b28\\\"\",\n    \"ContentType\": \"binary/octet-stream\",\n    \"ServerSideEncryption\": \"AES256\",\n    \"Metadata\": {}\n}\nvagrant@vsaio:~$ anycrc-32 \u003c test | base64\nbfJcxQ\u003d\u003d\nvagrant@vsaio:~$ type anycrc-32\nanycrc-32 is aliased to `python3 -c \u0027import anycrc,sys; sys.stdout.buffer.write(anycrc.Model(\"CRC32\").calc(sys.stdin.buffer.read()).to_bytes(4,\"big\"))\u0027\u0027\n```","commit_id":"c0decba0abfe2d2e63d37fe830f7aa12241aa609"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1961762849e2fb744efb2c371a31a34a4ae2255e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":155,"id":"a18d8a21_5f12520a","updated":"2026-11-05 04:05:49.000000000","message":"pushed up a squash patch on \"1014253: sq? Cover MPU checksums after disabling persistence | https://review.opendev.org/c/openstack/swift/+/1014253\"","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":158,"id":"845cadc5_0f62d7c9","updated":"2026-11-06 16:03:43.000000000","message":"-1 for compat tests hiding incompatibility, see squash patch","commit_id":"a9734eb9f2502c0bb44000f71bff578a31e5ccfa"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"b678813fc67d3266f0de26b23224a00b5dda4bb6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":158,"id":"6ccc57a1_c3c399e0","updated":"2026-11-06 17:10:27.000000000","message":"One thing I forgot to mention: I also run all compat tests on AWS at patchset 158 of this patchset, all passing.","commit_id":"a9734eb9f2502c0bb44000f71bff578a31e5ccfa"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"8c7b5400e53bae1ec94e9d8d4a5c5854b2b7a066","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":158,"id":"938f0a63_ec259c03","updated":"2026-11-06 16:55:37.000000000","message":"The +2 is based on my testing of the functionality of the overall changes in the series of the patches since master. I did not read all 10,000 LOC yet.\n\nRun a lot of testing again using the aws CLI, and all the tests succeeded so far. Stumbled upon a few small differences, but no blockers (for example using the AWS docs and trying to use their commands, just being remembered we don\u0027t include checksums in ListParts). For example (works both on AWS and on s3api):\n\n```\n#!/bin/bash\nBUCKETNAME\u003dlistparts-repro-$(date +%s)\nhead -c 5242880 /dev/urandom \u003e /tmp/repro-part.bin\n\naws s3api create-bucket --bucket $BUCKETNAME\n\nUPLOAD_ID\u003d$(aws s3api create-multipart-upload --bucket $BUCKETNAME --key k --checksum-algorithm CRC32 --query UploadId --output text)\naws s3api upload-part --bucket $BUCKETNAME --key k --upload-id \"$UPLOAD_ID\" --part-number 1 --body /tmp/repro-part.bin --checksum-algorithm CRC32 --query \u0027{PartNumber: `1`, ETag: ETag, ChecksumCRC32: ChecksumCRC32}\u0027 --output json \u003e /tmp/repro-part1.json\ncat /tmp/repro-part1.json\n\n# AWS returns the part checksum, s3api not\naws s3api list-parts --bucket $BUCKETNAME --key k --upload-id \"$UPLOAD_ID\" --query \u0027Parts[*].[PartNumber, ChecksumCRC32]\u0027\n\n# Complete from the upload-part answer, not from the listing\nprintf \u0027{\"Parts\": [%s]}\u0027 \"$(cat /tmp/repro-part1.json)\" \u003e /tmp/repro-parts.json\naws s3api complete-multipart-upload --bucket $BUCKETNAME --key k --upload-id \"$UPLOAD_ID\" --multipart-upload file:///tmp/repro-parts.json \u0026\u0026 echo \"RESULT: complete succeeded\" || echo \"RESULT: complete failed\"\n\naws s3api delete-object --bucket $BUCKETNAME --key k\naws s3api delete-bucket --bucket $BUCKETNAME\nrm -f /tmp/repro-part.bin /tmp/repro-part1.json /tmp/repro-parts.json\n```","commit_id":"a9734eb9f2502c0bb44000f71bff578a31e5ccfa"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"f1038a6f072eb4be96ec42eae3cd29d04d25a745","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":158,"id":"3e69a606_63893000","updated":"2026-11-06 11:19:59.000000000","message":"recheck\n\nAre we applying same rate limiting here? tearDownClass in TestObjectChecksumsMPUs failed with \"Please reduce your request rate.\"","commit_id":"a9734eb9f2502c0bb44000f71bff578a31e5ccfa"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"fe0a7f95bf79390cc16c628511941003aa895a2d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":160,"id":"c5db2b8c_1b8559f4","updated":"2026-11-07 03:58:17.000000000","message":"here are the s3api tests results on my vsaio, all three full test/s3api reruns passed:\n```\nTarget\t                Passed\tFailed\tSkipped\nSwift storage enabled\t 634\t    0\t  14\nSwift storage disabled\t553\t    0\t  95\nAWS S3\t                636\t    0\t  12\n```","commit_id":"77cdd92842321d013b81170a98d0a1ca6954a511"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4e57354bcd0d334b06097baa273533e73348ddba","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":160,"id":"31fedc03_c9640232","updated":"2026-11-07 03:58:34.000000000","message":"recheck\nunrelated delete error","commit_id":"77cdd92842321d013b81170a98d0a1ca6954a511"}],"doc/source/s3_compat.rst":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":true,"context_lines":[{"line_number":139,"context_line":"* Validation of an ``x-amz-checksum-*`` value supplied with a"},{"line_number":140,"context_line":"  `Complete Multipart Upload`_ request."},{"line_number":141,"context_line":"  If a part has no stored checksum, or an empty one, completion keeps the"},{"line_number":142,"context_line":"  compatibility behavior. It does not compare a supplied final checksum and"},{"line_number":143,"context_line":"  writes no final checksum. The response has no checksum fields."},{"line_number":144,"context_line":"  Request-format checks still apply."},{"line_number":145,"context_line":""}],"source_content_type":"text/x-rst","patch_set":158,"id":"28a5eb2d_e3639bf2","line":142,"range":{"start_line":142,"start_character":2,"end_line":142,"end_character":24},"updated":"2026-11-06 16:03:43.000000000","message":"In a document that is enumerating AWS S3 compatibility, the \"compatibility behaviour\" can reasonably be expected to mean \"compatible with S3\". That is not what this statement is trying to say.\n\nWith the feature flag, there idea of \"backwards compatibility\" or \"legacy\"  doesn\u0027t apply. There are just MPUs with persisted checksums and MPUs without persisted checksums. SO this should say:\n\n\"If a part has no stored checksum, or an empty one, the completed MPU will not have a persisted checksum.\"\n\nWe could add:\n\n\" This can happen if a part has been created using an `Upload Part Copy`_ request for which part checksum persistence is not yet supported (see below).\"\n\nIn general, I think it is better to be explicit in documents rather than rely on concepts that may not have been well define (like \"compatibility\"), and to assume that the reader of the doc has zero knowledge of the developers\u0027 implementation process and context.","commit_id":"a9734eb9f2502c0bb44000f71bff578a31e5ccfa"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"8c7b5400e53bae1ec94e9d8d4a5c5854b2b7a066","unresolved":true,"context_lines":[{"line_number":156,"context_line":"  `Upload Part Copy`_ requests."},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"* Return of checksum metadata for `List Parts`_ or individual parts in"},{"line_number":159,"context_line":"  `GET Object`_ and `HEAD Object`_ responses."},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"* Inclusion of the per-object checksum algorithm and type in bucket listing"},{"line_number":162,"context_line":"  responses."}],"source_content_type":"text/x-rst","patch_set":158,"id":"1538e316_4ce243a2","line":159,"updated":"2026-11-06 16:55:37.000000000","message":"How about mentioning that clients need to track the part checksums? Sth like\n\n```\nAWS returns the checksum of each part, and the algorithm and the type of the \nupload. Swift returns none of them. A client must keep each part checksum from \nthe `Upload Part`_ response, because a ``COMPOSITE`` completion must repeat it.```","commit_id":"a9734eb9f2502c0bb44000f71bff578a31e5ccfa"}],"etc/proxy-server.conf-sample":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8ff438c2b150ab545e4183434c5ee41d79d9653a","unresolved":true,"context_lines":[{"line_number":636,"context_line":""},{"line_number":637,"context_line":"[filter:s3api]"},{"line_number":638,"context_line":"use \u003d egg:swift#s3api"},{"line_number":639,"context_line":"# Write checksum metadata on a new PUT Object, MPU marker, MPU part, or"},{"line_number":640,"context_line":"# completed MPU."},{"line_number":641,"context_line":"# The default is false."},{"line_number":642,"context_line":"# Enable only after all proxy and internal applications that read, write, or"},{"line_number":643,"context_line":"# copy these objects have the checksum code and old workers have drained."}],"source_content_type":"application/octet-stream","patch_set":155,"id":"2655071b_6ae0c9d0","line":640,"range":{"start_line":639,"start_character":46,"end_line":640,"end_character":16},"updated":"2026-11-04 17:27:35.000000000","message":"this needs updating now that the option iso only potent for CreateMultipartUpload","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1961762849e2fb744efb2c371a31a34a4ae2255e","unresolved":false,"context_lines":[{"line_number":636,"context_line":""},{"line_number":637,"context_line":"[filter:s3api]"},{"line_number":638,"context_line":"use \u003d egg:swift#s3api"},{"line_number":639,"context_line":"# Write checksum metadata on a new PUT Object, MPU marker, MPU part, or"},{"line_number":640,"context_line":"# completed MPU."},{"line_number":641,"context_line":"# The default is false."},{"line_number":642,"context_line":"# Enable only after all proxy and internal applications that read, write, or"},{"line_number":643,"context_line":"# copy these objects have the checksum code and old workers have drained."}],"source_content_type":"application/octet-stream","patch_set":155,"id":"ec43577e_8fbf5770","line":640,"range":{"start_line":639,"start_character":46,"end_line":640,"end_character":16},"in_reply_to":"2655071b_6ae0c9d0","updated":"2026-11-05 04:05:49.000000000","message":"Done","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":true,"context_lines":[{"line_number":636,"context_line":""},{"line_number":637,"context_line":"[filter:s3api]"},{"line_number":638,"context_line":"use \u003d egg:swift#s3api"},{"line_number":639,"context_line":"# Write checksum metadata on a new PUT Object or a new MPU marker."},{"line_number":640,"context_line":"# An MPU with stored checksum settings stores and returns part and final"},{"line_number":641,"context_line":"# checksums, also when this option is false on a later proxy. A final"},{"line_number":642,"context_line":"# checksum needs a stored checksum for each part."}],"source_content_type":"application/octet-stream","patch_set":158,"id":"915dfbb8_09fb0dda","line":639,"updated":"2026-11-06 16:03:43.000000000","message":"this should probably come later in this section, *after* the \u0027s3api setup\u0027 test starting at line 654","commit_id":"a9734eb9f2502c0bb44000f71bff578a31e5ccfa"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":true,"context_lines":[{"line_number":646,"context_line":"# Legacy MPUs can complete with checksum request fields, but do not compare"},{"line_number":647,"context_line":"# or store them, with this option on or off. Request-format checks still apply."},{"line_number":648,"context_line":"# To disable, first set this option to false on all proxies. This stops new"},{"line_number":649,"context_line":"# checksum MPUs. Then complete or abort existing checksum MPUs on proxies that"},{"line_number":650,"context_line":"# have the checksum code. Existing checksum reads, registration, decryption,"},{"line_number":651,"context_line":"# and COPY cleanup continue."},{"line_number":652,"context_line":"# allow_store_checksums \u003d false"},{"line_number":653,"context_line":""}],"source_content_type":"application/octet-stream","patch_set":158,"id":"5ed17314_e4db9edc","line":650,"range":{"start_line":649,"start_character":17,"end_line":650,"end_character":26},"updated":"2026-11-06 16:03:43.000000000","message":"an operator cannot achieve this, the clients own the state of in progress MPUs.\n\nWhy is this step necessary?","commit_id":"a9734eb9f2502c0bb44000f71bff578a31e5ccfa"}],"swift/common/middleware/s3api/controllers/multi_upload.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"e89ffae954e5275be6b65dc44d252490f44e3150","unresolved":false,"context_lines":[{"line_number":760,"context_line":"            last_part \u003d os.path.basename(o[\u0027name\u0027])"},{"line_number":761,"context_line":""},{"line_number":762,"context_line":"        part_checksums \u003d {}"},{"line_number":763,"context_line":"        # For checksum-aware MPUs (those that have checksum fields in the manifest),"},{"line_number":764,"context_line":"        # We will perform more work on them to gather per part checksum metadata"},{"line_number":765,"context_line":"        if marker_checksum_elem_name:"},{"line_number":766,"context_line":"            for obj in objList:"}],"source_content_type":"text/x-python","patch_set":4,"id":"2d165149_830a26b9","line":763,"updated":"2026-06-15 23:30:07.000000000","message":"pep8: E501 line too long (84 \u003e 79 characters)","commit_id":"60954b871ad9a5512db943421bae279e3a9976ec"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"e89ffae954e5275be6b65dc44d252490f44e3150","unresolved":false,"context_lines":[{"line_number":761,"context_line":""},{"line_number":762,"context_line":"        part_checksums \u003d {}"},{"line_number":763,"context_line":"        # For checksum-aware MPUs (those that have checksum fields in the manifest),"},{"line_number":764,"context_line":"        # We will perform more work on them to gather per part checksum metadata"},{"line_number":765,"context_line":"        if marker_checksum_elem_name:"},{"line_number":766,"context_line":"            for obj in objList:"},{"line_number":767,"context_line":"                # Since checksum data is stored as sysmeta, we need to HEAD"}],"source_content_type":"text/x-python","patch_set":4,"id":"b3f4b6de_95d9659e","line":764,"updated":"2026-06-15 23:30:07.000000000","message":"pep8: E501 line too long (80 \u003e 79 characters)","commit_id":"60954b871ad9a5512db943421bae279e3a9976ec"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"b53513f3818aef36f2fec896eb2a7b318446eaa6","unresolved":false,"context_lines":[{"line_number":66,"context_line":"import time"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"from swift.common import constraints"},{"line_number":69,"context_line":"from swift.common.swob import Range, bytes_to_wsgi, normalize_etag, \\"},{"line_number":70,"context_line":"    wsgi_quote, wsgi_to_str, parse_date_header"},{"line_number":71,"context_line":"from swift.common.utils import json, public, reiterate, md5"},{"line_number":72,"context_line":"from swift.common.utils.timestamp import Timestamp, NormalTimestamp"}],"source_content_type":"text/x-python","patch_set":33,"id":"2e2634aa_0c05bdad","line":69,"updated":"2026-07-16 17:00:17.000000000","message":"pep8: F401 \u0027swift.common.swob.parse_date_header\u0027 imported but unused","commit_id":"6a22cf9103f29e484435b2c89d718bc61c9adc0f"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"b53513f3818aef36f2fec896eb2a7b318446eaa6","unresolved":false,"context_lines":[{"line_number":134,"context_line":"    \"\"\""},{"line_number":135,"context_line":"    checksum_hasher \u003d _checksum_hasher_from_header(checksum_header)"},{"line_number":136,"context_line":"    try:"},{"line_number":137,"context_line":"        return strict_b64decode("},{"line_number":138,"context_line":"            checksum_value,"},{"line_number":139,"context_line":"            exact_size\u003dint(checksum_hasher.digest_size),"},{"line_number":140,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":33,"id":"2095cfca_790e78e1","line":137,"updated":"2026-07-16 17:00:17.000000000","message":"pep8: F821 undefined name \u0027strict_b64decode\u0027","commit_id":"6a22cf9103f29e484435b2c89d718bc61c9adc0f"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"b53513f3818aef36f2fec896eb2a7b318446eaa6","unresolved":false,"context_lines":[{"line_number":176,"context_line":"    checksum_hasher \u003d _checksum_hasher_from_header(checksum_header)"},{"line_number":177,"context_line":"    checksum_hasher.update(b\u0027\u0027.join(part_checksum_values))"},{"line_number":178,"context_line":"    return \u0027%s-%d\u0027 % ("},{"line_number":179,"context_line":"        base64_str(checksum_hasher.digest()),"},{"line_number":180,"context_line":"        len(part_checksum_values))"},{"line_number":181,"context_line":""},{"line_number":182,"context_line":""}],"source_content_type":"text/x-python","patch_set":33,"id":"2dc8e822_9f7943fe","line":179,"updated":"2026-07-16 17:00:17.000000000","message":"pep8: F821 undefined name \u0027base64_str\u0027","commit_id":"6a22cf9103f29e484435b2c89d718bc61c9adc0f"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"b53513f3818aef36f2fec896eb2a7b318446eaa6","unresolved":false,"context_lines":[{"line_number":206,"context_line":"            raise S3NotImplemented("},{"line_number":207,"context_line":"                \u0027The %s algorithm is not supported for full object checksum \u0027"},{"line_number":208,"context_line":"                \u0027calculation.\u0027 % checksum_header)"},{"line_number":209,"context_line":"    return base64_str(crc.to_bytes(checksum_hasher.width // 8, \u0027big\u0027))"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"def _complete_request_checksum(req):"}],"source_content_type":"text/x-python","patch_set":33,"id":"155d532e_e90f6ba5","line":209,"updated":"2026-07-16 17:00:17.000000000","message":"pep8: F821 undefined name \u0027base64_str\u0027","commit_id":"6a22cf9103f29e484435b2c89d718bc61c9adc0f"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"e2628269dabc4c493ef10d54716317995cda52ed","unresolved":false,"context_lines":[{"line_number":417,"context_line":"                            expected_checksum_algorithm.lower(),"},{"line_number":418,"context_line":"                            actual_checksum_algorithm.lower()))"},{"line_number":419,"context_line":"            elif checksum_type \u003d\u003d CHECKSUM_TYPE_FULL_OBJECT:"},{"line_number":420,"context_line":"                # In S3 land, the user does NOT have to send the x-amz-checksum-*"},{"line_number":421,"context_line":"                # header IF the MPU is a FULL_OBJECT MPU."},{"line_number":422,"context_line":"                req.calculate_checksum_metadata(checksum_header)"},{"line_number":423,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":40,"id":"bf160a21_1659fd1e","line":420,"updated":"2026-07-20 20:58:14.000000000","message":"pep8: E501 line too long (81 \u003e 79 characters)","commit_id":"6e74348aa3675a298f703afd782f3c6db2b60a56"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"e2628269dabc4c493ef10d54716317995cda52ed","unresolved":false,"context_lines":[{"line_number":1097,"context_line":"                                actual_checksum_header)"},{"line_number":1098,"context_line":"                        if checksum_aware_composite:"},{"line_number":1099,"context_line":"                            # Again with the case of enforcing client checksum"},{"line_number":1100,"context_line":"                            # headers in COMPOSITE mode but not in FULL_OBJECT mode"},{"line_number":1101,"context_line":"                            raise InvalidPart(upload_id\u003dupload_id,"},{"line_number":1102,"context_line":"                                              part_number\u003dpart_number,"},{"line_number":1103,"context_line":"                                              e_tag\u003detag)"}],"source_content_type":"text/x-python","patch_set":40,"id":"dfe64334_4421c134","line":1100,"updated":"2026-07-20 20:58:14.000000000","message":"pep8: E501 line too long (83 \u003e 79 characters)","commit_id":"6e74348aa3675a298f703afd782f3c6db2b60a56"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"121caad55e479d22d843eb8687856636c089e4ac","unresolved":true,"context_lines":[{"line_number":1144,"context_line":"                try:"},{"line_number":1145,"context_line":"                    part_resp \u003d req.get_response("},{"line_number":1146,"context_line":"                        self.app, \u0027HEAD\u0027, container\u003dcontainer,"},{"line_number":1147,"context_line":"                        obj\u003dbytes_to_wsgi(part_obj.encode(\u0027utf-8\u0027)))"},{"line_number":1148,"context_line":"                except NoSuchKey:"},{"line_number":1149,"context_line":"                    raise InvalidPart(upload_id\u003dupload_id,"},{"line_number":1150,"context_line":"                                      part_number\u003dpart_number)"}],"source_content_type":"text/x-python","patch_set":45,"id":"4b992726_4ea44e68","line":1147,"updated":"2026-07-21 21:06:12.000000000","message":"- In CompleteMultipartUpload, it still does explicit per-part HEADs itself at instances/vsaio-1/swift/swift/common/middleware/s3api/controllers/multi_upload.py:1144 through instances/vsaio-1/swift/swift/common/middleware/s3api/controllers/\n    multi_upload.py:1179.\n\n... we all think these \"do the heads before we PUT the manifest and SLO does the same HEADs again\" is *BAD* right?","commit_id":"ea5a5b85390d0993c07b4b894088921892c89738"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"0f4e350c722111d9815f8d19293990cb20bbf59a","unresolved":false,"context_lines":[{"line_number":1144,"context_line":"                try:"},{"line_number":1145,"context_line":"                    part_resp \u003d req.get_response("},{"line_number":1146,"context_line":"                        self.app, \u0027HEAD\u0027, container\u003dcontainer,"},{"line_number":1147,"context_line":"                        obj\u003dbytes_to_wsgi(part_obj.encode(\u0027utf-8\u0027)))"},{"line_number":1148,"context_line":"                except NoSuchKey:"},{"line_number":1149,"context_line":"                    raise InvalidPart(upload_id\u003dupload_id,"},{"line_number":1150,"context_line":"                                      part_number\u003dpart_number)"}],"source_content_type":"text/x-python","patch_set":45,"id":"3010f128_34e99007","line":1147,"in_reply_to":"4b992726_4ea44e68","updated":"2026-07-21 21:50:26.000000000","message":"Yep! But now its removed!","commit_id":"ea5a5b85390d0993c07b4b894088921892c89738"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"121caad55e479d22d843eb8687856636c089e4ac","unresolved":true,"context_lines":[{"line_number":1231,"context_line":"        too_small_message \u003d (\u0027s3api requires that each segment be at least \u0027"},{"line_number":1232,"context_line":"                             \u0027%d bytes\u0027 % self.conf.min_segment_size)"},{"line_number":1233,"context_line":""},{"line_number":1234,"context_line":"        def size_checker(manifest, _segment_head_headers):"},{"line_number":1235,"context_line":"            # Check the size of each segment except the last and make sure"},{"line_number":1236,"context_line":"            # they are all more than the minimum upload chunk size."},{"line_number":1237,"context_line":"            # Note that we need to use the *internal* keys, since we\u0027re"}],"source_content_type":"text/x-python","patch_set":45,"id":"3c48393c_f731f4e8","line":1234,"updated":"2026-07-21 21:06:12.000000000","message":"do we still not USE `_segment_head_headers`!?","commit_id":"ea5a5b85390d0993c07b4b894088921892c89738"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"0f4e350c722111d9815f8d19293990cb20bbf59a","unresolved":false,"context_lines":[{"line_number":1231,"context_line":"        too_small_message \u003d (\u0027s3api requires that each segment be at least \u0027"},{"line_number":1232,"context_line":"                             \u0027%d bytes\u0027 % self.conf.min_segment_size)"},{"line_number":1233,"context_line":""},{"line_number":1234,"context_line":"        def size_checker(manifest, _segment_head_headers):"},{"line_number":1235,"context_line":"            # Check the size of each segment except the last and make sure"},{"line_number":1236,"context_line":"            # they are all more than the minimum upload chunk size."},{"line_number":1237,"context_line":"            # Note that we need to use the *internal* keys, since we\u0027re"}],"source_content_type":"text/x-python","patch_set":45,"id":"2f7036ec_5cc34b43","line":1234,"in_reply_to":"3c48393c_f731f4e8","updated":"2026-07-21 21:50:26.000000000","message":"Just added support in patchset 46, https://review.opendev.org/c/openstack/swift/+/993193/46\nDid not get time yesterday, so this was a today problem 🫡, but is done now!","commit_id":"ea5a5b85390d0993c07b4b894088921892c89738"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"542755814d1430bce54dfa234087f3f44f45c980","unresolved":false,"context_lines":[{"line_number":1263,"context_line":""},{"line_number":1264,"context_line":"        req.environ[\u0027swift.callback.slo_manifest_hook\u0027] \u003d manifest_hook"},{"line_number":1265,"context_line":""},{"line_number":1266,"context_line":"        # SLO invokes the manifest hook before issuing the downstream manifest PUT."},{"line_number":1267,"context_line":"        # By the time the object controller requests footers for that PUT, the hook"},{"line_number":1268,"context_line":"        # has populated the completed-object checksum metadata."},{"line_number":1269,"context_line":"        if checksum_aware_mpu:"}],"source_content_type":"text/x-python","patch_set":46,"id":"3fb822b2_5da57e2d","line":1266,"updated":"2026-07-21 21:48:30.000000000","message":"pep8: E501 line too long (83 \u003e 79 characters)","commit_id":"9db306baff7d7b1f9aef55ea55007219b7cdc3fc"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"542755814d1430bce54dfa234087f3f44f45c980","unresolved":false,"context_lines":[{"line_number":1264,"context_line":"        req.environ[\u0027swift.callback.slo_manifest_hook\u0027] \u003d manifest_hook"},{"line_number":1265,"context_line":""},{"line_number":1266,"context_line":"        # SLO invokes the manifest hook before issuing the downstream manifest PUT."},{"line_number":1267,"context_line":"        # By the time the object controller requests footers for that PUT, the hook"},{"line_number":1268,"context_line":"        # has populated the completed-object checksum metadata."},{"line_number":1269,"context_line":"        if checksum_aware_mpu:"},{"line_number":1270,"context_line":"            original_update_footers \u003d req.environ.get("}],"source_content_type":"text/x-python","patch_set":46,"id":"9c59a703_0a004252","line":1267,"updated":"2026-07-21 21:48:30.000000000","message":"pep8: E501 line too long (83 \u003e 79 characters)","commit_id":"9db306baff7d7b1f9aef55ea55007219b7cdc3fc"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"542755814d1430bce54dfa234087f3f44f45c980","unresolved":false,"context_lines":[{"line_number":1269,"context_line":"        if checksum_aware_mpu:"},{"line_number":1270,"context_line":"            original_update_footers \u003d req.environ.get("},{"line_number":1271,"context_line":"                \u0027swift.callback.update_footers\u0027)"},{"line_number":1272,"context_line":"            def update_footers(footers):"},{"line_number":1273,"context_line":"                if original_update_footers:"},{"line_number":1274,"context_line":"                    original_update_footers(footers)"},{"line_number":1275,"context_line":"                footers.update(footer_metadata)"}],"source_content_type":"text/x-python","patch_set":46,"id":"c67e99a4_624bcb12","line":1272,"updated":"2026-07-21 21:48:30.000000000","message":"pep8: E306 expected 1 blank line before a nested definition, found 0","commit_id":"9db306baff7d7b1f9aef55ea55007219b7cdc3fc"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1bf8d7fe1db8a32411f51d3a32080a5db91b8745","unresolved":false,"context_lines":[{"line_number":1004,"context_line":""},{"line_number":1005,"context_line":"                if part_number \u003c\u003d previous_number:"},{"line_number":1006,"context_line":"                    raise InvalidPartOrder(upload_id\u003dupload_id)"},{"line_number":1007,"context_line":"                # For MPUs with COMPOSITE checksums, we need to make sure the client"},{"line_number":1008,"context_line":"                # defined parts in order consecutively, if not, fallback"},{"line_number":1009,"context_line":"                if part_number !\u003d previous_number + 1:"},{"line_number":1010,"context_line":"                    consecutive_part_numbers \u003d False"}],"source_content_type":"text/x-python","patch_set":54,"id":"20948892_7e205dc7","line":1007,"updated":"2026-07-27 16:48:49.000000000","message":"pep8: E501 line too long (84 \u003e 79 characters)","commit_id":"ec149cf11a388d06847beeb09b7f69ce02d59b13"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"8eb6be141bdece167ad811e656af1bc4b352882e","unresolved":false,"context_lines":[{"line_number":1210,"context_line":"                    sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027))"},{"line_number":1211,"context_line":"                stored_checksum_value \u003d part_headers.get("},{"line_number":1212,"context_line":"                    sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027))"},{"line_number":1213,"context_line":"                if (not stored_checksum_header or"},{"line_number":1214,"context_line":"                        stored_checksum_header.lower() !\u003d"},{"line_number":1215,"context_line":"                        marker_checksum_header.lower()):"},{"line_number":1216,"context_line":"                    # An old proxy may upload a part without checksum metadata"},{"line_number":1217,"context_line":"                    # or copy an object whose checksum metadata does not match"},{"line_number":1218,"context_line":"                    # the MPU marker. Fall back to completing without a"},{"line_number":1219,"context_line":"                    # checksum."},{"line_number":1220,"context_line":"                    complete_checksum_header \u003d None"},{"line_number":1221,"context_line":"                    complete_checksum_value \u003d None"},{"line_number":1222,"context_line":"                    complete_checksum_type \u003d None"},{"line_number":1223,"context_line":"                    footer_metadata.clear()"},{"line_number":1224,"context_line":"                    return problem_segments"},{"line_number":1225,"context_line":"                stored_checksum_values.append(stored_checksum_value)"},{"line_number":1226,"context_line":""},{"line_number":1227,"context_line":"            # Handle checksum for the MPU"}],"source_content_type":"text/x-python","patch_set":58,"id":"e2a5ec94_9248638d","line":1224,"range":{"start_line":1213,"start_character":0,"end_line":1224,"end_character":43},"updated":"2026-07-27 20:03:41.000000000","message":"This should handle mismatch proxy severs injecting objects without correct checksum sysmeta into an MPU","commit_id":"330a1f65938676c92084ffa5d266a356c01f0c83"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":392,"context_line":"        checksum_aware_mpu \u003d checksum_type and checksum_header"},{"line_number":393,"context_line":"        should_handle_mpu_checksum \u003d ("},{"line_number":394,"context_line":"            checksum_aware_mpu and"},{"line_number":395,"context_line":"            \u0027X-Amz-Copy-Source\u0027 not in req.headers)"},{"line_number":396,"context_line":""},{"line_number":397,"context_line":"        # S3Request has already validated checksum declaration cardinality,"},{"line_number":398,"context_line":"        # header values, and any x-amz-sdk-checksum-algorithm match. Trailer"}],"source_content_type":"text/x-python","patch_set":87,"id":"44ce1c41_58eef7a7","line":395,"updated":"2026-08-10 16:59:30.000000000","message":"do we expect there to be MPUs *after* upgrade that are NOT checksum aware\n\nA: yes. clients may still not provide checksum headers with the Create MPU; but server-side a checksum IS still calculated for each part (CRC64) and generate the final mpu checksum; however clients cannot view this checksum metadata on *parts* but they do see it when the MPU is completed.\n\nso checksum aware relates to whether the client specified checksum when the MPU was initiated.","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":392,"context_line":"        checksum_aware_mpu \u003d checksum_type and checksum_header"},{"line_number":393,"context_line":"        should_handle_mpu_checksum \u003d ("},{"line_number":394,"context_line":"            checksum_aware_mpu and"},{"line_number":395,"context_line":"            \u0027X-Amz-Copy-Source\u0027 not in req.headers)"},{"line_number":396,"context_line":""},{"line_number":397,"context_line":"        # S3Request has already validated checksum declaration cardinality,"},{"line_number":398,"context_line":"        # header values, and any x-amz-sdk-checksum-algorithm match. Trailer"}],"source_content_type":"text/x-python","patch_set":87,"id":"9c3e494c_229a9d4d","line":395,"in_reply_to":"44ce1c41_58eef7a7","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":109,"context_line":"    :param checksum_header: An x-amz-checksum-* header name."},{"line_number":110,"context_line":"    :return: The normalized checksum algorithm."},{"line_number":111,"context_line":"    \"\"\""},{"line_number":112,"context_line":"    return checksum_header[len(\u0027x-amz-checksum-\u0027):].upper().replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"def _checksum_hasher_from_header(checksum_header):"}],"source_content_type":"text/x-python","patch_set":89,"id":"a6e4788a_83508ac8","line":112,"updated":"2026-08-11 17:04:46.000000000","message":"I feel like this must be a useful helper in some \"shared\" module, but I haven\u0027t figured out where yet\n\nmaybe we need checksum.py earlier in the patch chain?","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":false,"context_lines":[{"line_number":109,"context_line":"    :param checksum_header: An x-amz-checksum-* header name."},{"line_number":110,"context_line":"    :return: The normalized checksum algorithm."},{"line_number":111,"context_line":"    \"\"\""},{"line_number":112,"context_line":"    return checksum_header[len(\u0027x-amz-checksum-\u0027):].upper().replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"def _checksum_hasher_from_header(checksum_header):"}],"source_content_type":"text/x-python","patch_set":89,"id":"16943f46_7320f39c","line":112,"in_reply_to":"90fb175f_9ee993a0","updated":"2026-08-12 16:06:26.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":true,"context_lines":[{"line_number":109,"context_line":"    :param checksum_header: An x-amz-checksum-* header name."},{"line_number":110,"context_line":"    :return: The normalized checksum algorithm."},{"line_number":111,"context_line":"    \"\"\""},{"line_number":112,"context_line":"    return checksum_header[len(\u0027x-amz-checksum-\u0027):].upper().replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"def _checksum_hasher_from_header(checksum_header):"}],"source_content_type":"text/x-python","patch_set":89,"id":"90fb175f_9ee993a0","line":112,"in_reply_to":"a6e4788a_83508ac8","updated":"2026-08-12 01:33:28.000000000","message":"Yea I agree with this\n\nIn future patches, we add `checksum.py` mainly because we started using `ChecksummingInput` for generic Swift requests. But all of this checksum code is getting littered throughout we ought to have the module.","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":112,"context_line":"    return checksum_header[len(\u0027x-amz-checksum-\u0027):].upper().replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"def _checksum_hasher_from_header(checksum_header):"},{"line_number":116,"context_line":"    \"\"\""},{"line_number":117,"context_line":"    Build a checksum hasher for the algorithm named by a checksum header."},{"line_number":118,"context_line":""}],"source_content_type":"text/x-python","patch_set":89,"id":"601d3c8b_dbbfb455","line":115,"updated":"2026-08-11 17:04:46.000000000","message":"we already have _get_checksum_hasher in s3api\n\noh, but we cannot import it here because S3Request imports controllers 🙃\n\nwe should try to fix the (existing) import mess","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":112,"context_line":"    return checksum_header[len(\u0027x-amz-checksum-\u0027):].upper().replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"def _checksum_hasher_from_header(checksum_header):"},{"line_number":116,"context_line":"    \"\"\""},{"line_number":117,"context_line":"    Build a checksum hasher for the algorithm named by a checksum header."},{"line_number":118,"context_line":""}],"source_content_type":"text/x-python","patch_set":89,"id":"b57e608c_115dc8f7","line":115,"in_reply_to":"3f97fec4_6a70002b","updated":"2026-08-12 16:06:26.000000000","message":"hehe, I\u0027m not so sure because now we have a bunch of try/except clauses :/","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":true,"context_lines":[{"line_number":112,"context_line":"    return checksum_header[len(\u0027x-amz-checksum-\u0027):].upper().replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"def _checksum_hasher_from_header(checksum_header):"},{"line_number":116,"context_line":"    \"\"\""},{"line_number":117,"context_line":"    Build a checksum hasher for the algorithm named by a checksum header."},{"line_number":118,"context_line":""}],"source_content_type":"text/x-python","patch_set":89,"id":"3f97fec4_6a70002b","line":115,"in_reply_to":"601d3c8b_dbbfb455","updated":"2026-08-12 01:33:28.000000000","message":"Moving these functions to `checksum.py` was a good idea!","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":112,"context_line":"    return checksum_header[len(\u0027x-amz-checksum-\u0027):].upper().replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"def _checksum_hasher_from_header(checksum_header):"},{"line_number":116,"context_line":"    \"\"\""},{"line_number":117,"context_line":"    Build a checksum hasher for the algorithm named by a checksum header."},{"line_number":118,"context_line":""}],"source_content_type":"text/x-python","patch_set":89,"id":"cf62a4f4_f0d3d5f4","line":115,"in_reply_to":"b57e608c_115dc8f7","updated":"2026-08-13 01:17:17.000000000","message":"yea adding a wrapper for this might be better...","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":112,"context_line":"    return checksum_header[len(\u0027x-amz-checksum-\u0027):].upper().replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"def _checksum_hasher_from_header(checksum_header):"},{"line_number":116,"context_line":"    \"\"\""},{"line_number":117,"context_line":"    Build a checksum hasher for the algorithm named by a checksum header."},{"line_number":118,"context_line":""}],"source_content_type":"text/x-python","patch_set":89,"id":"c98abc02_88a81acc","line":115,"in_reply_to":"cf62a4f4_f0d3d5f4","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":127,"context_line":"            \u0027The %s algorithm is not supported.\u0027 % checksum_header)"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"def _get_mpu_checksum_sysmeta(sysmeta_headers):"},{"line_number":131,"context_line":"    \"\"\""},{"line_number":132,"context_line":"    Return the checksum algorithm, type, and header from MPU sysmeta."},{"line_number":133,"context_line":""}],"source_content_type":"text/x-python","patch_set":89,"id":"c53d4064_08986f03","line":130,"updated":"2026-08-11 17:04:46.000000000","message":"this is *so* similar to utils.checksum_sysmeta_headers","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":true,"context_lines":[{"line_number":127,"context_line":"            \u0027The %s algorithm is not supported.\u0027 % checksum_header)"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"def _get_mpu_checksum_sysmeta(sysmeta_headers):"},{"line_number":131,"context_line":"    \"\"\""},{"line_number":132,"context_line":"    Return the checksum algorithm, type, and header from MPU sysmeta."},{"line_number":133,"context_line":""}],"source_content_type":"text/x-python","patch_set":89,"id":"dc257bcb_4bd2f948","line":130,"in_reply_to":"c53d4064_08986f03","updated":"2026-08-12 01:33:28.000000000","message":"I concur!","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":false,"context_lines":[{"line_number":127,"context_line":"            \u0027The %s algorithm is not supported.\u0027 % checksum_header)"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"def _get_mpu_checksum_sysmeta(sysmeta_headers):"},{"line_number":131,"context_line":"    \"\"\""},{"line_number":132,"context_line":"    Return the checksum algorithm, type, and header from MPU sysmeta."},{"line_number":133,"context_line":""}],"source_content_type":"text/x-python","patch_set":89,"id":"48778bd0_842152f3","line":130,"in_reply_to":"dc257bcb_4bd2f948","updated":"2026-08-12 16:06:26.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":177,"context_line":""},{"line_number":178,"context_line":"    checksum_algorithm \u003d \\"},{"line_number":179,"context_line":"        checksum_algorithm.strip().upper().replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":180,"context_line":"    if checksum_algorithm not in MPU_CHECKSUM_ALGORITHMS:"},{"line_number":181,"context_line":"        raise InvalidRequest("},{"line_number":182,"context_line":"            \u0027Checksum algorithm provided is unsupported. Please \u0027"},{"line_number":183,"context_line":"            \u0027try again with any of the valid types: [%s]\u0027 %"}],"source_content_type":"text/x-python","patch_set":89,"id":"ae2efd16_937d18dd","line":180,"range":{"start_line":180,"start_character":33,"end_line":180,"end_character":56},"updated":"2026-08-11 17:04:46.000000000","message":"different source of truth than when we look in CHECKSUMS_BY_HEADER elsewhere?","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":true,"context_lines":[{"line_number":177,"context_line":""},{"line_number":178,"context_line":"    checksum_algorithm \u003d \\"},{"line_number":179,"context_line":"        checksum_algorithm.strip().upper().replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":180,"context_line":"    if checksum_algorithm not in MPU_CHECKSUM_ALGORITHMS:"},{"line_number":181,"context_line":"        raise InvalidRequest("},{"line_number":182,"context_line":"            \u0027Checksum algorithm provided is unsupported. Please \u0027"},{"line_number":183,"context_line":"            \u0027try again with any of the valid types: [%s]\u0027 %"}],"source_content_type":"text/x-python","patch_set":89,"id":"b51aa840_42a0a8a5","line":180,"range":{"start_line":180,"start_character":33,"end_line":180,"end_character":56},"in_reply_to":"ae2efd16_937d18dd","updated":"2026-08-12 01:33:28.000000000","message":"I think using `CHECKSUMS_BY_HEADER` then parsing other tuples from that main list is probably the best approach","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":177,"context_line":""},{"line_number":178,"context_line":"    checksum_algorithm \u003d \\"},{"line_number":179,"context_line":"        checksum_algorithm.strip().upper().replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":180,"context_line":"    if checksum_algorithm not in MPU_CHECKSUM_ALGORITHMS:"},{"line_number":181,"context_line":"        raise InvalidRequest("},{"line_number":182,"context_line":"            \u0027Checksum algorithm provided is unsupported. Please \u0027"},{"line_number":183,"context_line":"            \u0027try again with any of the valid types: [%s]\u0027 %"}],"source_content_type":"text/x-python","patch_set":89,"id":"871336ab_d82acd93","line":180,"range":{"start_line":180,"start_character":33,"end_line":180,"end_character":56},"in_reply_to":"b51aa840_42a0a8a5","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":190,"context_line":"            checksum_type \u003d CHECKSUM_TYPE_COMPOSITE"},{"line_number":191,"context_line":"    else:"},{"line_number":192,"context_line":"        checksum_type \u003d checksum_type.upper()"},{"line_number":193,"context_line":"    if checksum_type not in MPU_CHECKSUM_TYPES:"},{"line_number":194,"context_line":"        raise InvalidArgument(\u0027x-amz-checksum-type\u0027, checksum_type)"},{"line_number":195,"context_line":"    if (checksum_type \u003d\u003d CHECKSUM_TYPE_FULL_OBJECT and"},{"line_number":196,"context_line":"            checksum_algorithm not in FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS):"}],"source_content_type":"text/x-python","patch_set":89,"id":"e5c470cd_1700423f","line":193,"updated":"2026-08-11 17:04:46.000000000","message":"this can be indented to be in the else clause\n\nalso, it might be helpful to be explicit here cf. the if clause:\n\n```\nif checksum_type not in (CHECKSUM_TYPE_COMPOSITE, CHECKSUM_TYPE_FULL_OBJECT)\n```","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":190,"context_line":"            checksum_type \u003d CHECKSUM_TYPE_COMPOSITE"},{"line_number":191,"context_line":"    else:"},{"line_number":192,"context_line":"        checksum_type \u003d checksum_type.upper()"},{"line_number":193,"context_line":"    if checksum_type not in MPU_CHECKSUM_TYPES:"},{"line_number":194,"context_line":"        raise InvalidArgument(\u0027x-amz-checksum-type\u0027, checksum_type)"},{"line_number":195,"context_line":"    if (checksum_type \u003d\u003d CHECKSUM_TYPE_FULL_OBJECT and"},{"line_number":196,"context_line":"            checksum_algorithm not in FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS):"}],"source_content_type":"text/x-python","patch_set":89,"id":"e0b7648b_a3e1d8ac","line":193,"in_reply_to":"49c5cc55_cb151231","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":true,"context_lines":[{"line_number":190,"context_line":"            checksum_type \u003d CHECKSUM_TYPE_COMPOSITE"},{"line_number":191,"context_line":"    else:"},{"line_number":192,"context_line":"        checksum_type \u003d checksum_type.upper()"},{"line_number":193,"context_line":"    if checksum_type not in MPU_CHECKSUM_TYPES:"},{"line_number":194,"context_line":"        raise InvalidArgument(\u0027x-amz-checksum-type\u0027, checksum_type)"},{"line_number":195,"context_line":"    if (checksum_type \u003d\u003d CHECKSUM_TYPE_FULL_OBJECT and"},{"line_number":196,"context_line":"            checksum_algorithm not in FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS):"}],"source_content_type":"text/x-python","patch_set":89,"id":"49c5cc55_cb151231","line":193,"in_reply_to":"e5c470cd_1700423f","updated":"2026-08-12 01:33:28.000000000","message":"I could see that, I\u0027ll have to update this","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":211,"context_line":"            \u0027The %s checksum type cannot be used with the %s \u0027"},{"line_number":212,"context_line":"            \u0027checksum algorithm.\u0027 % ("},{"line_number":213,"context_line":"                checksum_type, checksum_algorithm.lower()))"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":"    checksum_header \u003d checksum_header_from_algorithm(checksum_algorithm)"},{"line_number":216,"context_line":"    return (mpu_checksum_sysmeta_headers("},{"line_number":217,"context_line":"        checksum_algorithm, checksum_header, checksum_type), {"}],"source_content_type":"text/x-python","patch_set":89,"id":"d913d18a_4f257af8","line":214,"updated":"2026-08-11 17:04:46.000000000","message":"I feel like this function has done its job here i.e. parsing and validation of headers, and that composing sysmeta and resp headers might move back to the caller","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":211,"context_line":"            \u0027The %s checksum type cannot be used with the %s \u0027"},{"line_number":212,"context_line":"            \u0027checksum algorithm.\u0027 % ("},{"line_number":213,"context_line":"                checksum_type, checksum_algorithm.lower()))"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":"    checksum_header \u003d checksum_header_from_algorithm(checksum_algorithm)"},{"line_number":216,"context_line":"    return (mpu_checksum_sysmeta_headers("},{"line_number":217,"context_line":"        checksum_algorithm, checksum_header, checksum_type), {"}],"source_content_type":"text/x-python","patch_set":89,"id":"d5d377e8_185337ae","line":214,"in_reply_to":"caabb6a9_8d9b82be","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":true,"context_lines":[{"line_number":211,"context_line":"            \u0027The %s checksum type cannot be used with the %s \u0027"},{"line_number":212,"context_line":"            \u0027checksum algorithm.\u0027 % ("},{"line_number":213,"context_line":"                checksum_type, checksum_algorithm.lower()))"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":"    checksum_header \u003d checksum_header_from_algorithm(checksum_algorithm)"},{"line_number":216,"context_line":"    return (mpu_checksum_sysmeta_headers("},{"line_number":217,"context_line":"        checksum_algorithm, checksum_header, checksum_type), {"}],"source_content_type":"text/x-python","patch_set":89,"id":"caabb6a9_8d9b82be","line":214,"in_reply_to":"d913d18a_4f257af8","updated":"2026-08-12 01:33:28.000000000","message":"Yea I agree, we ought to move this out","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":1015,"context_line":""},{"line_number":1016,"context_line":"        resp, is_marker \u003d _get_upload_info(req, self.app, upload_id)"},{"line_number":1017,"context_line":"        (marker_checksum_algorithm, marker_checksum_type,"},{"line_number":1018,"context_line":"         marker_checksum_header) \u003d _get_mpu_checksum_sysmeta("},{"line_number":1019,"context_line":"             resp.sysmeta_headers)"},{"line_number":1020,"context_line":""},{"line_number":1021,"context_line":"        # Make sure client supplied the same type as the CreateMultipartUpload"}],"source_content_type":"text/x-python","patch_set":89,"id":"1c9b7ddf_dac17756","line":1018,"range":{"start_line":1018,"start_character":9,"end_line":1018,"end_character":30},"updated":"2026-08-11 17:04:46.000000000","message":"why do we need to pass around header *and* algorithm ?","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":true,"context_lines":[{"line_number":1015,"context_line":""},{"line_number":1016,"context_line":"        resp, is_marker \u003d _get_upload_info(req, self.app, upload_id)"},{"line_number":1017,"context_line":"        (marker_checksum_algorithm, marker_checksum_type,"},{"line_number":1018,"context_line":"         marker_checksum_header) \u003d _get_mpu_checksum_sysmeta("},{"line_number":1019,"context_line":"             resp.sysmeta_headers)"},{"line_number":1020,"context_line":""},{"line_number":1021,"context_line":"        # Make sure client supplied the same type as the CreateMultipartUpload"}],"source_content_type":"text/x-python","patch_set":89,"id":"62e642a8_5cae9d6f","line":1018,"range":{"start_line":1018,"start_character":9,"end_line":1018,"end_character":30},"in_reply_to":"1c9b7ddf_dac17756","updated":"2026-08-12 01:33:28.000000000","message":"I think we can mainly use the header and parse the algorithm when need be","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":false,"context_lines":[{"line_number":1015,"context_line":""},{"line_number":1016,"context_line":"        resp, is_marker \u003d _get_upload_info(req, self.app, upload_id)"},{"line_number":1017,"context_line":"        (marker_checksum_algorithm, marker_checksum_type,"},{"line_number":1018,"context_line":"         marker_checksum_header) \u003d _get_mpu_checksum_sysmeta("},{"line_number":1019,"context_line":"             resp.sysmeta_headers)"},{"line_number":1020,"context_line":""},{"line_number":1021,"context_line":"        # Make sure client supplied the same type as the CreateMultipartUpload"}],"source_content_type":"text/x-python","patch_set":89,"id":"e48a4eac_a36d6d9a","line":1018,"range":{"start_line":1018,"start_character":9,"end_line":1018,"end_character":30},"in_reply_to":"62e642a8_5cae9d6f","updated":"2026-08-12 16:06:26.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":1018,"context_line":"         marker_checksum_header) \u003d _get_mpu_checksum_sysmeta("},{"line_number":1019,"context_line":"             resp.sysmeta_headers)"},{"line_number":1020,"context_line":""},{"line_number":1021,"context_line":"        # Make sure client supplied the same type as the CreateMultipartUpload"},{"line_number":1022,"context_line":"        request_checksum_type \u003d req.headers.get(\u0027x-amz-checksum-type\u0027)"},{"line_number":1023,"context_line":"        if request_checksum_type and marker_checksum_type:"},{"line_number":1024,"context_line":"            request_checksum_type \u003d request_checksum_type.upper()"}],"source_content_type":"text/x-python","patch_set":89,"id":"29839213_a73570df","line":1021,"updated":"2026-08-11 17:04:46.000000000","message":"this method was \u003e 200 lines long (already too long!) and it is now \u003e400 lines long...once a function doesn\u0027t fit on a screen it\u0027s time to think about decomposing it ;-)\n\nmaybe:\n\n```\n_validate_complete_upload_headers()\n_parse_user_manifest()\n```\n\ncan ``manifest_hook`` be closure defined outside of this method?","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":true,"context_lines":[{"line_number":1018,"context_line":"         marker_checksum_header) \u003d _get_mpu_checksum_sysmeta("},{"line_number":1019,"context_line":"             resp.sysmeta_headers)"},{"line_number":1020,"context_line":""},{"line_number":1021,"context_line":"        # Make sure client supplied the same type as the CreateMultipartUpload"},{"line_number":1022,"context_line":"        request_checksum_type \u003d req.headers.get(\u0027x-amz-checksum-type\u0027)"},{"line_number":1023,"context_line":"        if request_checksum_type and marker_checksum_type:"},{"line_number":1024,"context_line":"            request_checksum_type \u003d request_checksum_type.upper()"}],"source_content_type":"text/x-python","patch_set":89,"id":"ddb01545_9c27668f","line":1021,"in_reply_to":"29839213_a73570df","updated":"2026-08-12 01:33:28.000000000","message":"Yes it can! doing this is actually alot better, thanks to `feature/mpu` for inspration too!","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":false,"context_lines":[{"line_number":1018,"context_line":"         marker_checksum_header) \u003d _get_mpu_checksum_sysmeta("},{"line_number":1019,"context_line":"             resp.sysmeta_headers)"},{"line_number":1020,"context_line":""},{"line_number":1021,"context_line":"        # Make sure client supplied the same type as the CreateMultipartUpload"},{"line_number":1022,"context_line":"        request_checksum_type \u003d req.headers.get(\u0027x-amz-checksum-type\u0027)"},{"line_number":1023,"context_line":"        if request_checksum_type and marker_checksum_type:"},{"line_number":1024,"context_line":"            request_checksum_type \u003d request_checksum_type.upper()"}],"source_content_type":"text/x-python","patch_set":89,"id":"fcff33ee_82c2cfa6","line":1021,"in_reply_to":"ddb01545_9c27668f","updated":"2026-08-12 16:06:26.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":1032,"context_line":"            marker_checksum_elem_name \u003d checksum_xml_element_from_header("},{"line_number":1033,"context_line":"                marker_checksum_header)"},{"line_number":1034,"context_line":""},{"line_number":1035,"context_line":"        checksum_aware_composite \u003d ("},{"line_number":1036,"context_line":"            marker_checksum_type \u003d\u003d CHECKSUM_TYPE_COMPOSITE and"},{"line_number":1037,"context_line":"            marker_checksum_algorithm and marker_checksum_header and"},{"line_number":1038,"context_line":"            marker_checksum_elem_name)"},{"line_number":1039,"context_line":"        checksum_aware_full_object \u003d ("},{"line_number":1040,"context_line":"            marker_checksum_type \u003d\u003d CHECKSUM_TYPE_FULL_OBJECT and"},{"line_number":1041,"context_line":"            marker_checksum_algorithm and marker_checksum_header and"},{"line_number":1042,"context_line":"            marker_checksum_elem_name)"},{"line_number":1043,"context_line":"        checksum_aware_mpu \u003d ("},{"line_number":1044,"context_line":"            checksum_aware_composite or checksum_aware_full_object)"},{"line_number":1045,"context_line":"        request_checksum_header, request_checksum_value \u003d \\"},{"line_number":1046,"context_line":"            _complete_request_checksum(req)"},{"line_number":1047,"context_line":"        existing_checksum_value \u003d resp.sysmeta_headers.get("}],"source_content_type":"text/x-python","patch_set":89,"id":"3b64f7e3_7dddc287","line":1044,"range":{"start_line":1035,"start_character":8,"end_line":1044,"end_character":67},"updated":"2026-08-11 17:04:46.000000000","message":"might be helpful to encapsulate these checksum attrs and the various flags/condition checks in a ChecksumAttrs class\n\nsee ``slo.RespAttrs`` for example","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":true,"context_lines":[{"line_number":1032,"context_line":"            marker_checksum_elem_name \u003d checksum_xml_element_from_header("},{"line_number":1033,"context_line":"                marker_checksum_header)"},{"line_number":1034,"context_line":""},{"line_number":1035,"context_line":"        checksum_aware_composite \u003d ("},{"line_number":1036,"context_line":"            marker_checksum_type \u003d\u003d CHECKSUM_TYPE_COMPOSITE and"},{"line_number":1037,"context_line":"            marker_checksum_algorithm and marker_checksum_header and"},{"line_number":1038,"context_line":"            marker_checksum_elem_name)"},{"line_number":1039,"context_line":"        checksum_aware_full_object \u003d ("},{"line_number":1040,"context_line":"            marker_checksum_type \u003d\u003d CHECKSUM_TYPE_FULL_OBJECT and"},{"line_number":1041,"context_line":"            marker_checksum_algorithm and marker_checksum_header and"},{"line_number":1042,"context_line":"            marker_checksum_elem_name)"},{"line_number":1043,"context_line":"        checksum_aware_mpu \u003d ("},{"line_number":1044,"context_line":"            checksum_aware_composite or checksum_aware_full_object)"},{"line_number":1045,"context_line":"        request_checksum_header, request_checksum_value \u003d \\"},{"line_number":1046,"context_line":"            _complete_request_checksum(req)"},{"line_number":1047,"context_line":"        existing_checksum_value \u003d resp.sysmeta_headers.get("}],"source_content_type":"text/x-python","patch_set":89,"id":"f4046bda_6a8ed5ca","line":1044,"range":{"start_line":1035,"start_character":8,"end_line":1044,"end_character":67},"in_reply_to":"3b64f7e3_7dddc287","updated":"2026-08-12 01:33:28.000000000","message":"I think this is also a good idea, like a `ChecksumAttrs` is quite helpful where we can just pass those classes around and compare them for validation too","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":false,"context_lines":[{"line_number":1032,"context_line":"            marker_checksum_elem_name \u003d checksum_xml_element_from_header("},{"line_number":1033,"context_line":"                marker_checksum_header)"},{"line_number":1034,"context_line":""},{"line_number":1035,"context_line":"        checksum_aware_composite \u003d ("},{"line_number":1036,"context_line":"            marker_checksum_type \u003d\u003d CHECKSUM_TYPE_COMPOSITE and"},{"line_number":1037,"context_line":"            marker_checksum_algorithm and marker_checksum_header and"},{"line_number":1038,"context_line":"            marker_checksum_elem_name)"},{"line_number":1039,"context_line":"        checksum_aware_full_object \u003d ("},{"line_number":1040,"context_line":"            marker_checksum_type \u003d\u003d CHECKSUM_TYPE_FULL_OBJECT and"},{"line_number":1041,"context_line":"            marker_checksum_algorithm and marker_checksum_header and"},{"line_number":1042,"context_line":"            marker_checksum_elem_name)"},{"line_number":1043,"context_line":"        checksum_aware_mpu \u003d ("},{"line_number":1044,"context_line":"            checksum_aware_composite or checksum_aware_full_object)"},{"line_number":1045,"context_line":"        request_checksum_header, request_checksum_value \u003d \\"},{"line_number":1046,"context_line":"            _complete_request_checksum(req)"},{"line_number":1047,"context_line":"        existing_checksum_value \u003d resp.sysmeta_headers.get("}],"source_content_type":"text/x-python","patch_set":89,"id":"046154a4_1209a6e1","line":1044,"range":{"start_line":1035,"start_character":8,"end_line":1044,"end_character":67},"in_reply_to":"f4046bda_6a8ed5ca","updated":"2026-08-12 16:06:26.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"def90498db0528d690bd6d2257738471d27d010e","unresolved":true,"context_lines":[{"line_number":401,"context_line":"    try:"},{"line_number":402,"context_line":"        checksum_hasher \u003d get_checksum_hasher(checksum_header)"},{"line_number":403,"context_line":"    except NotImplementedError as err:"},{"line_number":404,"context_line":"        raise S3NotImplemented(str(err))"},{"line_number":405,"context_line":"    checksum_hasher.update(b\u0027\u0027.join(part_checksum_values))"},{"line_number":406,"context_line":"    return \u0027%s-%d\u0027 % ("},{"line_number":407,"context_line":"        base64_str(checksum_hasher.digest()),"}],"source_content_type":"text/x-python","patch_set":91,"id":"2776fbc2_4b098cea","line":404,"range":{"start_line":404,"start_character":0,"end_line":404,"end_character":40},"updated":"2026-08-12 01:37:20.000000000","message":"Not the biggest fan of `get_checksum_hasher` throwing `NotImplementedError` instead of just `S3NotImplemented`, but circulars imports are nasty","commit_id":"ae4f90c3e9836e6b397ac84817e1f195cd560cbc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":401,"context_line":"    try:"},{"line_number":402,"context_line":"        checksum_hasher \u003d get_checksum_hasher(checksum_header)"},{"line_number":403,"context_line":"    except NotImplementedError as err:"},{"line_number":404,"context_line":"        raise S3NotImplemented(str(err))"},{"line_number":405,"context_line":"    checksum_hasher.update(b\u0027\u0027.join(part_checksum_values))"},{"line_number":406,"context_line":"    return \u0027%s-%d\u0027 % ("},{"line_number":407,"context_line":"        base64_str(checksum_hasher.digest()),"}],"source_content_type":"text/x-python","patch_set":91,"id":"c2495266_695d8429","line":404,"range":{"start_line":404,"start_character":0,"end_line":404,"end_character":40},"in_reply_to":"116943b2_ab24f9d3","updated":"2026-08-14 14:35:38.000000000","message":"Acknowledged","commit_id":"ae4f90c3e9836e6b397ac84817e1f195cd560cbc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":401,"context_line":"    try:"},{"line_number":402,"context_line":"        checksum_hasher \u003d get_checksum_hasher(checksum_header)"},{"line_number":403,"context_line":"    except NotImplementedError as err:"},{"line_number":404,"context_line":"        raise S3NotImplemented(str(err))"},{"line_number":405,"context_line":"    checksum_hasher.update(b\u0027\u0027.join(part_checksum_values))"},{"line_number":406,"context_line":"    return \u0027%s-%d\u0027 % ("},{"line_number":407,"context_line":"        base64_str(checksum_hasher.digest()),"}],"source_content_type":"text/x-python","patch_set":91,"id":"4f5ea720_a489805f","line":404,"range":{"start_line":404,"start_character":0,"end_line":404,"end_character":40},"in_reply_to":"2776fbc2_4b098cea","updated":"2026-08-12 16:06:26.000000000","message":"I think that we may have to pragmatically give-up on the goal of a single ``get_checksum_hasher(checksum_header)`` function:\n\nWe could remove s3response dependency of checksum by having the obj controller translate the checksum sysmeta to response headers when handling GET/HEAD. IMHO that might be a better pattern, i.e. not have s3response import checksum.  But there\u0027s existing precedent for header translation in S3Response. And although that would allow us to import S3NotImplemented into checksum, that seems unfortunate because it feels like checksum.py wants to be a \u0027utils\u0027-like module full of helpers with as few dependencies as possible.\n\nSo maybe we just need to accept that there are two places where algorithm support is validated (s3request and mpu) and in each case we have a shim to catch the NotImplementedError and raise the http response error?","commit_id":"ae4f90c3e9836e6b397ac84817e1f195cd560cbc"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":401,"context_line":"    try:"},{"line_number":402,"context_line":"        checksum_hasher \u003d get_checksum_hasher(checksum_header)"},{"line_number":403,"context_line":"    except NotImplementedError as err:"},{"line_number":404,"context_line":"        raise S3NotImplemented(str(err))"},{"line_number":405,"context_line":"    checksum_hasher.update(b\u0027\u0027.join(part_checksum_values))"},{"line_number":406,"context_line":"    return \u0027%s-%d\u0027 % ("},{"line_number":407,"context_line":"        base64_str(checksum_hasher.digest()),"}],"source_content_type":"text/x-python","patch_set":91,"id":"116943b2_ab24f9d3","line":404,"range":{"start_line":404,"start_character":0,"end_line":404,"end_character":40},"in_reply_to":"4f5ea720_a489805f","updated":"2026-08-13 01:17:17.000000000","message":"\u003e So maybe we just need to accept that there are two places where algorithm support is validated (s3request and mpu) and in each case we have a shim to catch the NotImplementedError and raise the http response error?\n\nI think this is probably the reality, it is unfortunate, since anytime this function is called, we are just raising `S3NotImplemented`. Though I feel it might be a better pattern to have module functions not raise HTTP errors and the handlers of said HTTP request actually throw the HTTP response errors. Food for thought I guess","commit_id":"ae4f90c3e9836e6b397ac84817e1f195cd560cbc"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"def90498db0528d690bd6d2257738471d27d010e","unresolved":false,"context_lines":[{"line_number":1433,"context_line":"            \u0027manifest_part_checksums\u0027: manifest_part_checksums,"},{"line_number":1434,"context_line":"            \u0027footer_metadata\u0027: footer_metadata,"},{"line_number":1435,"context_line":"        }"},{"line_number":1436,"context_line":"        manifest_hook \u003d _CompleteMultipartUploadSloManifestHook("},{"line_number":1437,"context_line":"            manifest_hook_state)"},{"line_number":1438,"context_line":"        req.environ[\u0027swift.callback.slo_manifest_hook\u0027] \u003d manifest_hook"},{"line_number":1439,"context_line":""}],"source_content_type":"text/x-python","patch_set":91,"id":"ef66493e_b26c1278","line":1436,"range":{"start_line":1436,"start_character":0,"end_line":1436,"end_character":64},"updated":"2026-08-12 01:37:20.000000000","message":"Now we can see whats going on here!! +1 to moving closure to a class!","commit_id":"ae4f90c3e9836e6b397ac84817e1f195cd560cbc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":265,"context_line":"            checksum_hasher \u003d get_checksum_hasher("},{"line_number":266,"context_line":"                checksum_attrs.checksum_header)"},{"line_number":267,"context_line":"        except NotImplementedError as err:"},{"line_number":268,"context_line":"            raise S3NotImplemented(str(err))"},{"line_number":269,"context_line":"        # The current proxy server might not have a crc_combine function"},{"line_number":270,"context_line":"        # so lets not make a MPU we cannot complete"},{"line_number":271,"context_line":"        if checksum_hasher.crc_combine_func is None:"}],"source_content_type":"text/x-python","patch_set":92,"id":"f61d90ae_cdd30621","line":268,"updated":"2026-08-12 16:06:26.000000000","message":"hmmm, so now we have multiple places with this try/except\n\nI\u0027m starting to think we might just need to accept the duplicated function in each module; wrangling the import cycle is probably not worth the distraction at this stage. Maybe a brief comment with each helper pointing out why they duplicate.","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":265,"context_line":"            checksum_hasher \u003d get_checksum_hasher("},{"line_number":266,"context_line":"                checksum_attrs.checksum_header)"},{"line_number":267,"context_line":"        except NotImplementedError as err:"},{"line_number":268,"context_line":"            raise S3NotImplemented(str(err))"},{"line_number":269,"context_line":"        # The current proxy server might not have a crc_combine function"},{"line_number":270,"context_line":"        # so lets not make a MPU we cannot complete"},{"line_number":271,"context_line":"        if checksum_hasher.crc_combine_func is None:"}],"source_content_type":"text/x-python","patch_set":92,"id":"c5c7f5ff_0f81bc78","line":268,"in_reply_to":"5058dd37_8714c2d9","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":265,"context_line":"            checksum_hasher \u003d get_checksum_hasher("},{"line_number":266,"context_line":"                checksum_attrs.checksum_header)"},{"line_number":267,"context_line":"        except NotImplementedError as err:"},{"line_number":268,"context_line":"            raise S3NotImplemented(str(err))"},{"line_number":269,"context_line":"        # The current proxy server might not have a crc_combine function"},{"line_number":270,"context_line":"        # so lets not make a MPU we cannot complete"},{"line_number":271,"context_line":"        if checksum_hasher.crc_combine_func is None:"}],"source_content_type":"text/x-python","patch_set":92,"id":"5058dd37_8714c2d9","line":268,"in_reply_to":"f61d90ae_cdd30621","updated":"2026-08-13 01:17:17.000000000","message":"Yea that can be good, less code too!","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":579,"context_line":"        \"\"\"Return the segment HEAD response headers from the manifest.\"\"\""},{"line_number":580,"context_line":"        segment_head_headers \u003d []"},{"line_number":581,"context_line":"        for segment in manifest:"},{"line_number":582,"context_line":"            if segment is None:"},{"line_number":583,"context_line":"                segment_head_headers.append(None)"},{"line_number":584,"context_line":"                continue"},{"line_number":585,"context_line":"            segment_head_headers.append(segment.get(\u0027headers\u0027))"}],"source_content_type":"text/x-python","patch_set":92,"id":"3d7e6997_b80ccb92","line":582,"updated":"2026-08-12 16:06:26.000000000","message":"can this be true?","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":579,"context_line":"        \"\"\"Return the segment HEAD response headers from the manifest.\"\"\""},{"line_number":580,"context_line":"        segment_head_headers \u003d []"},{"line_number":581,"context_line":"        for segment in manifest:"},{"line_number":582,"context_line":"            if segment is None:"},{"line_number":583,"context_line":"                segment_head_headers.append(None)"},{"line_number":584,"context_line":"                continue"},{"line_number":585,"context_line":"            segment_head_headers.append(segment.get(\u0027headers\u0027))"}],"source_content_type":"text/x-python","patch_set":92,"id":"b7249a46_d73c2b7c","line":582,"in_reply_to":"39415e52_b8cbe71a","updated":"2026-08-14 14:35:38.000000000","message":"thanks I see that now. SLO deals with the part HEAD failures after the hook call","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":579,"context_line":"        \"\"\"Return the segment HEAD response headers from the manifest.\"\"\""},{"line_number":580,"context_line":"        segment_head_headers \u003d []"},{"line_number":581,"context_line":"        for segment in manifest:"},{"line_number":582,"context_line":"            if segment is None:"},{"line_number":583,"context_line":"                segment_head_headers.append(None)"},{"line_number":584,"context_line":"                continue"},{"line_number":585,"context_line":"            segment_head_headers.append(segment.get(\u0027headers\u0027))"}],"source_content_type":"text/x-python","patch_set":92,"id":"39415e52_b8cbe71a","line":582,"in_reply_to":"3d7e6997_b80ccb92","updated":"2026-08-13 01:17:17.000000000","message":"Yes since the manifest hook is executed BEFORE we handle the `problem_segments` say for instance the `problem_segments` encounters a `404` while trying to look up a part.\n\nThe segment will be None\n```\n        def validate_seg_dict(seg_dict, head_seg_resp, allow_empty_segment):\n            obj_name \u003d seg_dict[\u0027path\u0027]\n            if not head_seg_resp.is_success:\n                problem_segments.append([quote(obj_name),\n                                         head_seg_resp.status])\n                return 0, None\n```\n\nAnd then once `slo` has gotten all of the segments it calls the hook we setup BEFORE handling the `problem_segments` meaning segments can have problems in the hook\n```\n            hook \u003d req.environ.get(\u0027swift.callback.slo_manifest_hook\u0027)\n            if hook:\n                more_problems \u003d hook(data_for_validation)\n                if more_problems:\n                    problem_segments.extend(more_problems)\n\n            if problem_segments:\n                err \u003d HTTPBadRequest(content_type\u003dout_content_type)\n                resp_dict \u003d {}\n                if heartbeat:\n                    resp_dict[\u0027Response Status\u0027] \u003d err.status\n                    err_body \u003d err.body.decode(\u0027utf-8\u0027)\n                    resp_dict[\u0027Response Body\u0027] \u003d err_body or \u0027\\n\u0027.join(\n                        RESPONSE_REASONS.get(err.status_int, [\u0027\u0027]))\n```\n\nSo this means the hook can encounter 404\u0027ed segments so we have to handle that. I think also since this is before the handling of the `problem_segments` we probably shouldn\u0027t be throwing an error when we find a 404\u0027ed segment, but just let MPU deal with it like it is doing today.\n\nLooking at this the question becomes \"why aren\u0027t we just stopping the checksum calculation at this point?\" I think we should! just give up if we find a \u0027None\u0027 segment. This patch right now is turnning the \u0027None\u0027 segment into missing headers which eventually causes the checksum calculation to stop in L597","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":599,"context_line":"                # sentinel. Fall back to completing without a checksum."},{"line_number":600,"context_line":"                self.mpu_checksum_attrs \u003d MPUChecksumAttrs("},{"line_number":601,"context_line":"                    is_mpu_in_progress\u003dFalse)"},{"line_number":602,"context_line":"                self.footer_metadata.clear()"},{"line_number":603,"context_line":"                return None"},{"line_number":604,"context_line":"            stored_checksum_values.append(stored_checksum_value)"},{"line_number":605,"context_line":"        return stored_checksum_values"}],"source_content_type":"text/x-python","patch_set":92,"id":"cf914d63_caee5c86","line":602,"updated":"2026-08-12 16:06:26.000000000","message":"these are side_effects; instead, set flags on this class to be read somewhere around line 1444\n\ni.e. keep the scope of this class tighter: it reads manifest, reports errors and notes if all parts have checksums; the controller decides what to do in response to all parts not having checksums\n\nalso, ``self.footer_metadata.clear()`` doesn\u0027t seem to be covered by unit tests","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":599,"context_line":"                # sentinel. Fall back to completing without a checksum."},{"line_number":600,"context_line":"                self.mpu_checksum_attrs \u003d MPUChecksumAttrs("},{"line_number":601,"context_line":"                    is_mpu_in_progress\u003dFalse)"},{"line_number":602,"context_line":"                self.footer_metadata.clear()"},{"line_number":603,"context_line":"                return None"},{"line_number":604,"context_line":"            stored_checksum_values.append(stored_checksum_value)"},{"line_number":605,"context_line":"        return stored_checksum_values"}],"source_content_type":"text/x-python","patch_set":92,"id":"f91754c9_a99c38d8","line":602,"in_reply_to":"802f7d6f_02fe1787","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":599,"context_line":"                # sentinel. Fall back to completing without a checksum."},{"line_number":600,"context_line":"                self.mpu_checksum_attrs \u003d MPUChecksumAttrs("},{"line_number":601,"context_line":"                    is_mpu_in_progress\u003dFalse)"},{"line_number":602,"context_line":"                self.footer_metadata.clear()"},{"line_number":603,"context_line":"                return None"},{"line_number":604,"context_line":"            stored_checksum_values.append(stored_checksum_value)"},{"line_number":605,"context_line":"        return stored_checksum_values"}],"source_content_type":"text/x-python","patch_set":92,"id":"802f7d6f_02fe1787","line":602,"in_reply_to":"cf914d63_caee5c86","updated":"2026-08-13 01:17:17.000000000","message":"The usage of flags is better here","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":608,"context_line":"            self, manifest_part_checksum, stored_checksum_value,"},{"line_number":609,"context_line":"            manifest_item):"},{"line_number":610,"context_line":"        \"\"\"Validate and return checksum metadata for a completed part.\"\"\""},{"line_number":611,"context_line":"        part_number, part_checksum_value, part_checksum_raw \u003d \\"},{"line_number":612,"context_line":"            manifest_part_checksum"},{"line_number":613,"context_line":""},{"line_number":614,"context_line":"        # FULL_OBJECT completion may omit client-provided per-part"}],"source_content_type":"text/x-python","patch_set":92,"id":"9ac3cb5c_d36110b9","line":611,"range":{"start_line":611,"start_character":42,"end_line":611,"end_character":60},"updated":"2026-08-12 16:06:26.000000000","message":"this is not used in this method","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":608,"context_line":"            self, manifest_part_checksum, stored_checksum_value,"},{"line_number":609,"context_line":"            manifest_item):"},{"line_number":610,"context_line":"        \"\"\"Validate and return checksum metadata for a completed part.\"\"\""},{"line_number":611,"context_line":"        part_number, part_checksum_value, part_checksum_raw \u003d \\"},{"line_number":612,"context_line":"            manifest_part_checksum"},{"line_number":613,"context_line":""},{"line_number":614,"context_line":"        # FULL_OBJECT completion may omit client-provided per-part"}],"source_content_type":"text/x-python","patch_set":92,"id":"abd8173d_7f3bf008","line":611,"range":{"start_line":611,"start_character":42,"end_line":611,"end_character":60},"in_reply_to":"6c12d463_043d48e4","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":608,"context_line":"            self, manifest_part_checksum, stored_checksum_value,"},{"line_number":609,"context_line":"            manifest_item):"},{"line_number":610,"context_line":"        \"\"\"Validate and return checksum metadata for a completed part.\"\"\""},{"line_number":611,"context_line":"        part_number, part_checksum_value, part_checksum_raw \u003d \\"},{"line_number":612,"context_line":"            manifest_part_checksum"},{"line_number":613,"context_line":""},{"line_number":614,"context_line":"        # FULL_OBJECT completion may omit client-provided per-part"}],"source_content_type":"text/x-python","patch_set":92,"id":"6c12d463_043d48e4","line":611,"range":{"start_line":611,"start_character":42,"end_line":611,"end_character":60},"in_reply_to":"9ac3cb5c_d36110b9","updated":"2026-08-13 01:17:17.000000000","message":"fixed","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":614,"context_line":"        # FULL_OBJECT completion may omit client-provided per-part"},{"line_number":615,"context_line":"        # checksums; use the value persisted during UploadPart instead."},{"line_number":616,"context_line":"        if part_checksum_value is None:"},{"line_number":617,"context_line":"            if self.mpu_checksum_attrs.is_composite:"},{"line_number":618,"context_line":"                raise InvalidPart("},{"line_number":619,"context_line":"                    upload_id\u003dself.upload_id,"},{"line_number":620,"context_line":"                    part_number\u003dpart_number)"}],"source_content_type":"text/x-python","patch_set":92,"id":"6264fd90_ef28f545","line":617,"updated":"2026-08-12 16:06:26.000000000","message":"there\u0027s a few places in this class where we have ``if composite/else...``; enough places to make me wonder if two subclasses of a shared base class might be neater: one for each checksum type? it might not work out but if it did it would help to grok the different handling of the two cases. Then the controller just uses whichever subclass is appropriate when installing the hook.","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":true,"context_lines":[{"line_number":614,"context_line":"        # FULL_OBJECT completion may omit client-provided per-part"},{"line_number":615,"context_line":"        # checksums; use the value persisted during UploadPart instead."},{"line_number":616,"context_line":"        if part_checksum_value is None:"},{"line_number":617,"context_line":"            if self.mpu_checksum_attrs.is_composite:"},{"line_number":618,"context_line":"                raise InvalidPart("},{"line_number":619,"context_line":"                    upload_id\u003dself.upload_id,"},{"line_number":620,"context_line":"                    part_number\u003dpart_number)"}],"source_content_type":"text/x-python","patch_set":92,"id":"6c1a3b23_20b79085","line":617,"in_reply_to":"6264fd90_ef28f545","updated":"2026-08-14 14:35:38.000000000","message":"maybe not worth it","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"010621ef8337f9eae1cb8e1ddaebffafe261c28b","unresolved":true,"context_lines":[{"line_number":614,"context_line":"        # FULL_OBJECT completion may omit client-provided per-part"},{"line_number":615,"context_line":"        # checksums; use the value persisted during UploadPart instead."},{"line_number":616,"context_line":"        if part_checksum_value is None:"},{"line_number":617,"context_line":"            if self.mpu_checksum_attrs.is_composite:"},{"line_number":618,"context_line":"                raise InvalidPart("},{"line_number":619,"context_line":"                    upload_id\u003dself.upload_id,"},{"line_number":620,"context_line":"                    part_number\u003dpart_number)"}],"source_content_type":"text/x-python","patch_set":92,"id":"a97ca5bb_5b24e457","line":617,"in_reply_to":"6c1a3b23_20b79085","updated":"2026-08-14 23:44:06.000000000","message":"I think it might require some more refactoring that is probably not worth it IMHO","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":614,"context_line":"        # FULL_OBJECT completion may omit client-provided per-part"},{"line_number":615,"context_line":"        # checksums; use the value persisted during UploadPart instead."},{"line_number":616,"context_line":"        if part_checksum_value is None:"},{"line_number":617,"context_line":"            if self.mpu_checksum_attrs.is_composite:"},{"line_number":618,"context_line":"                raise InvalidPart("},{"line_number":619,"context_line":"                    upload_id\u003dself.upload_id,"},{"line_number":620,"context_line":"                    part_number\u003dpart_number)"}],"source_content_type":"text/x-python","patch_set":92,"id":"d109bb30_2ff4b26a","line":617,"in_reply_to":"a97ca5bb_5b24e457","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":628,"context_line":"        elif stored_checksum_value !\u003d part_checksum_value:"},{"line_number":629,"context_line":"            raise InvalidPart("},{"line_number":630,"context_line":"                upload_id\u003dself.upload_id,"},{"line_number":631,"context_line":"                part_number\u003dpart_number)"},{"line_number":632,"context_line":""},{"line_number":633,"context_line":"        full_object_part_checksum \u003d None"},{"line_number":634,"context_line":"        if self.mpu_checksum_attrs.is_full_object:"}],"source_content_type":"text/x-python","patch_set":92,"id":"3f8e9ef6_bcff78cb","line":631,"updated":"2026-08-12 16:06:26.000000000","message":"I don\u0027t think the outcome is predictable if we raise an exception here.\n\nthis code is called inside the response body iterator which in general is iterated *after* the response status and headers have been sent to the client, so we\u0027d get a 200 response status.\n\nExcept It\u0027s a little more complicated than that:\n\n1. multi_upload uses reiterate to read the first chunk of the response before sending the status - so yay this callback will be called during reiterate and raise its exception *before* we\u0027re sending the resp iter for real, except...\n2. slo sends heartbeat bytes ``b\u0027 \u0027`` before calling this hook, so multi_upload reiterate will be spent on reading a heartbeat\n3 but wait! multi_upload response_iter drops heartbeat bytes for the first 10 seconds, so the reiterate won\u0027t be spent reading heartbeats, so we\u0027re good??\n4. well no! we cannot assume that the hook is called within the first 10 seconds of the response, so we have to assume reiterate is already spent and the status is sent to clients before this hook executes, in which case raising an exception here will not change the status code (but will find its way to the response body)\n\nI think for a more predictable outcome the hook should always populate ``problem_segments`` and  leave slo to close out the response with an error body and then have multi_upload translate the segment errors to s3api error response body in the same way it does for too_small_part etc.","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":628,"context_line":"        elif stored_checksum_value !\u003d part_checksum_value:"},{"line_number":629,"context_line":"            raise InvalidPart("},{"line_number":630,"context_line":"                upload_id\u003dself.upload_id,"},{"line_number":631,"context_line":"                part_number\u003dpart_number)"},{"line_number":632,"context_line":""},{"line_number":633,"context_line":"        full_object_part_checksum \u003d None"},{"line_number":634,"context_line":"        if self.mpu_checksum_attrs.is_full_object:"}],"source_content_type":"text/x-python","patch_set":92,"id":"14350fea_03d5b918","line":631,"in_reply_to":"3f8e9ef6_bcff78cb","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":666,"context_line":"            self.mpu_checksum_attrs.checksum_value,"},{"line_number":667,"context_line":"            self.mpu_checksum_attrs.checksum_type))"},{"line_number":668,"context_line":""},{"line_number":669,"context_line":"    def __call__(self, manifest):"},{"line_number":670,"context_line":"        \"\"\"Validate the manifest and calculate its completed checksum.\"\"\""},{"line_number":671,"context_line":"        # Check the size of each segment except the last and make sure"},{"line_number":672,"context_line":"        # they are all more than the minimum upload chunk size."}],"source_content_type":"text/x-python","patch_set":92,"id":"67c2bf04_95686995","line":669,"updated":"2026-08-12 16:06:26.000000000","message":"this is the callback passed to slo; as such it should not raise any exceptions that slo is bot expecting to handle, which currently is none!\n\noff-topic: slo should probably wrap its call to the callback in a try/except to guard against unknown third party middlewares doing bad things\n\nUpdate: so there\u0027s cases where want the hook to report a non-part specific error (e.g. final checksum doesn\u0027t match), therefore we need to change the slo hook interface. Ideas:\n\n``return problem_segments, problem``\n\nor have slo try/except the hook and format any exception message into it\u0027s response body.","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":666,"context_line":"            self.mpu_checksum_attrs.checksum_value,"},{"line_number":667,"context_line":"            self.mpu_checksum_attrs.checksum_type))"},{"line_number":668,"context_line":""},{"line_number":669,"context_line":"    def __call__(self, manifest):"},{"line_number":670,"context_line":"        \"\"\"Validate the manifest and calculate its completed checksum.\"\"\""},{"line_number":671,"context_line":"        # Check the size of each segment except the last and make sure"},{"line_number":672,"context_line":"        # they are all more than the minimum upload chunk size."}],"source_content_type":"text/x-python","patch_set":92,"id":"0666c601_943a1d6c","line":669,"in_reply_to":"67c2bf04_95686995","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":672,"context_line":"        # they are all more than the minimum upload chunk size."},{"line_number":673,"context_line":"        # Note that we need to use the *internal* keys, since we\u0027re"},{"line_number":674,"context_line":"        # looking at the manifest that\u0027s about to be written."},{"line_number":675,"context_line":"        problem_segments \u003d ["},{"line_number":676,"context_line":"            (item[\u0027name\u0027], self.too_small_message)"},{"line_number":677,"context_line":"            for item in manifest[:-1]"},{"line_number":678,"context_line":"            if item and item[\u0027bytes\u0027] \u003c self.min_segment_size]"}],"source_content_type":"text/x-python","patch_set":92,"id":"cd10bea9_eb7590d3","line":675,"updated":"2026-08-12 16:06:26.000000000","message":"this iterates over the parts...and assumes they are all not None","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":false,"context_lines":[{"line_number":672,"context_line":"        # they are all more than the minimum upload chunk size."},{"line_number":673,"context_line":"        # Note that we need to use the *internal* keys, since we\u0027re"},{"line_number":674,"context_line":"        # looking at the manifest that\u0027s about to be written."},{"line_number":675,"context_line":"        problem_segments \u003d ["},{"line_number":676,"context_line":"            (item[\u0027name\u0027], self.too_small_message)"},{"line_number":677,"context_line":"            for item in manifest[:-1]"},{"line_number":678,"context_line":"            if item and item[\u0027bytes\u0027] \u003c self.min_segment_size]"}],"source_content_type":"text/x-python","patch_set":92,"id":"2e228079_a4aa6680","line":675,"in_reply_to":"cd10bea9_eb7590d3","updated":"2026-08-13 01:17:17.000000000","message":"Acknowledged","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":683,"context_line":"            return problem_segments"},{"line_number":684,"context_line":""},{"line_number":685,"context_line":"        # Make sure all the parts are valid before handling the MPU"},{"line_number":686,"context_line":"        segment_head_headers \u003d self._parse_segment_head_header(manifest)"},{"line_number":687,"context_line":"        stored_checksum_values \u003d self._validate_segment_head_headers("},{"line_number":688,"context_line":"            segment_head_headers)"},{"line_number":689,"context_line":"        if stored_checksum_values is None:"}],"source_content_type":"text/x-python","patch_set":92,"id":"732f5221_35b11d26","line":686,"updated":"2026-08-12 16:06:26.000000000","message":"this iterates over the parts...and allows for None","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":false,"context_lines":[{"line_number":683,"context_line":"            return problem_segments"},{"line_number":684,"context_line":""},{"line_number":685,"context_line":"        # Make sure all the parts are valid before handling the MPU"},{"line_number":686,"context_line":"        segment_head_headers \u003d self._parse_segment_head_header(manifest)"},{"line_number":687,"context_line":"        stored_checksum_values \u003d self._validate_segment_head_headers("},{"line_number":688,"context_line":"            segment_head_headers)"},{"line_number":689,"context_line":"        if stored_checksum_values is None:"}],"source_content_type":"text/x-python","patch_set":92,"id":"a0e9b1fe_46889438","line":686,"in_reply_to":"732f5221_35b11d26","updated":"2026-08-13 01:17:17.000000000","message":"Acknowledged","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":685,"context_line":"        # Make sure all the parts are valid before handling the MPU"},{"line_number":686,"context_line":"        segment_head_headers \u003d self._parse_segment_head_header(manifest)"},{"line_number":687,"context_line":"        stored_checksum_values \u003d self._validate_segment_head_headers("},{"line_number":688,"context_line":"            segment_head_headers)"},{"line_number":689,"context_line":"        if stored_checksum_values is None:"},{"line_number":690,"context_line":"            return problem_segments"},{"line_number":691,"context_line":""}],"source_content_type":"text/x-python","patch_set":92,"id":"6f4836f0_c190ee38","line":688,"updated":"2026-08-12 16:06:26.000000000","message":"this iterates over the parts...","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":685,"context_line":"        # Make sure all the parts are valid before handling the MPU"},{"line_number":686,"context_line":"        segment_head_headers \u003d self._parse_segment_head_header(manifest)"},{"line_number":687,"context_line":"        stored_checksum_values \u003d self._validate_segment_head_headers("},{"line_number":688,"context_line":"            segment_head_headers)"},{"line_number":689,"context_line":"        if stored_checksum_values is None:"},{"line_number":690,"context_line":"            return problem_segments"},{"line_number":691,"context_line":""}],"source_content_type":"text/x-python","patch_set":92,"id":"eaf81cca_d2e369fc","line":688,"in_reply_to":"6f4836f0_c190ee38","updated":"2026-08-13 01:17:17.000000000","message":"Yea we are clearly doing too much work here. I\u0027m sure it can be consolidated","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":685,"context_line":"        # Make sure all the parts are valid before handling the MPU"},{"line_number":686,"context_line":"        segment_head_headers \u003d self._parse_segment_head_header(manifest)"},{"line_number":687,"context_line":"        stored_checksum_values \u003d self._validate_segment_head_headers("},{"line_number":688,"context_line":"            segment_head_headers)"},{"line_number":689,"context_line":"        if stored_checksum_values is None:"},{"line_number":690,"context_line":"            return problem_segments"},{"line_number":691,"context_line":""}],"source_content_type":"text/x-python","patch_set":92,"id":"0ab74b49_601ab101","line":688,"in_reply_to":"eaf81cca_d2e369fc","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":1261,"context_line":"                request_checksum_attrs.checksum_type !\u003d"},{"line_number":1262,"context_line":"                mpu_checksum_attrs.checksum_type):"},{"line_number":1263,"context_line":"            raise InvalidRequest("},{"line_number":1264,"context_line":"                \u0027The upload was created using the %s checksum mode. \u0027"},{"line_number":1265,"context_line":"                \u0027The complete request must use the same checksum mode.\u0027 %"},{"line_number":1266,"context_line":"                mpu_checksum_attrs.checksum_type)"},{"line_number":1267,"context_line":""}],"source_content_type":"text/x-python","patch_set":92,"id":"8381afc1_20f1a76c","line":1264,"range":{"start_line":1264,"start_character":62,"end_line":1264,"end_character":66},"updated":"2026-08-12 16:06:26.000000000","message":"does AWS switch between using \u0027type\u0027 and \u0027mode\u0027 when referring to x-amz-checksum-type?\n\nA: yes it does! I see there is a compat test assertion for the message in test_mpu_complete_rejects_checksum_type_mismatch","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":1261,"context_line":"                request_checksum_attrs.checksum_type !\u003d"},{"line_number":1262,"context_line":"                mpu_checksum_attrs.checksum_type):"},{"line_number":1263,"context_line":"            raise InvalidRequest("},{"line_number":1264,"context_line":"                \u0027The upload was created using the %s checksum mode. \u0027"},{"line_number":1265,"context_line":"                \u0027The complete request must use the same checksum mode.\u0027 %"},{"line_number":1266,"context_line":"                mpu_checksum_attrs.checksum_type)"},{"line_number":1267,"context_line":""}],"source_content_type":"text/x-python","patch_set":92,"id":"f33a2a42_23adfc08","line":1264,"range":{"start_line":1264,"start_character":62,"end_line":1264,"end_character":66},"in_reply_to":"8381afc1_20f1a76c","updated":"2026-08-14 14:35:38.000000000","message":"Acknowledged","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":1270,"context_line":"                (mpu_checksum_attrs.is_checksum_aware or"},{"line_number":1271,"context_line":"                 mpu_checksum_attrs.has_completed_checksum) and"},{"line_number":1272,"context_line":"                request_checksum_attrs.checksum_header !\u003d"},{"line_number":1273,"context_line":"                mpu_checksum_attrs.checksum_header.lower()):"},{"line_number":1274,"context_line":"            raise InvalidRequest("},{"line_number":1275,"context_line":"                \u0027Checksum Type mismatch occurred, expected checksum \u0027"},{"line_number":1276,"context_line":"                \u0027Type: %s, actual checksum Type: %s\u0027 % ("}],"source_content_type":"text/x-python","patch_set":92,"id":"bedceca3_3ef28055","line":1273,"range":{"start_line":1273,"start_character":50,"end_line":1273,"end_character":58},"updated":"2026-08-12 16:06:26.000000000","message":"if we need to use lower here then MPUChecksumAttrs hasn\u0027t done it\u0027s job :) Normalise all the properties in the MPUChecksumAttrs constructor","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":1270,"context_line":"                (mpu_checksum_attrs.is_checksum_aware or"},{"line_number":1271,"context_line":"                 mpu_checksum_attrs.has_completed_checksum) and"},{"line_number":1272,"context_line":"                request_checksum_attrs.checksum_header !\u003d"},{"line_number":1273,"context_line":"                mpu_checksum_attrs.checksum_header.lower()):"},{"line_number":1274,"context_line":"            raise InvalidRequest("},{"line_number":1275,"context_line":"                \u0027Checksum Type mismatch occurred, expected checksum \u0027"},{"line_number":1276,"context_line":"                \u0027Type: %s, actual checksum Type: %s\u0027 % ("}],"source_content_type":"text/x-python","patch_set":92,"id":"b0809d89_176cbd70","line":1273,"range":{"start_line":1273,"start_character":50,"end_line":1273,"end_character":58},"in_reply_to":"7262a7ec_57867f2e","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":1270,"context_line":"                (mpu_checksum_attrs.is_checksum_aware or"},{"line_number":1271,"context_line":"                 mpu_checksum_attrs.has_completed_checksum) and"},{"line_number":1272,"context_line":"                request_checksum_attrs.checksum_header !\u003d"},{"line_number":1273,"context_line":"                mpu_checksum_attrs.checksum_header.lower()):"},{"line_number":1274,"context_line":"            raise InvalidRequest("},{"line_number":1275,"context_line":"                \u0027Checksum Type mismatch occurred, expected checksum \u0027"},{"line_number":1276,"context_line":"                \u0027Type: %s, actual checksum Type: %s\u0027 % ("}],"source_content_type":"text/x-python","patch_set":92,"id":"7262a7ec_57867f2e","line":1273,"range":{"start_line":1273,"start_character":50,"end_line":1273,"end_character":58},"in_reply_to":"bedceca3_3ef28055","updated":"2026-08-13 01:17:17.000000000","message":"Oh yea thanks for the catch!","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":1319,"context_line":"        container \u003d req.container_name + MULTIUPLOAD_SUFFIX"},{"line_number":1320,"context_line":"        s3_etag_hasher \u003d md5(usedforsecurity\u003dFalse)"},{"line_number":1321,"context_line":"        manifest \u003d []"},{"line_number":1322,"context_line":"        manifest_part_checksums \u003d []"},{"line_number":1323,"context_line":"        previous_number \u003d 0"},{"line_number":1324,"context_line":"        try:"},{"line_number":1325,"context_line":"            xml \u003d req.xml(MAX_COMPLETE_UPLOAD_BODY_SIZE)"}],"source_content_type":"text/x-python","patch_set":92,"id":"30d9deb0_a5f8c351","line":1322,"updated":"2026-08-12 16:06:26.000000000","message":"I\u0027m inclined to think this might be better as a *dict* mapping part_number to checksum_value\n\n...or mapping part_number to checksum_info dict that gets populated with everything we need to track","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":1319,"context_line":"        container \u003d req.container_name + MULTIUPLOAD_SUFFIX"},{"line_number":1320,"context_line":"        s3_etag_hasher \u003d md5(usedforsecurity\u003dFalse)"},{"line_number":1321,"context_line":"        manifest \u003d []"},{"line_number":1322,"context_line":"        manifest_part_checksums \u003d []"},{"line_number":1323,"context_line":"        previous_number \u003d 0"},{"line_number":1324,"context_line":"        try:"},{"line_number":1325,"context_line":"            xml \u003d req.xml(MAX_COMPLETE_UPLOAD_BODY_SIZE)"}],"source_content_type":"text/x-python","patch_set":92,"id":"763f5bbe_de55d1cb","line":1322,"in_reply_to":"30d9deb0_a5f8c351","updated":"2026-08-13 01:17:17.000000000","message":"Maybe something like\n```\nif mpu_checksum_attrs.is_checksum_aware:\n  part_checksums.append({\n    \u0027part_number\u0027: part_number,\n    \u0027manifest_checksum_value\u0027:\n      _validate_request_manifest_checksum_part(\n        part_elem, mpu_checksum_attrs),\n      })\n```\n\nI would like to use `manifest` but we would have to then delete the `checksum_info` later which might be annoying","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":1319,"context_line":"        container \u003d req.container_name + MULTIUPLOAD_SUFFIX"},{"line_number":1320,"context_line":"        s3_etag_hasher \u003d md5(usedforsecurity\u003dFalse)"},{"line_number":1321,"context_line":"        manifest \u003d []"},{"line_number":1322,"context_line":"        manifest_part_checksums \u003d []"},{"line_number":1323,"context_line":"        previous_number \u003d 0"},{"line_number":1324,"context_line":"        try:"},{"line_number":1325,"context_line":"            xml \u003d req.xml(MAX_COMPLETE_UPLOAD_BODY_SIZE)"}],"source_content_type":"text/x-python","patch_set":92,"id":"00be8566_c40b5f8c","line":1322,"in_reply_to":"763f5bbe_de55d1cb","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":1362,"context_line":"                            part_elem, mpu_checksum_attrs)"},{"line_number":1363,"context_line":"                    manifest_part_checksums.append("},{"line_number":1364,"context_line":"                        (part_number, part_checksum_value,"},{"line_number":1365,"context_line":"                         part_checksum_raw))"},{"line_number":1366,"context_line":"                manifest.append({"},{"line_number":1367,"context_line":"                    \u0027path\u0027: \u0027/%s/%s/%s/%d\u0027 % ("},{"line_number":1368,"context_line":"                        wsgi_to_str(container), wsgi_to_str(req.object_name),"}],"source_content_type":"text/x-python","patch_set":92,"id":"5297dcfd_f51d2a1c","line":1365,"range":{"start_line":1365,"start_character":25,"end_line":1365,"end_character":42},"updated":"2026-08-12 16:06:26.000000000","message":"I realise we have decoded the manifest part checksum as part of validation, but is it necessary to then complicate interfaces by passing it around? could we just decode again later when necessary to calculate the final checksum. Then we can have a simpler dict of part_number -\u003e checksum_value that is passed around.\n\nor...just pass around a list of dicts that start to accumulate everything of interest...manifest checksum, decoded value, stored checksums etc, instead of lists of tuples of various metadata","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":1362,"context_line":"                            part_elem, mpu_checksum_attrs)"},{"line_number":1363,"context_line":"                    manifest_part_checksums.append("},{"line_number":1364,"context_line":"                        (part_number, part_checksum_value,"},{"line_number":1365,"context_line":"                         part_checksum_raw))"},{"line_number":1366,"context_line":"                manifest.append({"},{"line_number":1367,"context_line":"                    \u0027path\u0027: \u0027/%s/%s/%s/%d\u0027 % ("},{"line_number":1368,"context_line":"                        wsgi_to_str(container), wsgi_to_str(req.object_name),"}],"source_content_type":"text/x-python","patch_set":92,"id":"739a6596_f5434c21","line":1365,"range":{"start_line":1365,"start_character":25,"end_line":1365,"end_character":42},"in_reply_to":"5297dcfd_f51d2a1c","updated":"2026-08-13 01:17:17.000000000","message":"Yea I think this is complicating things just to save an extra computation, we can probably just do it again later","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":1362,"context_line":"                            part_elem, mpu_checksum_attrs)"},{"line_number":1363,"context_line":"                    manifest_part_checksums.append("},{"line_number":1364,"context_line":"                        (part_number, part_checksum_value,"},{"line_number":1365,"context_line":"                         part_checksum_raw))"},{"line_number":1366,"context_line":"                manifest.append({"},{"line_number":1367,"context_line":"                    \u0027path\u0027: \u0027/%s/%s/%s/%d\u0027 % ("},{"line_number":1368,"context_line":"                        wsgi_to_str(container), wsgi_to_str(req.object_name),"}],"source_content_type":"text/x-python","patch_set":92,"id":"b6fb8a4a_bd118602","line":1365,"range":{"start_line":1365,"start_character":25,"end_line":1365,"end_character":42},"in_reply_to":"739a6596_f5434c21","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":1421,"context_line":"        headers[get_container_update_override_key(\u0027etag\u0027)] \u003d c_etag"},{"line_number":1422,"context_line":""},{"line_number":1423,"context_line":"        # Make the state for the SLO Manifest hook"},{"line_number":1424,"context_line":"        too_small_message \u003d ("},{"line_number":1425,"context_line":"            \u0027s3api requires that each segment be at least %d bytes\u0027 %"},{"line_number":1426,"context_line":"            self.conf.min_segment_size)"},{"line_number":1427,"context_line":"        manifest_hook_state \u003d {"}],"source_content_type":"text/x-python","patch_set":92,"id":"f36b116f_9b721afa","line":1424,"range":{"start_line":1424,"start_character":8,"end_line":1424,"end_character":25},"updated":"2026-08-12 16:06:26.000000000","message":"_CompleteMultipartUploadSloManifestHook can build this string itself given that it is passed min_segments_size","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":1421,"context_line":"        headers[get_container_update_override_key(\u0027etag\u0027)] \u003d c_etag"},{"line_number":1422,"context_line":""},{"line_number":1423,"context_line":"        # Make the state for the SLO Manifest hook"},{"line_number":1424,"context_line":"        too_small_message \u003d ("},{"line_number":1425,"context_line":"            \u0027s3api requires that each segment be at least %d bytes\u0027 %"},{"line_number":1426,"context_line":"            self.conf.min_segment_size)"},{"line_number":1427,"context_line":"        manifest_hook_state \u003d {"}],"source_content_type":"text/x-python","patch_set":92,"id":"7bfaee0b_f852e15b","line":1424,"range":{"start_line":1424,"start_character":8,"end_line":1424,"end_character":25},"in_reply_to":"15e86f1a_4807a26a","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":1421,"context_line":"        headers[get_container_update_override_key(\u0027etag\u0027)] \u003d c_etag"},{"line_number":1422,"context_line":""},{"line_number":1423,"context_line":"        # Make the state for the SLO Manifest hook"},{"line_number":1424,"context_line":"        too_small_message \u003d ("},{"line_number":1425,"context_line":"            \u0027s3api requires that each segment be at least %d bytes\u0027 %"},{"line_number":1426,"context_line":"            self.conf.min_segment_size)"},{"line_number":1427,"context_line":"        manifest_hook_state \u003d {"}],"source_content_type":"text/x-python","patch_set":92,"id":"15e86f1a_4807a26a","line":1424,"range":{"start_line":1424,"start_character":8,"end_line":1424,"end_character":25},"in_reply_to":"f36b116f_9b721afa","updated":"2026-08-13 01:17:17.000000000","message":"Yep this works better I feel","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":1431,"context_line":"            \u0027mpu_checksum_attrs\u0027: mpu_checksum_attrs,"},{"line_number":1432,"context_line":"            \u0027request_checksum_attrs\u0027: request_checksum_attrs,"},{"line_number":1433,"context_line":"            \u0027manifest_part_checksums\u0027: manifest_part_checksums,"},{"line_number":1434,"context_line":"            \u0027footer_metadata\u0027: footer_metadata,"},{"line_number":1435,"context_line":"        }"},{"line_number":1436,"context_line":"        manifest_hook \u003d _CompleteMultipartUploadSloManifestHook("},{"line_number":1437,"context_line":"            manifest_hook_state)"}],"source_content_type":"text/x-python","patch_set":92,"id":"b03c2ff9_4016f843","line":1434,"range":{"start_line":1434,"start_character":12,"end_line":1434,"end_character":47},"updated":"2026-08-12 16:06:26.000000000","message":"it is generally frowned upon (but sometimes ok) to have a function/class mutate a variable it has been passed, and in this case it is unnecessary. \n\n_CompleteMultipartUploadSloManifestHook should have a boolean attribute that indicates if all the checksums were ok or not, and at line 1451 this can be checked before updating the request footers.","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":1431,"context_line":"            \u0027mpu_checksum_attrs\u0027: mpu_checksum_attrs,"},{"line_number":1432,"context_line":"            \u0027request_checksum_attrs\u0027: request_checksum_attrs,"},{"line_number":1433,"context_line":"            \u0027manifest_part_checksums\u0027: manifest_part_checksums,"},{"line_number":1434,"context_line":"            \u0027footer_metadata\u0027: footer_metadata,"},{"line_number":1435,"context_line":"        }"},{"line_number":1436,"context_line":"        manifest_hook \u003d _CompleteMultipartUploadSloManifestHook("},{"line_number":1437,"context_line":"            manifest_hook_state)"}],"source_content_type":"text/x-python","patch_set":92,"id":"fed58ba9_32a121f8","line":1434,"range":{"start_line":1434,"start_character":12,"end_line":1434,"end_character":47},"in_reply_to":"b03c2ff9_4016f843","updated":"2026-08-13 01:17:17.000000000","message":"Yea this can work better, I could see in the future someone mutating the footer metadata field and have some behavior we don\u0027t want","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":1431,"context_line":"            \u0027mpu_checksum_attrs\u0027: mpu_checksum_attrs,"},{"line_number":1432,"context_line":"            \u0027request_checksum_attrs\u0027: request_checksum_attrs,"},{"line_number":1433,"context_line":"            \u0027manifest_part_checksums\u0027: manifest_part_checksums,"},{"line_number":1434,"context_line":"            \u0027footer_metadata\u0027: footer_metadata,"},{"line_number":1435,"context_line":"        }"},{"line_number":1436,"context_line":"        manifest_hook \u003d _CompleteMultipartUploadSloManifestHook("},{"line_number":1437,"context_line":"            manifest_hook_state)"}],"source_content_type":"text/x-python","patch_set":92,"id":"dfd99a02_41cae670","line":1434,"range":{"start_line":1434,"start_character":12,"end_line":1434,"end_character":47},"in_reply_to":"fed58ba9_32a121f8","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":1434,"context_line":"            \u0027footer_metadata\u0027: footer_metadata,"},{"line_number":1435,"context_line":"        }"},{"line_number":1436,"context_line":"        manifest_hook \u003d _CompleteMultipartUploadSloManifestHook("},{"line_number":1437,"context_line":"            manifest_hook_state)"},{"line_number":1438,"context_line":"        req.environ[\u0027swift.callback.slo_manifest_hook\u0027] \u003d manifest_hook"},{"line_number":1439,"context_line":""},{"line_number":1440,"context_line":"        # SLO invokes the manifest hook before issuing the downstream manifest"}],"source_content_type":"text/x-python","patch_set":92,"id":"57c075a6_8ba572bc","line":1437,"updated":"2026-08-12 16:06:26.000000000","message":"-1, this isn\u0027t the way to pass args to a constructor. The __init__ should have keyword args for each key in manifest_hook_state , then dispense with manifest_hook_state  and just call the constructor with all the args\n\nmanifest_hook_state  is not used again","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":1434,"context_line":"            \u0027footer_metadata\u0027: footer_metadata,"},{"line_number":1435,"context_line":"        }"},{"line_number":1436,"context_line":"        manifest_hook \u003d _CompleteMultipartUploadSloManifestHook("},{"line_number":1437,"context_line":"            manifest_hook_state)"},{"line_number":1438,"context_line":"        req.environ[\u0027swift.callback.slo_manifest_hook\u0027] \u003d manifest_hook"},{"line_number":1439,"context_line":""},{"line_number":1440,"context_line":"        # SLO invokes the manifest hook before issuing the downstream manifest"}],"source_content_type":"text/x-python","patch_set":92,"id":"c7eafd44_8b991fd0","line":1437,"in_reply_to":"57c075a6_8ba572bc","updated":"2026-08-13 01:17:17.000000000","message":"I agree, the keyword args is much cleaner","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":1434,"context_line":"            \u0027footer_metadata\u0027: footer_metadata,"},{"line_number":1435,"context_line":"        }"},{"line_number":1436,"context_line":"        manifest_hook \u003d _CompleteMultipartUploadSloManifestHook("},{"line_number":1437,"context_line":"            manifest_hook_state)"},{"line_number":1438,"context_line":"        req.environ[\u0027swift.callback.slo_manifest_hook\u0027] \u003d manifest_hook"},{"line_number":1439,"context_line":""},{"line_number":1440,"context_line":"        # SLO invokes the manifest hook before issuing the downstream manifest"}],"source_content_type":"text/x-python","patch_set":92,"id":"471fe5cc_c1b632ef","line":1437,"in_reply_to":"c7eafd44_8b991fd0","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":1525,"context_line":"                    req, s3_etag, yielded_anything,"},{"line_number":1526,"context_line":"                    manifest_hook.mpu_checksum_attrs.checksum_header,"},{"line_number":1527,"context_line":"                    manifest_hook.mpu_checksum_attrs.checksum_value,"},{"line_number":1528,"context_line":"                    manifest_hook.mpu_checksum_attrs.checksum_type)"},{"line_number":1529,"context_line":"            except ErrorResponse as err_resp:"},{"line_number":1530,"context_line":"                if yielded_anything:"},{"line_number":1531,"context_line":"                    err_resp.xml_declaration \u003d False"}],"source_content_type":"text/x-python","patch_set":92,"id":"b87fbf65_bca5e863","line":1528,"updated":"2026-08-12 16:06:26.000000000","message":"you don\u0027t need to retrieve these from the hook, you already have them","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":false,"context_lines":[{"line_number":1525,"context_line":"                    req, s3_etag, yielded_anything,"},{"line_number":1526,"context_line":"                    manifest_hook.mpu_checksum_attrs.checksum_header,"},{"line_number":1527,"context_line":"                    manifest_hook.mpu_checksum_attrs.checksum_value,"},{"line_number":1528,"context_line":"                    manifest_hook.mpu_checksum_attrs.checksum_type)"},{"line_number":1529,"context_line":"            except ErrorResponse as err_resp:"},{"line_number":1530,"context_line":"                if yielded_anything:"},{"line_number":1531,"context_line":"                    err_resp.xml_declaration \u003d False"}],"source_content_type":"text/x-python","patch_set":92,"id":"975d0686_285deaad","line":1528,"in_reply_to":"0bd2a4c8_f5c470dd","updated":"2026-08-14 14:35:38.000000000","message":"Done","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7c1846e16387106b661b43dd9c2919d8ca460721","unresolved":true,"context_lines":[{"line_number":1525,"context_line":"                    req, s3_etag, yielded_anything,"},{"line_number":1526,"context_line":"                    manifest_hook.mpu_checksum_attrs.checksum_header,"},{"line_number":1527,"context_line":"                    manifest_hook.mpu_checksum_attrs.checksum_value,"},{"line_number":1528,"context_line":"                    manifest_hook.mpu_checksum_attrs.checksum_type)"},{"line_number":1529,"context_line":"            except ErrorResponse as err_resp:"},{"line_number":1530,"context_line":"                if yielded_anything:"},{"line_number":1531,"context_line":"                    err_resp.xml_declaration \u003d False"}],"source_content_type":"text/x-python","patch_set":92,"id":"0bd2a4c8_f5c470dd","line":1528,"in_reply_to":"b87fbf65_bca5e863","updated":"2026-08-13 01:17:17.000000000","message":"Good point, we can just use the local one","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c088400f7f645e4903a28581405d46f30ff288e","unresolved":true,"context_lines":[{"line_number":586,"context_line":"    @property"},{"line_number":587,"context_line":"    def final_checksum_calculated(self):"},{"line_number":588,"context_line":"        \"\"\"Return whether the hook produced final checksum metadata.\"\"\""},{"line_number":589,"context_line":"        return self.final_checksum_value is not None"},{"line_number":590,"context_line":""},{"line_number":591,"context_line":"    def _clear_checksum_variables(self):"},{"line_number":592,"context_line":"        \"\"\"Clear MPU and final checksum state for checksum-less fallback.\"\"\""}],"source_content_type":"text/x-python","patch_set":93,"id":"f62aaf5e_09e76f35","line":589,"updated":"2026-08-13 16:37:29.000000000","message":"overkill, callers can just test ``self.final_checksum_value is not None``","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":586,"context_line":"    @property"},{"line_number":587,"context_line":"    def final_checksum_calculated(self):"},{"line_number":588,"context_line":"        \"\"\"Return whether the hook produced final checksum metadata.\"\"\""},{"line_number":589,"context_line":"        return self.final_checksum_value is not None"},{"line_number":590,"context_line":""},{"line_number":591,"context_line":"    def _clear_checksum_variables(self):"},{"line_number":592,"context_line":"        \"\"\"Clear MPU and final checksum state for checksum-less fallback.\"\"\""}],"source_content_type":"text/x-python","patch_set":93,"id":"6762c5bc_a907abf3","line":589,"in_reply_to":"231544e9_d5b29ade","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3e05b45c3062aeed117e41f50c3cdb33487a532d","unresolved":true,"context_lines":[{"line_number":586,"context_line":"    @property"},{"line_number":587,"context_line":"    def final_checksum_calculated(self):"},{"line_number":588,"context_line":"        \"\"\"Return whether the hook produced final checksum metadata.\"\"\""},{"line_number":589,"context_line":"        return self.final_checksum_value is not None"},{"line_number":590,"context_line":""},{"line_number":591,"context_line":"    def _clear_checksum_variables(self):"},{"line_number":592,"context_line":"        \"\"\"Clear MPU and final checksum state for checksum-less fallback.\"\"\""}],"source_content_type":"text/x-python","patch_set":93,"id":"231544e9_d5b29ade","line":589,"in_reply_to":"f62aaf5e_09e76f35","updated":"2026-08-13 23:44:17.000000000","message":"Yea I can see that","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c088400f7f645e4903a28581405d46f30ff288e","unresolved":true,"context_lines":[{"line_number":593,"context_line":"        self.mpu_checksum_attrs.checksum_header \u003d None"},{"line_number":594,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d None"},{"line_number":595,"context_line":"        self.mpu_checksum_attrs.checksum_type \u003d None"},{"line_number":596,"context_line":"        self.mpu_checksum_attrs.is_mpu_in_progress \u003d False"},{"line_number":597,"context_line":"        self.final_checksum_header \u003d None"},{"line_number":598,"context_line":"        self.final_checksum_value \u003d None"},{"line_number":599,"context_line":"        self.final_checksum_type \u003d None"}],"source_content_type":"text/x-python","patch_set":93,"id":"e019ca77_d17bd099","line":596,"updated":"2026-08-13 16:37:29.000000000","message":"these side-effects should be avoided; just give the hook a boolean that indicates if the final checksum is available or not","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3e05b45c3062aeed117e41f50c3cdb33487a532d","unresolved":true,"context_lines":[{"line_number":593,"context_line":"        self.mpu_checksum_attrs.checksum_header \u003d None"},{"line_number":594,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d None"},{"line_number":595,"context_line":"        self.mpu_checksum_attrs.checksum_type \u003d None"},{"line_number":596,"context_line":"        self.mpu_checksum_attrs.is_mpu_in_progress \u003d False"},{"line_number":597,"context_line":"        self.final_checksum_header \u003d None"},{"line_number":598,"context_line":"        self.final_checksum_value \u003d None"},{"line_number":599,"context_line":"        self.final_checksum_type \u003d None"}],"source_content_type":"text/x-python","patch_set":93,"id":"fe1211ef_7d5bf80a","line":596,"in_reply_to":"e019ca77_d17bd099","updated":"2026-08-13 23:44:17.000000000","message":"Yea this can be much cleaner","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":593,"context_line":"        self.mpu_checksum_attrs.checksum_header \u003d None"},{"line_number":594,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d None"},{"line_number":595,"context_line":"        self.mpu_checksum_attrs.checksum_type \u003d None"},{"line_number":596,"context_line":"        self.mpu_checksum_attrs.is_mpu_in_progress \u003d False"},{"line_number":597,"context_line":"        self.final_checksum_header \u003d None"},{"line_number":598,"context_line":"        self.final_checksum_value \u003d None"},{"line_number":599,"context_line":"        self.final_checksum_type \u003d None"}],"source_content_type":"text/x-python","patch_set":93,"id":"626a9ca6_2c2e1b4a","line":596,"in_reply_to":"fe1211ef_7d5bf80a","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c088400f7f645e4903a28581405d46f30ff288e","unresolved":true,"context_lines":[{"line_number":594,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d None"},{"line_number":595,"context_line":"        self.mpu_checksum_attrs.checksum_type \u003d None"},{"line_number":596,"context_line":"        self.mpu_checksum_attrs.is_mpu_in_progress \u003d False"},{"line_number":597,"context_line":"        self.final_checksum_header \u003d None"},{"line_number":598,"context_line":"        self.final_checksum_value \u003d None"},{"line_number":599,"context_line":"        self.final_checksum_type \u003d None"},{"line_number":600,"context_line":""}],"source_content_type":"text/x-python","patch_set":93,"id":"a0a39921_1f02bcf1","line":597,"range":{"start_line":597,"start_character":37,"end_line":597,"end_character":41},"updated":"2026-08-13 16:37:29.000000000","message":"the tests all pass if this is \u0027x-banana\u0027 ;-)\n\nI don\u0027t think these attrs are used if there is no checksum","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":594,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d None"},{"line_number":595,"context_line":"        self.mpu_checksum_attrs.checksum_type \u003d None"},{"line_number":596,"context_line":"        self.mpu_checksum_attrs.is_mpu_in_progress \u003d False"},{"line_number":597,"context_line":"        self.final_checksum_header \u003d None"},{"line_number":598,"context_line":"        self.final_checksum_value \u003d None"},{"line_number":599,"context_line":"        self.final_checksum_type \u003d None"},{"line_number":600,"context_line":""}],"source_content_type":"text/x-python","patch_set":93,"id":"391078a0_60860150","line":597,"range":{"start_line":597,"start_character":37,"end_line":597,"end_character":41},"in_reply_to":"7b5680bb_c4e19f77","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3e05b45c3062aeed117e41f50c3cdb33487a532d","unresolved":true,"context_lines":[{"line_number":594,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d None"},{"line_number":595,"context_line":"        self.mpu_checksum_attrs.checksum_type \u003d None"},{"line_number":596,"context_line":"        self.mpu_checksum_attrs.is_mpu_in_progress \u003d False"},{"line_number":597,"context_line":"        self.final_checksum_header \u003d None"},{"line_number":598,"context_line":"        self.final_checksum_value \u003d None"},{"line_number":599,"context_line":"        self.final_checksum_type \u003d None"},{"line_number":600,"context_line":""}],"source_content_type":"text/x-python","patch_set":93,"id":"7b5680bb_c4e19f77","line":597,"range":{"start_line":597,"start_character":37,"end_line":597,"end_character":41},"in_reply_to":"a0a39921_1f02bcf1","updated":"2026-08-13 23:44:17.000000000","message":"Yea they are not, the final boolean seems a lot more enticing","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c088400f7f645e4903a28581405d46f30ff288e","unresolved":true,"context_lines":[{"line_number":708,"context_line":"                complete_checksum_value):"},{"line_number":709,"context_line":"            raise BadDigest("},{"line_number":710,"context_line":"                \u0027The %s you specified did not match the calculated \u0027"},{"line_number":711,"context_line":"                \u0027checksum.\u0027 % self.request_checksum_attrs.checksum_header)"},{"line_number":712,"context_line":"        return complete_checksum_value"},{"line_number":713,"context_line":""},{"line_number":714,"context_line":"    def __call__(self, manifest):"}],"source_content_type":"text/x-python","patch_set":93,"id":"124db541_b6ce885d","line":711,"updated":"2026-08-13 16:37:29.000000000","message":"I\u0027m still wary of these exceptions being raised inside the resp iter","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3e05b45c3062aeed117e41f50c3cdb33487a532d","unresolved":true,"context_lines":[{"line_number":708,"context_line":"                complete_checksum_value):"},{"line_number":709,"context_line":"            raise BadDigest("},{"line_number":710,"context_line":"                \u0027The %s you specified did not match the calculated \u0027"},{"line_number":711,"context_line":"                \u0027checksum.\u0027 % self.request_checksum_attrs.checksum_header)"},{"line_number":712,"context_line":"        return complete_checksum_value"},{"line_number":713,"context_line":""},{"line_number":714,"context_line":"    def __call__(self, manifest):"}],"source_content_type":"text/x-python","patch_set":93,"id":"a0e6b321_7e3f5c06","line":711,"in_reply_to":"124db541_b6ce885d","updated":"2026-08-13 23:44:17.000000000","message":"Yea I think the solution in 1000853: sq? make mpu manifest hook cache errors | https://review.opendev.org/c/openstack/swift/+/1000853 will fix this up","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":708,"context_line":"                complete_checksum_value):"},{"line_number":709,"context_line":"            raise BadDigest("},{"line_number":710,"context_line":"                \u0027The %s you specified did not match the calculated \u0027"},{"line_number":711,"context_line":"                \u0027checksum.\u0027 % self.request_checksum_attrs.checksum_header)"},{"line_number":712,"context_line":"        return complete_checksum_value"},{"line_number":713,"context_line":""},{"line_number":714,"context_line":"    def __call__(self, manifest):"}],"source_content_type":"text/x-python","patch_set":93,"id":"dfc3bf40_2826da89","line":711,"in_reply_to":"a0e6b321_7e3f5c06","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c088400f7f645e4903a28581405d46f30ff288e","unresolved":true,"context_lines":[{"line_number":724,"context_line":""},{"line_number":725,"context_line":"        # Calculate the final checksum for the response"},{"line_number":726,"context_line":"        self.final_checksum_value \u003d self._calculate_final_checksum()"},{"line_number":727,"context_line":"        self.final_checksum_header \u003d \\"},{"line_number":728,"context_line":"            self.mpu_checksum_attrs.checksum_header"},{"line_number":729,"context_line":"        self.final_checksum_type \u003d self.mpu_checksum_attrs.checksum_type"},{"line_number":730,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d self.final_checksum_value"},{"line_number":731,"context_line":"        return problem_segments"},{"line_number":732,"context_line":""}],"source_content_type":"text/x-python","patch_set":93,"id":"878ea13e_28c13036","line":729,"range":{"start_line":727,"start_character":8,"end_line":729,"end_character":72},"updated":"2026-08-13 16:37:29.000000000","message":"I can comment these out without breaking unit tests :(","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3e05b45c3062aeed117e41f50c3cdb33487a532d","unresolved":true,"context_lines":[{"line_number":724,"context_line":""},{"line_number":725,"context_line":"        # Calculate the final checksum for the response"},{"line_number":726,"context_line":"        self.final_checksum_value \u003d self._calculate_final_checksum()"},{"line_number":727,"context_line":"        self.final_checksum_header \u003d \\"},{"line_number":728,"context_line":"            self.mpu_checksum_attrs.checksum_header"},{"line_number":729,"context_line":"        self.final_checksum_type \u003d self.mpu_checksum_attrs.checksum_type"},{"line_number":730,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d self.final_checksum_value"},{"line_number":731,"context_line":"        return problem_segments"},{"line_number":732,"context_line":""}],"source_content_type":"text/x-python","patch_set":93,"id":"f6911e76_69da51dd","line":729,"range":{"start_line":727,"start_character":8,"end_line":729,"end_character":72},"in_reply_to":"878ea13e_28c13036","updated":"2026-08-13 23:44:17.000000000","message":"Its probably best to get rid of them then, thanks for catching this!","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":724,"context_line":""},{"line_number":725,"context_line":"        # Calculate the final checksum for the response"},{"line_number":726,"context_line":"        self.final_checksum_value \u003d self._calculate_final_checksum()"},{"line_number":727,"context_line":"        self.final_checksum_header \u003d \\"},{"line_number":728,"context_line":"            self.mpu_checksum_attrs.checksum_header"},{"line_number":729,"context_line":"        self.final_checksum_type \u003d self.mpu_checksum_attrs.checksum_type"},{"line_number":730,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d self.final_checksum_value"},{"line_number":731,"context_line":"        return problem_segments"},{"line_number":732,"context_line":""}],"source_content_type":"text/x-python","patch_set":93,"id":"6bb6efa3_12180e46","line":729,"range":{"start_line":727,"start_character":8,"end_line":729,"end_character":72},"in_reply_to":"f6911e76_69da51dd","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c088400f7f645e4903a28581405d46f30ff288e","unresolved":true,"context_lines":[{"line_number":727,"context_line":"        self.final_checksum_header \u003d \\"},{"line_number":728,"context_line":"            self.mpu_checksum_attrs.checksum_header"},{"line_number":729,"context_line":"        self.final_checksum_type \u003d self.mpu_checksum_attrs.checksum_type"},{"line_number":730,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d self.final_checksum_value"},{"line_number":731,"context_line":"        return problem_segments"},{"line_number":732,"context_line":""},{"line_number":733,"context_line":""}],"source_content_type":"text/x-python","patch_set":93,"id":"8a81d88e_b8a0c15b","line":730,"updated":"2026-08-13 16:37:29.000000000","message":"don\u0027t mutate this; avoid side-effects when possible; the resp_iter can just retrieve the final_checksum_value","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":727,"context_line":"        self.final_checksum_header \u003d \\"},{"line_number":728,"context_line":"            self.mpu_checksum_attrs.checksum_header"},{"line_number":729,"context_line":"        self.final_checksum_type \u003d self.mpu_checksum_attrs.checksum_type"},{"line_number":730,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d self.final_checksum_value"},{"line_number":731,"context_line":"        return problem_segments"},{"line_number":732,"context_line":""},{"line_number":733,"context_line":""}],"source_content_type":"text/x-python","patch_set":93,"id":"3c7a47c8_62d83127","line":730,"in_reply_to":"0e5ad1ab_586091b5","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3e05b45c3062aeed117e41f50c3cdb33487a532d","unresolved":true,"context_lines":[{"line_number":727,"context_line":"        self.final_checksum_header \u003d \\"},{"line_number":728,"context_line":"            self.mpu_checksum_attrs.checksum_header"},{"line_number":729,"context_line":"        self.final_checksum_type \u003d self.mpu_checksum_attrs.checksum_type"},{"line_number":730,"context_line":"        self.mpu_checksum_attrs.checksum_value \u003d self.final_checksum_value"},{"line_number":731,"context_line":"        return problem_segments"},{"line_number":732,"context_line":""},{"line_number":733,"context_line":""}],"source_content_type":"text/x-python","patch_set":93,"id":"0e5ad1ab_586091b5","line":730,"in_reply_to":"8a81d88e_b8a0c15b","updated":"2026-08-13 23:44:17.000000000","message":"Noted","commit_id":"1734fb8c60562d4f346cb4fb38612206211c46fe"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":true,"context_lines":[{"line_number":141,"context_line":"    def __init__(self, checksum_header\u003dNone, checksum_value\u003dNone,"},{"line_number":142,"context_line":"                 checksum_type\u003dNone, is_mpu_in_progress\u003dTrue):"},{"line_number":143,"context_line":"        \"\"\"Initialize a multipart upload checksum configuration.\"\"\""},{"line_number":144,"context_line":"        if checksum_header is not None:"},{"line_number":145,"context_line":"            checksum_header \u003d checksum_header.lower()"},{"line_number":146,"context_line":"        self.checksum_header \u003d checksum_header"},{"line_number":147,"context_line":"        self.checksum_value \u003d checksum_value"}],"source_content_type":"text/x-python","patch_set":94,"id":"219e1a7f_56819911","line":144,"updated":"2026-08-14 14:35:38.000000000","message":"given that the class name is ``MPUChecksumAttrs`` I think we could drop the ``checksum`` prefix on the attributes and save some screen real estate thoughout the module","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"010621ef8337f9eae1cb8e1ddaebffafe261c28b","unresolved":true,"context_lines":[{"line_number":141,"context_line":"    def __init__(self, checksum_header\u003dNone, checksum_value\u003dNone,"},{"line_number":142,"context_line":"                 checksum_type\u003dNone, is_mpu_in_progress\u003dTrue):"},{"line_number":143,"context_line":"        \"\"\"Initialize a multipart upload checksum configuration.\"\"\""},{"line_number":144,"context_line":"        if checksum_header is not None:"},{"line_number":145,"context_line":"            checksum_header \u003d checksum_header.lower()"},{"line_number":146,"context_line":"        self.checksum_header \u003d checksum_header"},{"line_number":147,"context_line":"        self.checksum_value \u003d checksum_value"}],"source_content_type":"text/x-python","patch_set":94,"id":"a7270b2e_9192f83d","line":144,"in_reply_to":"219e1a7f_56819911","updated":"2026-08-14 23:44:06.000000000","message":"Yea I think that can be good","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":141,"context_line":"    def __init__(self, checksum_header\u003dNone, checksum_value\u003dNone,"},{"line_number":142,"context_line":"                 checksum_type\u003dNone, is_mpu_in_progress\u003dTrue):"},{"line_number":143,"context_line":"        \"\"\"Initialize a multipart upload checksum configuration.\"\"\""},{"line_number":144,"context_line":"        if checksum_header is not None:"},{"line_number":145,"context_line":"            checksum_header \u003d checksum_header.lower()"},{"line_number":146,"context_line":"        self.checksum_header \u003d checksum_header"},{"line_number":147,"context_line":"        self.checksum_value \u003d checksum_value"}],"source_content_type":"text/x-python","patch_set":94,"id":"f047cb71_8840e21d","line":144,"in_reply_to":"a7270b2e_9192f83d","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":true,"context_lines":[{"line_number":390,"context_line":"        raise InvalidRequest("},{"line_number":391,"context_line":"            \u0027No checksum algorithm provided for this request. \u0027"},{"line_number":392,"context_line":"            \u0027This multipart upload requires %s.\u0027 %"},{"line_number":393,"context_line":"            checksum_attrs.checksum_algorithm)"},{"line_number":394,"context_line":""},{"line_number":395,"context_line":""},{"line_number":396,"context_line":"def _composite_checksum(checksum_header, part_checksums):"}],"source_content_type":"text/x-python","patch_set":94,"id":"10fe1565_09f45794","line":393,"range":{"start_line":393,"start_character":27,"end_line":393,"end_character":45},"updated":"2026-08-14 14:35:38.000000000","message":"this is anomalous use of the upper case version of algorithm in an error message - is that compatible with S3?\n\nI changed to lower and a unit test failed but not a compat test...worth checking with a compat test, I hate anomalies 😉","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"010621ef8337f9eae1cb8e1ddaebffafe261c28b","unresolved":true,"context_lines":[{"line_number":390,"context_line":"        raise InvalidRequest("},{"line_number":391,"context_line":"            \u0027No checksum algorithm provided for this request. \u0027"},{"line_number":392,"context_line":"            \u0027This multipart upload requires %s.\u0027 %"},{"line_number":393,"context_line":"            checksum_attrs.checksum_algorithm)"},{"line_number":394,"context_line":""},{"line_number":395,"context_line":""},{"line_number":396,"context_line":"def _composite_checksum(checksum_header, part_checksums):"}],"source_content_type":"text/x-python","patch_set":94,"id":"a27b1b11_69357365","line":393,"range":{"start_line":393,"start_character":27,"end_line":393,"end_character":45},"in_reply_to":"10fe1565_09f45794","updated":"2026-08-14 23:44:06.000000000","message":"Yea I can add one, I\u0027m pretty sure I manually tested this, but we should have compat test for all these things.\n\nActually we do have one! \n`test_composite_upload_part_requires_checksum`\nBut after handling the request message, AWS actually sends:\n```\nChecksum Type mismatch occurred, expected checksum Type: crc32,\nactual checksum Type: null\n```\nWhich is different... we should fix this up","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":390,"context_line":"        raise InvalidRequest("},{"line_number":391,"context_line":"            \u0027No checksum algorithm provided for this request. \u0027"},{"line_number":392,"context_line":"            \u0027This multipart upload requires %s.\u0027 %"},{"line_number":393,"context_line":"            checksum_attrs.checksum_algorithm)"},{"line_number":394,"context_line":""},{"line_number":395,"context_line":""},{"line_number":396,"context_line":"def _composite_checksum(checksum_header, part_checksums):"}],"source_content_type":"text/x-python","patch_set":94,"id":"b818c1eb_9f39542f","line":393,"range":{"start_line":393,"start_character":27,"end_line":393,"end_character":45},"in_reply_to":"a27b1b11_69357365","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":true,"context_lines":[{"line_number":1295,"context_line":"                \u0027Checksum Type mismatch occurred, expected checksum \u0027"},{"line_number":1296,"context_line":"                \u0027Type: %s, actual checksum Type: %s\u0027 % ("},{"line_number":1297,"context_line":"                    mpu_checksum_attrs.checksum_algorithm.lower(),"},{"line_number":1298,"context_line":"                    request_checksum_attrs.checksum_algorithm.lower()))"},{"line_number":1299,"context_line":""},{"line_number":1300,"context_line":"        marker_delta \u003d ("},{"line_number":1301,"context_line":"            float(Timestamp(resp.sw_headers.get(\u0027X-Backend-Timestamp\u0027, \u00270\u0027)))"}],"source_content_type":"text/x-python","patch_set":94,"id":"34f6b986_a0d0d6d9","line":1298,"updated":"2026-08-14 14:35:38.000000000","message":"pull these checks into a ``_validate_mpu_complete_checksum_headers`` method to mirror ``_validate_mpu_initiate_checksum_headers``","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"010621ef8337f9eae1cb8e1ddaebffafe261c28b","unresolved":true,"context_lines":[{"line_number":1295,"context_line":"                \u0027Checksum Type mismatch occurred, expected checksum \u0027"},{"line_number":1296,"context_line":"                \u0027Type: %s, actual checksum Type: %s\u0027 % ("},{"line_number":1297,"context_line":"                    mpu_checksum_attrs.checksum_algorithm.lower(),"},{"line_number":1298,"context_line":"                    request_checksum_attrs.checksum_algorithm.lower()))"},{"line_number":1299,"context_line":""},{"line_number":1300,"context_line":"        marker_delta \u003d ("},{"line_number":1301,"context_line":"            float(Timestamp(resp.sw_headers.get(\u0027X-Backend-Timestamp\u0027, \u00270\u0027)))"}],"source_content_type":"text/x-python","patch_set":94,"id":"ea376149_cce13404","line":1298,"in_reply_to":"34f6b986_a0d0d6d9","updated":"2026-08-14 23:44:06.000000000","message":"Good catch!","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1295,"context_line":"                \u0027Checksum Type mismatch occurred, expected checksum \u0027"},{"line_number":1296,"context_line":"                \u0027Type: %s, actual checksum Type: %s\u0027 % ("},{"line_number":1297,"context_line":"                    mpu_checksum_attrs.checksum_algorithm.lower(),"},{"line_number":1298,"context_line":"                    request_checksum_attrs.checksum_algorithm.lower()))"},{"line_number":1299,"context_line":""},{"line_number":1300,"context_line":"        marker_delta \u003d ("},{"line_number":1301,"context_line":"            float(Timestamp(resp.sw_headers.get(\u0027X-Backend-Timestamp\u0027, \u00270\u0027)))"}],"source_content_type":"text/x-python","patch_set":94,"id":"7945c04c_05e07ad2","line":1298,"in_reply_to":"ea376149_cce13404","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":true,"context_lines":[{"line_number":1375,"context_line":"                                      part_number\u003dpart_number,"},{"line_number":1376,"context_line":"                                      e_tag\u003detag)"},{"line_number":1377,"context_line":"                if mpu_checksum_attrs.is_checksum_aware:"},{"line_number":1378,"context_line":"                    part_checksums.append({"},{"line_number":1379,"context_line":"                        \u0027part_number\u0027: part_number,"},{"line_number":1380,"context_line":"                        \u0027manifest_checksum_value\u0027:"},{"line_number":1381,"context_line":"                            _validate_request_manifest_checksum_part("}],"source_content_type":"text/x-python","patch_set":94,"id":"a9620816_5d9d7123","line":1378,"range":{"start_line":1378,"start_character":20,"end_line":1378,"end_character":34},"updated":"2026-08-14 14:35:38.000000000","message":"for clarity it might be better to name this ``req_part_checksums`` and propagate that naming through the call stack","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1375,"context_line":"                                      part_number\u003dpart_number,"},{"line_number":1376,"context_line":"                                      e_tag\u003detag)"},{"line_number":1377,"context_line":"                if mpu_checksum_attrs.is_checksum_aware:"},{"line_number":1378,"context_line":"                    part_checksums.append({"},{"line_number":1379,"context_line":"                        \u0027part_number\u0027: part_number,"},{"line_number":1380,"context_line":"                        \u0027manifest_checksum_value\u0027:"},{"line_number":1381,"context_line":"                            _validate_request_manifest_checksum_part("}],"source_content_type":"text/x-python","patch_set":94,"id":"50af013c_a462ff66","line":1378,"range":{"start_line":1378,"start_character":20,"end_line":1378,"end_character":34},"in_reply_to":"366d92b7_25f01c52","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"010621ef8337f9eae1cb8e1ddaebffafe261c28b","unresolved":true,"context_lines":[{"line_number":1375,"context_line":"                                      part_number\u003dpart_number,"},{"line_number":1376,"context_line":"                                      e_tag\u003detag)"},{"line_number":1377,"context_line":"                if mpu_checksum_attrs.is_checksum_aware:"},{"line_number":1378,"context_line":"                    part_checksums.append({"},{"line_number":1379,"context_line":"                        \u0027part_number\u0027: part_number,"},{"line_number":1380,"context_line":"                        \u0027manifest_checksum_value\u0027:"},{"line_number":1381,"context_line":"                            _validate_request_manifest_checksum_part("}],"source_content_type":"text/x-python","patch_set":94,"id":"366d92b7_25f01c52","line":1378,"range":{"start_line":1378,"start_character":20,"end_line":1378,"end_character":34},"in_reply_to":"a9620816_5d9d7123","updated":"2026-08-14 23:44:06.000000000","message":"Yea this is a good idea, these slo segments vs request parts can get confusing 😵‍💫","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"78252a5289684d5435216957464d52ad9239fd41","unresolved":true,"context_lines":[{"line_number":1377,"context_line":"                if mpu_checksum_attrs.is_checksum_aware:"},{"line_number":1378,"context_line":"                    part_checksums.append({"},{"line_number":1379,"context_line":"                        \u0027part_number\u0027: part_number,"},{"line_number":1380,"context_line":"                        \u0027manifest_checksum_value\u0027:"},{"line_number":1381,"context_line":"                            _validate_request_manifest_checksum_part("},{"line_number":1382,"context_line":"                                part_elem, mpu_checksum_attrs),"},{"line_number":1383,"context_line":"                    })"}],"source_content_type":"text/x-python","patch_set":94,"id":"eeac575d_f00149c2","line":1380,"range":{"start_line":1380,"start_character":25,"end_line":1380,"end_character":34},"updated":"2026-08-14 14:35:38.000000000","message":"this data structure is only used to describe manifest parts so I think we could drop the manifest_prefix from the key perhaps? my concern is that it can be confused with \u0027manifest\u0027 as a whole checksum i.e. the \u0027final checksum\u0027","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1377,"context_line":"                if mpu_checksum_attrs.is_checksum_aware:"},{"line_number":1378,"context_line":"                    part_checksums.append({"},{"line_number":1379,"context_line":"                        \u0027part_number\u0027: part_number,"},{"line_number":1380,"context_line":"                        \u0027manifest_checksum_value\u0027:"},{"line_number":1381,"context_line":"                            _validate_request_manifest_checksum_part("},{"line_number":1382,"context_line":"                                part_elem, mpu_checksum_attrs),"},{"line_number":1383,"context_line":"                    })"}],"source_content_type":"text/x-python","patch_set":94,"id":"6f7b23f5_fff79efe","line":1380,"range":{"start_line":1380,"start_character":25,"end_line":1380,"end_character":34},"in_reply_to":"a39aecb9_6a23f3c0","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"010621ef8337f9eae1cb8e1ddaebffafe261c28b","unresolved":true,"context_lines":[{"line_number":1377,"context_line":"                if mpu_checksum_attrs.is_checksum_aware:"},{"line_number":1378,"context_line":"                    part_checksums.append({"},{"line_number":1379,"context_line":"                        \u0027part_number\u0027: part_number,"},{"line_number":1380,"context_line":"                        \u0027manifest_checksum_value\u0027:"},{"line_number":1381,"context_line":"                            _validate_request_manifest_checksum_part("},{"line_number":1382,"context_line":"                                part_elem, mpu_checksum_attrs),"},{"line_number":1383,"context_line":"                    })"}],"source_content_type":"text/x-python","patch_set":94,"id":"a39aecb9_6a23f3c0","line":1380,"range":{"start_line":1380,"start_character":25,"end_line":1380,"end_character":34},"in_reply_to":"eeac575d_f00149c2","updated":"2026-08-14 23:44:06.000000000","message":"Yea I could see that, its small enough too so I think dropping it can be a good idea!","commit_id":"5b5c8a2378c798025d8f185f69adecfe98a1c3f3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"831676e8a2c5d83317d1cd207585bc32c30a85ca","unresolved":false,"context_lines":[{"line_number":783,"context_line":"        elif missing_part_checksum:"},{"line_number":784,"context_line":"            return None"},{"line_number":785,"context_line":"        elif hasher:"},{"line_number":786,"context_line":"            if self.mpu_checksum_attrs.type \u003d\u003d CHECKSUM_TYPE_COMPOSITE:"},{"line_number":787,"context_line":"                # Update the SLO manifest so that HEAD/GET?partNumber"},{"line_number":788,"context_line":"                # requests can get the checksum without a segment HEAD request."},{"line_number":789,"context_line":"                # S3 only exposes part checksums for COMPOSITE MPUs."}],"source_content_type":"text/x-python","patch_set":98,"id":"ece7474d_9ab6922b","line":786,"range":{"start_line":786,"start_character":0,"end_line":786,"end_character":71},"updated":"2026-08-17 15:36:54.000000000","message":"This is more for future proofing checksums on MPUs when in the future we need to get the part checksums via a GetObject or HeadObject request. We ought to be able to support all checksum MPUs once we add that future, so might as well store the data we are going to need later.","commit_id":"a3c3c8aab342416d520a57f8787140e525bc3744"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"631c414471bcfdc40e9dbadd784e59fb07340166","unresolved":true,"context_lines":[{"line_number":789,"context_line":"                # S3 only exposes part checksums for COMPOSITE MPUs."},{"line_number":790,"context_line":"                for manifest_item, part_checksum_value in zip("},{"line_number":791,"context_line":"                        slo_manifest, part_checksum_values):"},{"line_number":792,"context_line":"                    manifest_item[S3API_PART_CHECKSUM_KEY] \u003d \\"},{"line_number":793,"context_line":"                        part_checksum_value"},{"line_number":794,"context_line":"            return hasher.base64digest()"},{"line_number":795,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":98,"id":"103e8158_d97f0a8d","line":792,"updated":"2026-08-18 14:49:44.000000000","message":"Manifests written here land on disk carrying `s3api_checksum`, which makes them permanently non-copyable: a manifest COPY validates the stored manifest as if it were new input, and parse_and_validate_input rejects the key with 400 \"Index 0: extraneous keys\".\n\nFor example:\n```\nfrom swift.common.middleware import slo\nimport json\nm \u003d [{\u0027path\u0027:\u0027/c/seg1\u0027,\u0027etag\u0027:\u0027a\u0027,\u0027size_bytes\u0027:100,\u0027s3api_checksum\u0027:\u0027CRC32:xxxx\u0027}]\ntry:\n    slo.parse_and_validate_input(json.dumps(m).encode(), \u0027/v1/a/c/man\u0027)\nexcept Exception as e:\n    print(e.status, e.body\n```","commit_id":"a3c3c8aab342416d520a57f8787140e525bc3744"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":789,"context_line":"                # S3 only exposes part checksums for COMPOSITE MPUs."},{"line_number":790,"context_line":"                for manifest_item, part_checksum_value in zip("},{"line_number":791,"context_line":"                        slo_manifest, part_checksum_values):"},{"line_number":792,"context_line":"                    manifest_item[S3API_PART_CHECKSUM_KEY] \u003d \\"},{"line_number":793,"context_line":"                        part_checksum_value"},{"line_number":794,"context_line":"            return hasher.base64digest()"},{"line_number":795,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":98,"id":"67f1433a_eb48f09a","line":792,"in_reply_to":"037cc2c2_d75fd567","updated":"2026-08-19 23:49:24.000000000","message":"Will think of a better solution to use the actual sysmeta","commit_id":"a3c3c8aab342416d520a57f8787140e525bc3744"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"586820f611a9f8aa1f45c9b0903b0f452387bfd5","unresolved":true,"context_lines":[{"line_number":789,"context_line":"                # S3 only exposes part checksums for COMPOSITE MPUs."},{"line_number":790,"context_line":"                for manifest_item, part_checksum_value in zip("},{"line_number":791,"context_line":"                        slo_manifest, part_checksum_values):"},{"line_number":792,"context_line":"                    manifest_item[S3API_PART_CHECKSUM_KEY] \u003d \\"},{"line_number":793,"context_line":"                        part_checksum_value"},{"line_number":794,"context_line":"            return hasher.base64digest()"},{"line_number":795,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":98,"id":"037cc2c2_d75fd567","line":792,"in_reply_to":"103e8158_d97f0a8d","updated":"2026-08-18 17:12:19.000000000","message":"Ah, yea then this will not work, we will need a better solution,\nwe might not be able to avoid HEADing the part to get the metadata...","commit_id":"a3c3c8aab342416d520a57f8787140e525bc3744"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a848964b37814e1d241fe3ba071f27207824fc0e","unresolved":true,"context_lines":[{"line_number":543,"context_line":"        if self.checksum_hasher.crc_combine_func is None:"},{"line_number":544,"context_line":"            raise S3NotImplemented("},{"line_number":545,"context_line":"                \u0027The %s algorithm is not supported for full object checksum \u0027"},{"line_number":546,"context_line":"                \u0027calculation.\u0027 % checksum_header)"},{"line_number":547,"context_line":"        self.crc \u003d 0"},{"line_number":548,"context_line":""},{"line_number":549,"context_line":"    def update(self, b64digest, bytes, *args, **kwargs):"}],"source_content_type":"text/x-python","patch_set":121,"id":"e0ad0942_1683fcad","line":546,"updated":"2026-08-26 16:56:52.000000000","message":"IIUC this isn\u0027t raised until we\u0027ve already passed a PUT request to SLO and it is making HEAD requests to part, but we could have failed much earlier in ``_validate_mpu_complete_checksum_headers``, similar to how the ``_validate_mpu_initiate_checksum_headers`` check fail if combine is not available?","commit_id":"c2096b3e5e55d0262b18863792d3b6d4de5671aa"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"e4d84b2c7fa04e798d57d0c80d39088029cd190a","unresolved":true,"context_lines":[{"line_number":543,"context_line":"        if self.checksum_hasher.crc_combine_func is None:"},{"line_number":544,"context_line":"            raise S3NotImplemented("},{"line_number":545,"context_line":"                \u0027The %s algorithm is not supported for full object checksum \u0027"},{"line_number":546,"context_line":"                \u0027calculation.\u0027 % checksum_header)"},{"line_number":547,"context_line":"        self.crc \u003d 0"},{"line_number":548,"context_line":""},{"line_number":549,"context_line":"    def update(self, b64digest, bytes, *args, **kwargs):"}],"source_content_type":"text/x-python","patch_set":121,"id":"ea4ad434_5d86432c","line":546,"in_reply_to":"e0ad0942_1683fcad","updated":"2026-08-26 17:21:38.000000000","message":"Oh this is a good point\nI was getting this confused with AWS\u0027s error order, but this is our error so its different! I will move this up so we don\u0027t call upon SLO to head segments","commit_id":"c2096b3e5e55d0262b18863792d3b6d4de5671aa"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"66055382ee9cd118215902933af39fed19b92497","unresolved":false,"context_lines":[{"line_number":543,"context_line":"        if self.checksum_hasher.crc_combine_func is None:"},{"line_number":544,"context_line":"            raise S3NotImplemented("},{"line_number":545,"context_line":"                \u0027The %s algorithm is not supported for full object checksum \u0027"},{"line_number":546,"context_line":"                \u0027calculation.\u0027 % checksum_header)"},{"line_number":547,"context_line":"        self.crc \u003d 0"},{"line_number":548,"context_line":""},{"line_number":549,"context_line":"    def update(self, b64digest, bytes, *args, **kwargs):"}],"source_content_type":"text/x-python","patch_set":121,"id":"4e310745_9dddb20b","line":546,"in_reply_to":"ea4ad434_5d86432c","updated":"2026-08-27 06:37:43.000000000","message":"Done","commit_id":"c2096b3e5e55d0262b18863792d3b6d4de5671aa"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c43861d91f11abdd8696e5ab6da7e328f4e9b321","unresolved":true,"context_lines":[{"line_number":457,"context_line":"        return None"},{"line_number":458,"context_line":"    request_checksum_header, request_checksum_value \u003d \\"},{"line_number":459,"context_line":"        _validate_part_checksum_occurrences(part_elem)"},{"line_number":460,"context_line":"    # The client should not give us a checksum in there"},{"line_number":461,"context_line":"    # request manifest if the MPU was not defined with one"},{"line_number":462,"context_line":"    if (request_checksum_header is not None and"},{"line_number":463,"context_line":"            not checksum_attrs.is_checksum_aware):"}],"source_content_type":"text/x-python","patch_set":134,"id":"fd9e3bfb_1723a57c","line":460,"range":{"start_line":460,"start_character":50,"end_line":460,"end_character":55},"updated":"2026-09-14 19:58:24.000000000","message":"\"their\"","commit_id":"4aedf6761dea26ea5f7c69ec1b75718f2f420e9e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0a70fc21f1287872786a623c93de2170cba79a9b","unresolved":false,"context_lines":[{"line_number":457,"context_line":"        return None"},{"line_number":458,"context_line":"    request_checksum_header, request_checksum_value \u003d \\"},{"line_number":459,"context_line":"        _validate_part_checksum_occurrences(part_elem)"},{"line_number":460,"context_line":"    # The client should not give us a checksum in there"},{"line_number":461,"context_line":"    # request manifest if the MPU was not defined with one"},{"line_number":462,"context_line":"    if (request_checksum_header is not None and"},{"line_number":463,"context_line":"            not checksum_attrs.is_checksum_aware):"}],"source_content_type":"text/x-python","patch_set":134,"id":"1a6f6269_eace5c13","line":460,"range":{"start_line":460,"start_character":50,"end_line":460,"end_character":55},"in_reply_to":"fd9e3bfb_1723a57c","updated":"2026-09-16 15:03:27.000000000","message":"Done","commit_id":"4aedf6761dea26ea5f7c69ec1b75718f2f420e9e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c43861d91f11abdd8696e5ab6da7e328f4e9b321","unresolved":true,"context_lines":[{"line_number":760,"context_line":"            raise InvalidPart("},{"line_number":761,"context_line":"                upload_id\u003dself.upload_id,"},{"line_number":762,"context_line":"                part_number\u003dreq_part_checksum[\u0027part_number\u0027],"},{"line_number":763,"context_line":"                e_tag\u003dreq_part_checksum[\u0027etag\u0027])"},{"line_number":764,"context_line":"        return stored_checksum_value"},{"line_number":765,"context_line":""},{"line_number":766,"context_line":"    def _validate_parts(self, slo_manifest):"}],"source_content_type":"text/x-python","patch_set":134,"id":"a8651523_b617abb5","line":763,"range":{"start_line":763,"start_character":16,"end_line":763,"end_character":21},"updated":"2026-09-14 19:58:24.000000000","message":"Really? We\u0027re only sending back the etag, when it was the checksum that was the problem? Is this what AWS does?","commit_id":"4aedf6761dea26ea5f7c69ec1b75718f2f420e9e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0a70fc21f1287872786a623c93de2170cba79a9b","unresolved":true,"context_lines":[{"line_number":760,"context_line":"            raise InvalidPart("},{"line_number":761,"context_line":"                upload_id\u003dself.upload_id,"},{"line_number":762,"context_line":"                part_number\u003dreq_part_checksum[\u0027part_number\u0027],"},{"line_number":763,"context_line":"                e_tag\u003dreq_part_checksum[\u0027etag\u0027])"},{"line_number":764,"context_line":"        return stored_checksum_value"},{"line_number":765,"context_line":""},{"line_number":766,"context_line":"    def _validate_parts(self, slo_manifest):"}],"source_content_type":"text/x-python","patch_set":134,"id":"a454ee4e_580a51e0","line":763,"range":{"start_line":763,"start_character":16,"end_line":763,"end_character":21},"in_reply_to":"51abe4e4_013cc705","updated":"2026-09-16 15:03:27.000000000","message":"added comment to remind us","commit_id":"4aedf6761dea26ea5f7c69ec1b75718f2f420e9e"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"def038ede734ad99fcc398086a4e26ee8eca1b98","unresolved":true,"context_lines":[{"line_number":760,"context_line":"            raise InvalidPart("},{"line_number":761,"context_line":"                upload_id\u003dself.upload_id,"},{"line_number":762,"context_line":"                part_number\u003dreq_part_checksum[\u0027part_number\u0027],"},{"line_number":763,"context_line":"                e_tag\u003dreq_part_checksum[\u0027etag\u0027])"},{"line_number":764,"context_line":"        return stored_checksum_value"},{"line_number":765,"context_line":""},{"line_number":766,"context_line":"    def _validate_parts(self, slo_manifest):"}],"source_content_type":"text/x-python","patch_set":134,"id":"51abe4e4_013cc705","line":763,"range":{"start_line":763,"start_character":16,"end_line":763,"end_character":21},"in_reply_to":"9101a871_b5bc64d2","updated":"2026-09-15 17:55:36.000000000","message":"Confirmed against AWS S3 with a CRC32 COMPOSITE MPU, which uploaded a part with the correct checksum, and then completed it with the correct ETag but an incorrect part checksum. AWS returned HTTP 400 InvalidPart with exactly Code, Message, UploadId, PartNumber, and ETag. The returned ETag matched the valid submitted ETag, and there was no checksum field.\n\nalso ran the cross-compat test ``TestObjectChecksumsMPUs::test_complete_bad_part_checksum_can_retry`` against AWS S3, it passed too.\n\nso AWS returns InvalidPart with the ETag even though the part checksum caused the failure.","commit_id":"4aedf6761dea26ea5f7c69ec1b75718f2f420e9e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"490b7e450cabf098550cfc62978ff43d5f19e614","unresolved":false,"context_lines":[{"line_number":760,"context_line":"            raise InvalidPart("},{"line_number":761,"context_line":"                upload_id\u003dself.upload_id,"},{"line_number":762,"context_line":"                part_number\u003dreq_part_checksum[\u0027part_number\u0027],"},{"line_number":763,"context_line":"                e_tag\u003dreq_part_checksum[\u0027etag\u0027])"},{"line_number":764,"context_line":"        return stored_checksum_value"},{"line_number":765,"context_line":""},{"line_number":766,"context_line":"    def _validate_parts(self, slo_manifest):"}],"source_content_type":"text/x-python","patch_set":134,"id":"27df6256_b20a65ea","line":763,"range":{"start_line":763,"start_character":16,"end_line":763,"end_character":21},"in_reply_to":"a454ee4e_580a51e0","updated":"2026-09-16 19:53:05.000000000","message":"And I see it\u0027s done -- thanks!","commit_id":"4aedf6761dea26ea5f7c69ec1b75718f2f420e9e"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ada1edab8ca0d62e32881cf1f40ece984da146a8","unresolved":true,"context_lines":[{"line_number":760,"context_line":"            raise InvalidPart("},{"line_number":761,"context_line":"                upload_id\u003dself.upload_id,"},{"line_number":762,"context_line":"                part_number\u003dreq_part_checksum[\u0027part_number\u0027],"},{"line_number":763,"context_line":"                e_tag\u003dreq_part_checksum[\u0027etag\u0027])"},{"line_number":764,"context_line":"        return stored_checksum_value"},{"line_number":765,"context_line":""},{"line_number":766,"context_line":"    def _validate_parts(self, slo_manifest):"}],"source_content_type":"text/x-python","patch_set":134,"id":"9101a871_b5bc64d2","line":763,"range":{"start_line":763,"start_character":16,"end_line":763,"end_character":21},"in_reply_to":"a8651523_b617abb5","updated":"2026-09-15 03:17:03.000000000","message":"Good question, checksum probably should be expected in the response. I will rerun this exact case against AWS and inspect the full error response before changing the implementation, and make sure this cross-compat test is correct: https://review.opendev.org/c/openstack/swift/+/993193/134/test/s3api/test_object_checksums.py#2436","commit_id":"4aedf6761dea26ea5f7c69ec1b75718f2f420e9e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0685a51f81f74568ad61287222cdb7a7e76dccdc","unresolved":true,"context_lines":[{"line_number":722,"context_line":"        stored_checksum_upload_id \u003d segment_head_headers.get("},{"line_number":723,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027))"},{"line_number":724,"context_line":"        if stored_checksum_upload_id !\u003d self.upload_id:"},{"line_number":725,"context_line":"            # An old proxy may upload a part without the upload-id"},{"line_number":726,"context_line":"            # sentinel. Fall back to completing without a checksum."},{"line_number":727,"context_line":"            return None"},{"line_number":728,"context_line":"        return stored_checksum_value"},{"line_number":729,"context_line":""}],"source_content_type":"text/x-python","patch_set":138,"id":"6ffc6d9b_04f5ae97","line":726,"range":{"start_line":725,"start_character":14,"end_line":726,"end_character":67},"updated":"2026-09-18 10:39:31.000000000","message":"I can\u0027t make sense of this comment:\n\nIf we have a checksum_value, why would we then return None? the reason is NOT that the part was uploaded via an old proxy, because if that was the case there would be no stored checksum value.\n\nI thought this was a guard against \"we have a checksum value but the part has been copied\". But I\u0027m not sure we need to have that guard any more because we no longer copy checksum sysmeta.","commit_id":"baf68678435dd89186c8e14aa9af72e5e7e1f3f2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"505cd7b64b3804d5ee146ec7e869a4e4b63d4566","unresolved":false,"context_lines":[{"line_number":722,"context_line":"        stored_checksum_upload_id \u003d segment_head_headers.get("},{"line_number":723,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027))"},{"line_number":724,"context_line":"        if stored_checksum_upload_id !\u003d self.upload_id:"},{"line_number":725,"context_line":"            # An old proxy may upload a part without the upload-id"},{"line_number":726,"context_line":"            # sentinel. Fall back to completing without a checksum."},{"line_number":727,"context_line":"            return None"},{"line_number":728,"context_line":"        return stored_checksum_value"},{"line_number":729,"context_line":""}],"source_content_type":"text/x-python","patch_set":138,"id":"9931eee1_cdf1f0f3","line":726,"range":{"start_line":725,"start_character":14,"end_line":726,"end_character":67},"in_reply_to":"6ffc6d9b_04f5ae97","updated":"2026-11-03 18:03:54.000000000","message":"Done","commit_id":"baf68678435dd89186c8e14aa9af72e5e7e1f3f2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0685a51f81f74568ad61287222cdb7a7e76dccdc","unresolved":true,"context_lines":[{"line_number":723,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027))"},{"line_number":724,"context_line":"        if stored_checksum_upload_id !\u003d self.upload_id:"},{"line_number":725,"context_line":"            # An old proxy may omit the sentinel or copy it from another"},{"line_number":726,"context_line":"            # upload. Fall back to completing without a checksum."},{"line_number":727,"context_line":"            return None"},{"line_number":728,"context_line":"        return stored_checksum_value"},{"line_number":729,"context_line":""}],"source_content_type":"text/x-python","patch_set":139,"id":"08b34661_31c8f8ec","line":726,"updated":"2026-09-18 10:39:31.000000000","message":"-1 for this change\n\nThis now implies that an old proxy may or may not include the sentinel. In fact, an old proxy will NEVER include a sentinel.\n\nAlso, sentinels cannot be copied because we now have a copy hook.","commit_id":"20c59d9bd2d964045ef583798f5b5a931492ffe3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"d1be75218d4b879c3aa3bfc9da40405dd1f61428","unresolved":true,"context_lines":[{"line_number":723,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027))"},{"line_number":724,"context_line":"        if stored_checksum_upload_id !\u003d self.upload_id:"},{"line_number":725,"context_line":"            # An old proxy may omit the sentinel or copy it from another"},{"line_number":726,"context_line":"            # upload. Fall back to completing without a checksum."},{"line_number":727,"context_line":"            return None"},{"line_number":728,"context_line":"        return stored_checksum_value"},{"line_number":729,"context_line":""}],"source_content_type":"text/x-python","patch_set":139,"id":"c26c03fc_1c8e6c28","line":726,"in_reply_to":"08b34661_31c8f8ec","updated":"2026-09-19 14:25:03.000000000","message":"I think this can still happen with proxy servers that do not know about removing s3 sysmeta on copy and those that do not know about checksums.\n\nSee https://review.opendev.org/c/openstack/swift/+/1002405/comment/fd1db2c6_f3eabb07/\nSure old proxies won\u0027t ever write a sentinel header, but an old proxy could copy a full object that has a checksum on it into a in progress MPU, which may be a ranged copy therefore leaving invalid checksum sysmeta on a part\n\nNo sentinel means that a new proxy did not upload it, leading us to assume some old proxy put this part into it so we cannot trust the checksum sysmeta.\n\n\nAlso the value guard:\n```\nif stored_checksum_upload_id !\u003d self.upload_id\n```\nReally only is needed if Swift client start copying objects","commit_id":"20c59d9bd2d964045ef583798f5b5a931492ffe3"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"d5e92a59427d5f329dd2bfeb753ed44727534a56","unresolved":true,"context_lines":[{"line_number":723,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027))"},{"line_number":724,"context_line":"        if stored_checksum_upload_id !\u003d self.upload_id:"},{"line_number":725,"context_line":"            # An old proxy may omit the sentinel or copy it from another"},{"line_number":726,"context_line":"            # upload. Fall back to completing without a checksum."},{"line_number":727,"context_line":"            return None"},{"line_number":728,"context_line":"        return stored_checksum_value"},{"line_number":729,"context_line":""}],"source_content_type":"text/x-python","patch_set":139,"id":"d0eece64_d3f351ed","line":726,"in_reply_to":"c26c03fc_1c8e6c28","updated":"2026-09-20 04:29:14.000000000","message":"ack, in this case old proxy means those upstream clusters with previous-release-not-master installed","commit_id":"20c59d9bd2d964045ef583798f5b5a931492ffe3"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"d1ef53b66075027ed4276cf04143f28ecdf8c716","unresolved":false,"context_lines":[{"line_number":723,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027))"},{"line_number":724,"context_line":"        if stored_checksum_upload_id !\u003d self.upload_id:"},{"line_number":725,"context_line":"            # An old proxy may omit the sentinel or copy it from another"},{"line_number":726,"context_line":"            # upload. Fall back to completing without a checksum."},{"line_number":727,"context_line":"            return None"},{"line_number":728,"context_line":"        return stored_checksum_value"},{"line_number":729,"context_line":""}],"source_content_type":"text/x-python","patch_set":139,"id":"cb0a485d_286cd174","line":726,"in_reply_to":"d0eece64_d3f351ed","updated":"2026-10-20 04:24:43.000000000","message":"upload_id based sentinel removed after feature flag is added.","commit_id":"20c59d9bd2d964045ef583798f5b5a931492ffe3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0685a51f81f74568ad61287222cdb7a7e76dccdc","unresolved":true,"context_lines":[{"line_number":754,"context_line":"            if segment_head_headers.get(s3api_sysmeta_header("},{"line_number":755,"context_line":"                    \u0027object\u0027, \u0027checksum-upload-id\u0027)) \u003d\u003d self.upload_id:"},{"line_number":756,"context_line":"                # The sentinel marks checksum persistence for this upload."},{"line_number":757,"context_line":"                # A missing or empty value makes the part invalid."},{"line_number":758,"context_line":"                raise InvalidPart("},{"line_number":759,"context_line":"                    upload_id\u003dself.upload_id,"},{"line_number":760,"context_line":"                    part_number\u003dreq_part_checksum[\u0027part_number\u0027],"}],"source_content_type":"text/x-python","patch_set":139,"id":"5d9c818b_01b1b21a","line":757,"updated":"2026-09-18 10:39:31.000000000","message":"how does ever happen? The sentinel is *only* written when checksum sysmeta is written https://review.opendev.org/c/openstack/swift/+/993193/138..139/swift/common/middleware/s3api/controllers/multi_upload.py#926","commit_id":"20c59d9bd2d964045ef583798f5b5a931492ffe3"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"d5e92a59427d5f329dd2bfeb753ed44727534a56","unresolved":false,"context_lines":[{"line_number":754,"context_line":"            if segment_head_headers.get(s3api_sysmeta_header("},{"line_number":755,"context_line":"                    \u0027object\u0027, \u0027checksum-upload-id\u0027)) \u003d\u003d self.upload_id:"},{"line_number":756,"context_line":"                # The sentinel marks checksum persistence for this upload."},{"line_number":757,"context_line":"                # A missing or empty value makes the part invalid."},{"line_number":758,"context_line":"                raise InvalidPart("},{"line_number":759,"context_line":"                    upload_id\u003dself.upload_id,"},{"line_number":760,"context_line":"                    part_number\u003dreq_part_checksum[\u0027part_number\u0027],"}],"source_content_type":"text/x-python","patch_set":139,"id":"7e9c910c_7f904054","line":757,"in_reply_to":"111d6556_bc685f61","updated":"2026-09-20 04:29:14.000000000","message":"I was thinking of encryption middleware changes, something like this:\n```\n1. The parts contain encrypted checksums and clear sentinels.\n2. The operator sets disable_encryption \u003d true and remove encryptor from the pipeline.\n3. MPU Completion arrives, its HEAD requests will see the sentinel but not the stored checksums.\n```\nbut it probably will be operator\u0027s mistake if they remove encryptor from pipeline after setting ``disable_encryption \u003d true``, it\u0027s possible but no need to worry about it, I can live with both ways.","commit_id":"20c59d9bd2d964045ef583798f5b5a931492ffe3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"d1be75218d4b879c3aa3bfc9da40405dd1f61428","unresolved":true,"context_lines":[{"line_number":754,"context_line":"            if segment_head_headers.get(s3api_sysmeta_header("},{"line_number":755,"context_line":"                    \u0027object\u0027, \u0027checksum-upload-id\u0027)) \u003d\u003d self.upload_id:"},{"line_number":756,"context_line":"                # The sentinel marks checksum persistence for this upload."},{"line_number":757,"context_line":"                # A missing or empty value makes the part invalid."},{"line_number":758,"context_line":"                raise InvalidPart("},{"line_number":759,"context_line":"                    upload_id\u003dself.upload_id,"},{"line_number":760,"context_line":"                    part_number\u003dreq_part_checksum[\u0027part_number\u0027],"}],"source_content_type":"text/x-python","patch_set":139,"id":"111d6556_bc685f61","line":757,"in_reply_to":"5d9c818b_01b1b21a","updated":"2026-09-19 14:25:03.000000000","message":"Yea I don\u0027t think this would be possible. We should toss it","commit_id":"20c59d9bd2d964045ef583798f5b5a931492ffe3"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"90eeada1e41b3d853021561a50c4a984dbde8d7c","unresolved":true,"context_lines":[{"line_number":334,"context_line":"    if mpu_checksum_attrs.is_mpu_in_progress:"},{"line_number":335,"context_line":"        # Make sure client supplied the same type as the CreateMultipartUpload"},{"line_number":336,"context_line":"        if (request_checksum_attrs.type and"},{"line_number":337,"context_line":"                request_checksum_attrs.type !\u003d mpu_checksum_attrs.type):"},{"line_number":338,"context_line":"            raise InvalidRequest("},{"line_number":339,"context_line":"                \u0027The upload was created using the %s checksum mode. \u0027"},{"line_number":340,"context_line":"                \u0027The complete request must use the same checksum mode.\u0027 %"}],"source_content_type":"text/x-python","patch_set":140,"id":"10748224_f4ad4791","line":337,"updated":"2026-10-19 05:06:37.000000000","message":"if the client creates MPU and uploads parts when allow_store_checksum is false, and then allow_store_checksum  is turned on, and client sends x-amz-checksum-type: COMPOSITE with completion. Swift compares that with the MPU’s absent type and returns HTTP 400 InvalidRequest:\n``The upload was created using the null checksum mode.``\n\nneed to add check ``mpu_checksum_attrs.is_checksum_aware and`` at here","commit_id":"4763b353e70f9684389ba5d7b48d5fb4b29232ca"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"d1ef53b66075027ed4276cf04143f28ecdf8c716","unresolved":false,"context_lines":[{"line_number":334,"context_line":"    if mpu_checksum_attrs.is_mpu_in_progress:"},{"line_number":335,"context_line":"        # Make sure client supplied the same type as the CreateMultipartUpload"},{"line_number":336,"context_line":"        if (request_checksum_attrs.type and"},{"line_number":337,"context_line":"                request_checksum_attrs.type !\u003d mpu_checksum_attrs.type):"},{"line_number":338,"context_line":"            raise InvalidRequest("},{"line_number":339,"context_line":"                \u0027The upload was created using the %s checksum mode. \u0027"},{"line_number":340,"context_line":"                \u0027The complete request must use the same checksum mode.\u0027 %"}],"source_content_type":"text/x-python","patch_set":140,"id":"d369c8e2_b675aee2","line":337,"in_reply_to":"10748224_f4ad4791","updated":"2026-10-20 04:24:43.000000000","message":"actually just to remove ``allow_store_checksums``.","commit_id":"4763b353e70f9684389ba5d7b48d5fb4b29232ca"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"90eeada1e41b3d853021561a50c4a984dbde8d7c","unresolved":true,"context_lines":[{"line_number":458,"context_line":"    part_checksum_header, part_checksum_value \u003d \\"},{"line_number":459,"context_line":"        _validate_part_checksum_occurrences(part_elem)"},{"line_number":460,"context_line":"    # The client should not include a checksum in the manifest part element if"},{"line_number":461,"context_line":"    # the MPU was not initiated with a checksum"},{"line_number":462,"context_line":"    if (part_checksum_header is not None and"},{"line_number":463,"context_line":"            not checksum_attrs.is_checksum_aware):"},{"line_number":464,"context_line":"        raise InvalidPart(upload_id\u003dupload_id, part_number\u003dpart_number,"}],"source_content_type":"text/x-python","patch_set":140,"id":"b7385d1b_b42f0644","line":461,"updated":"2026-10-19 05:06:37.000000000","message":"consider this case:\n```\n1.Initiate with the flag false. The client requests CRC32/COMPOSITE. Swift creates the MPU without storing those checksum settings.\n2.Enable the flag.\n3.UploadPart with a valid CRC32. Swift validates the checksum and returns the ETag, but it does not store or return the checksum.\n4.The client completes using its own saved CRC32. It can construct a XML because it calculated the checksum before uploading.\n```\nWith the flag now true, Swift returns HTTP 400 InvalidPart, even when the part exists, its ETag is correct, and the checksum is correct. The rejection occurs because the MPU has no stored checksum settings and the request contains a part checksum.\n\nadding below check will avoid this corner case\n```\n    if not checksum_attrs.is_checksum_aware:\n        # Checksum fields do not change a legacy MPU\u0027s checksum settings.\n        return None\n```","commit_id":"4763b353e70f9684389ba5d7b48d5fb4b29232ca"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"d1ef53b66075027ed4276cf04143f28ecdf8c716","unresolved":false,"context_lines":[{"line_number":458,"context_line":"    part_checksum_header, part_checksum_value \u003d \\"},{"line_number":459,"context_line":"        _validate_part_checksum_occurrences(part_elem)"},{"line_number":460,"context_line":"    # The client should not include a checksum in the manifest part element if"},{"line_number":461,"context_line":"    # the MPU was not initiated with a checksum"},{"line_number":462,"context_line":"    if (part_checksum_header is not None and"},{"line_number":463,"context_line":"            not checksum_attrs.is_checksum_aware):"},{"line_number":464,"context_line":"        raise InvalidPart(upload_id\u003dupload_id, part_number\u003dpart_number,"}],"source_content_type":"text/x-python","patch_set":140,"id":"b938ef67_f80c7b9a","line":461,"in_reply_to":"b7385d1b_b42f0644","updated":"2026-10-20 04:24:43.000000000","message":"Done","commit_id":"4763b353e70f9684389ba5d7b48d5fb4b29232ca"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"d1ef53b66075027ed4276cf04143f28ecdf8c716","unresolved":false,"context_lines":[{"line_number":423,"context_line":"        _validate_part_checksum_occurrences(part_elem)"},{"line_number":424,"context_line":"    if not checksum_attrs.is_checksum_aware:"},{"line_number":425,"context_line":"        # Keep legacy completion acceptance while checksum writes are off."},{"line_number":426,"context_line":"        if allow_store_checksums and part_checksum_header is not None:"},{"line_number":427,"context_line":"            raise InvalidPart(upload_id\u003dupload_id, part_number\u003dpart_number,"},{"line_number":428,"context_line":"                              e_tag\u003detag)"},{"line_number":429,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":143,"id":"e87b2b4e_1a0c4224","line":426,"updated":"2026-10-20 04:24:43.000000000","message":"this was an issue the other comment mentioned, the fix is to just remove this block.","commit_id":"6e458defdb216fff3bffb90fc3c3eb81a0a5e6cb"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"24401abc2518083e871cd82cb108bcbf58ffe20b","unresolved":true,"context_lines":[{"line_number":772,"context_line":"            if (index \u003c len(slo_manifest) - 1 and"},{"line_number":773,"context_line":"                    slo_manifest_item[\u0027bytes\u0027] \u003c self.min_segment_size):"},{"line_number":774,"context_line":"                # Save the size error and check the remaining parts."},{"line_number":775,"context_line":"                size_error \u003d size_error or EntityTooSmall("},{"line_number":776,"context_line":"                    \u0027s3api requires that each segment be at least \u0027"},{"line_number":777,"context_line":"                    \u0027%d bytes\u0027 % self.min_segment_size)"},{"line_number":778,"context_line":""}],"source_content_type":"text/x-python","patch_set":146,"id":"757aed0a_1671973d","line":775,"updated":"2026-10-22 14:42:01.000000000","message":"The response text from the AWS response. `size_error \u003d size_error or EntityTooSmall()` would fix this","commit_id":"3f4cf669533f582ee88099cfe083458a4762a72f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"dc33e0ba2f304fc6d904d8ef5efe1e3fd7cb102a","unresolved":false,"context_lines":[{"line_number":772,"context_line":"            if (index \u003c len(slo_manifest) - 1 and"},{"line_number":773,"context_line":"                    slo_manifest_item[\u0027bytes\u0027] \u003c self.min_segment_size):"},{"line_number":774,"context_line":"                # Save the size error and check the remaining parts."},{"line_number":775,"context_line":"                size_error \u003d size_error or EntityTooSmall("},{"line_number":776,"context_line":"                    \u0027s3api requires that each segment be at least \u0027"},{"line_number":777,"context_line":"                    \u0027%d bytes\u0027 % self.min_segment_size)"},{"line_number":778,"context_line":""}],"source_content_type":"text/x-python","patch_set":146,"id":"ca2dcd65_f4b2c627","line":775,"in_reply_to":"757aed0a_1671973d","updated":"2026-10-24 00:14:05.000000000","message":"fix squashed, thanks.","commit_id":"3f4cf669533f582ee88099cfe083458a4762a72f"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"0f1f244b1df7ec2ce0e02cbcaf3c2a748a6eeb71","unresolved":false,"context_lines":[{"line_number":772,"context_line":"            if (index \u003c len(slo_manifest) - 1 and"},{"line_number":773,"context_line":"                    slo_manifest_item[\u0027bytes\u0027] \u003c self.min_segment_size):"},{"line_number":774,"context_line":"                # Save the size error and check the remaining parts."},{"line_number":775,"context_line":"                size_error \u003d size_error or EntityTooSmall("},{"line_number":776,"context_line":"                    \u0027s3api requires that each segment be at least \u0027"},{"line_number":777,"context_line":"                    \u0027%d bytes\u0027 % self.min_segment_size)"},{"line_number":778,"context_line":""}],"source_content_type":"text/x-python","patch_set":146,"id":"2a7ee785_1044b05a","line":775,"in_reply_to":"ca2dcd65_f4b2c627","updated":"2026-10-26 12:52:53.000000000","message":"Thanks Jianjian!\n\nI just noticed that I cut my previous response accidentally. What I wanted to say:\n\nThe response text from the AWS responses is different, thus using a different message here returns two different responses for the same reasons to the client, depending on the request type. The default `EntitiyTooSmall()` should be ok for all cases?\n\n`size_error \u003d size_error or EntityTooSmall()` would fix this","commit_id":"3f4cf669533f582ee88099cfe083458a4762a72f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"505cd7b64b3804d5ee146ec7e869a4e4b63d4566","unresolved":true,"context_lines":[{"line_number":1474,"context_line":"        # SLO invokes the manifest hook before issuing the downstream manifest"},{"line_number":1475,"context_line":"        # PUT. By the time the object controller requests footers for that PUT,"},{"line_number":1476,"context_line":"        # the hook has calculated the final checksum metadata."},{"line_number":1477,"context_line":"        if self.conf.allow_store_checksums and \\"},{"line_number":1478,"context_line":"                mpu_checksum_attrs.is_checksum_aware:"},{"line_number":1479,"context_line":"            original_update_footers \u003d req.environ.get("},{"line_number":1480,"context_line":"                \u0027swift.callback.update_footers\u0027)"}],"source_content_type":"text/x-python","patch_set":151,"id":"0db3e6d5_caedac85","line":1477,"range":{"start_line":1477,"start_character":11,"end_line":1477,"end_character":42},"updated":"2026-11-03 18:03:54.000000000","message":"I\u0027m not convinced that this should be a condition at this point: if the mpu_checksum_attrs says that allow_store_checksums was true when the MPU was *created* then that should apply when the mpu is *completed*, regardless of what config the current proxy has.\n\nThis comment relates to similar comment about UploadPart - if the MPU session/marker object is has checksum  then subsequent requests for that MPU should persist checksums","commit_id":"c0decba0abfe2d2e63d37fe830f7aa12241aa609"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8ff438c2b150ab545e4183434c5ee41d79d9653a","unresolved":false,"context_lines":[{"line_number":1474,"context_line":"        # SLO invokes the manifest hook before issuing the downstream manifest"},{"line_number":1475,"context_line":"        # PUT. By the time the object controller requests footers for that PUT,"},{"line_number":1476,"context_line":"        # the hook has calculated the final checksum metadata."},{"line_number":1477,"context_line":"        if self.conf.allow_store_checksums and \\"},{"line_number":1478,"context_line":"                mpu_checksum_attrs.is_checksum_aware:"},{"line_number":1479,"context_line":"            original_update_footers \u003d req.environ.get("},{"line_number":1480,"context_line":"                \u0027swift.callback.update_footers\u0027)"}],"source_content_type":"text/x-python","patch_set":151,"id":"d8a13de1_0e0c94fe","line":1477,"range":{"start_line":1477,"start_character":11,"end_line":1477,"end_character":42},"in_reply_to":"0db3e6d5_caedac85","updated":"2026-11-04 17:27:35.000000000","message":"Done","commit_id":"c0decba0abfe2d2e63d37fe830f7aa12241aa609"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"505cd7b64b3804d5ee146ec7e869a4e4b63d4566","unresolved":true,"context_lines":[{"line_number":1484,"context_line":"                if original_update_footers:"},{"line_number":1485,"context_line":"                    original_update_footers(footers)"},{"line_number":1486,"context_line":"                checksum_value \u003d manifest_hook.final_checksum_value"},{"line_number":1487,"context_line":"                if checksum_value:"},{"line_number":1488,"context_line":"                    footers.update(checksum_sysmeta_headers("},{"line_number":1489,"context_line":"                        mpu_checksum_attrs.algorithm,"},{"line_number":1490,"context_line":"                        checksum_value,"}],"source_content_type":"text/x-python","patch_set":151,"id":"70b1625f_8f6ee16d","line":1487,"range":{"start_line":1487,"start_character":16,"end_line":1487,"end_character":33},"updated":"2026-11-03 18:03:54.000000000","message":"if any part was missing checksum sysmeta then we just quietly skip writing the checksum with the manifest...this is necessary with the patch as it is, but might not be if UploadPart just follows whatever the CreateMultipartUpload request determined w.r.t. checksum persistence.","commit_id":"c0decba0abfe2d2e63d37fe830f7aa12241aa609"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":true,"context_lines":[{"line_number":1484,"context_line":"                if original_update_footers:"},{"line_number":1485,"context_line":"                    original_update_footers(footers)"},{"line_number":1486,"context_line":"                checksum_value \u003d manifest_hook.final_checksum_value"},{"line_number":1487,"context_line":"                if checksum_value:"},{"line_number":1488,"context_line":"                    footers.update(checksum_sysmeta_headers("},{"line_number":1489,"context_line":"                        mpu_checksum_attrs.algorithm,"},{"line_number":1490,"context_line":"                        checksum_value,"}],"source_content_type":"text/x-python","patch_set":151,"id":"f8a3e83f_b44c3e81","line":1487,"range":{"start_line":1487,"start_character":16,"end_line":1487,"end_character":33},"in_reply_to":"70b1625f_8f6ee16d","updated":"2026-11-06 16:03:43.000000000","message":"this escape hatch is needed to handle UploadPartCopy not persisting checksums","commit_id":"c0decba0abfe2d2e63d37fe830f7aa12241aa609"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6cad42e81f4f38ab01e7b674efa84d2c2daa98ca","unresolved":true,"context_lines":[{"line_number":297,"context_line":"        raise InvalidRequest("},{"line_number":298,"context_line":"            \u0027Value for x-amz-checksum-type header is invalid.\u0027)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"    if mpu_checksum_attrs.is_mpu_in_progress:"},{"line_number":301,"context_line":"        # The completion type must match the stored initiation type."},{"line_number":302,"context_line":"        if (request_checksum_attrs.type and"},{"line_number":303,"context_line":"                mpu_checksum_attrs.is_checksum_aware and"}],"source_content_type":"text/x-python","patch_set":155,"id":"b312abda_93b65582","line":300,"updated":"2026-11-05 17:07:17.000000000","message":"ok, this test\ntest/s3api/test_object_checksums.py::TestObjectChecksumsMPUs::test_complete_retry_ignores_any_request_checksums_and_types\n\nseems to verify that the attrs are not checked if the complete is a repeat","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":false,"context_lines":[{"line_number":297,"context_line":"        raise InvalidRequest("},{"line_number":298,"context_line":"            \u0027Value for x-amz-checksum-type header is invalid.\u0027)"},{"line_number":299,"context_line":""},{"line_number":300,"context_line":"    if mpu_checksum_attrs.is_mpu_in_progress:"},{"line_number":301,"context_line":"        # The completion type must match the stored initiation type."},{"line_number":302,"context_line":"        if (request_checksum_attrs.type and"},{"line_number":303,"context_line":"                mpu_checksum_attrs.is_checksum_aware and"}],"source_content_type":"text/x-python","patch_set":155,"id":"dca39c0e_20ac506c","line":300,"in_reply_to":"b312abda_93b65582","updated":"2026-11-06 16:03:43.000000000","message":"Acknowledged","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6cad42e81f4f38ab01e7b674efa84d2c2daa98ca","unresolved":true,"context_lines":[{"line_number":409,"context_line":"    :return: The encoded checksum value, or ``None`` when the part does not"},{"line_number":410,"context_line":"        supply a checksum, the MPU is legacy, or it has already finished."},{"line_number":411,"context_line":"    \"\"\""},{"line_number":412,"context_line":"    if not checksum_attrs.is_mpu_in_progress:"},{"line_number":413,"context_line":"        # Once the upload has finished S3 replays it without looking at the"},{"line_number":414,"context_line":"        # checksums the client echoed back to us."},{"line_number":415,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":155,"id":"43928f9e_6ff58c4d","line":412,"updated":"2026-11-05 17:07:17.000000000","message":"ok, this condition seems to be covered by test/s3api/test_object_checksums.py::TestObjectChecksumsMPUs::test_complete_retry_ignores_any_request_checksums_and_types","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":false,"context_lines":[{"line_number":409,"context_line":"    :return: The encoded checksum value, or ``None`` when the part does not"},{"line_number":410,"context_line":"        supply a checksum, the MPU is legacy, or it has already finished."},{"line_number":411,"context_line":"    \"\"\""},{"line_number":412,"context_line":"    if not checksum_attrs.is_mpu_in_progress:"},{"line_number":413,"context_line":"        # Once the upload has finished S3 replays it without looking at the"},{"line_number":414,"context_line":"        # checksums the client echoed back to us."},{"line_number":415,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":155,"id":"1fe365fa_b0c82a45","line":412,"in_reply_to":"43928f9e_6ff58c4d","updated":"2026-11-06 16:03:43.000000000","message":"Acknowledged","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"8c7b5400e53bae1ec94e9d8d4a5c5854b2b7a066","unresolved":true,"context_lines":[{"line_number":775,"context_line":"            raise BadDigest("},{"line_number":776,"context_line":"                \u0027The %s you specified did not match the calculated \u0027"},{"line_number":777,"context_line":"                \u0027checksum.\u0027 %"},{"line_number":778,"context_line":"                self.request_checksum_attrs.algorithm.lower())"},{"line_number":779,"context_line":"        elif size_error:"},{"line_number":780,"context_line":"            raise size_error"},{"line_number":781,"context_line":"        elif part_checksum_error:"}],"source_content_type":"text/x-python","patch_set":158,"id":"7e7b0afc_6a6e6020","line":778,"updated":"2026-11-06 16:55:37.000000000","message":"Note if someone else stumbles upon this: the `.lower()` is a change to master - master uses `.upper()`:\n\nhttps://opendev.org/openstack/swift/src/branch/master/swift/common/middleware/s3api/s3checksum.py#L108\n\n`.lower()` (this change) is correct though. I stumbled upon this when testing using a wrong checksum on the complete request.","commit_id":"a9734eb9f2502c0bb44000f71bff578a31e5ccfa"}],"swift/common/middleware/s3api/controllers/obj.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8ff438c2b150ab545e4183434c5ee41d79d9653a","unresolved":true,"context_lines":[{"line_number":192,"context_line":"        if \u0027X-Amz-Copy-Source\u0027 in req.headers:"},{"line_number":193,"context_line":"            # note: checksum re-calculation while copying is not yet supported"},{"line_number":194,"context_line":"            req.check_copy_source(self.app)"},{"line_number":195,"context_line":"        elif self.conf.allow_store_checksums:"},{"line_number":196,"context_line":"            req.enable_checksum_persistence()"},{"line_number":197,"context_line":"        if not req.headers.get(\u0027Content-Type\u0027):"},{"line_number":198,"context_line":"            # can\u0027t setdefault because it can be None for some reason"}],"source_content_type":"text/x-python","patch_set":155,"id":"bdc49ba9_5d576a36","line":195,"updated":"2026-11-04 17:27:35.000000000","message":"I was expecting to see this change in the earlier patch for normal objects; ideally, for future us looking at code history, it would be less confusing for the S3Request.enable_checksum_persistence to change behaviour and then revert a few commits later. Also less confusing if this patch only touched multi_upload.py.\n\nIt\u0027s not just \u0027refactoring\u0027 - the UploadPart behaviour w.r.t. what gates part checksum persistence depends on this change.","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":false,"context_lines":[{"line_number":192,"context_line":"        if \u0027X-Amz-Copy-Source\u0027 in req.headers:"},{"line_number":193,"context_line":"            # note: checksum re-calculation while copying is not yet supported"},{"line_number":194,"context_line":"            req.check_copy_source(self.app)"},{"line_number":195,"context_line":"        elif self.conf.allow_store_checksums:"},{"line_number":196,"context_line":"            req.enable_checksum_persistence()"},{"line_number":197,"context_line":"        if not req.headers.get(\u0027Content-Type\u0027):"},{"line_number":198,"context_line":"            # can\u0027t setdefault because it can be None for some reason"}],"source_content_type":"text/x-python","patch_set":155,"id":"4c06b39c_3baf6e06","line":195,"in_reply_to":"1ba7ca0b_dc7b880b","updated":"2026-11-06 16:03:43.000000000","message":"Done","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1961762849e2fb744efb2c371a31a34a4ae2255e","unresolved":true,"context_lines":[{"line_number":192,"context_line":"        if \u0027X-Amz-Copy-Source\u0027 in req.headers:"},{"line_number":193,"context_line":"            # note: checksum re-calculation while copying is not yet supported"},{"line_number":194,"context_line":"            req.check_copy_source(self.app)"},{"line_number":195,"context_line":"        elif self.conf.allow_store_checksums:"},{"line_number":196,"context_line":"            req.enable_checksum_persistence()"},{"line_number":197,"context_line":"        if not req.headers.get(\u0027Content-Type\u0027):"},{"line_number":198,"context_line":"            # can\u0027t setdefault because it can be None for some reason"}],"source_content_type":"text/x-python","patch_set":155,"id":"f41c3308_1a6c5c34","line":195,"in_reply_to":"bdc49ba9_5d576a36","updated":"2026-11-05 04:05:49.000000000","message":"if we end up squashing those patches into one or two, the order won\u0027t matter. we can make that decision later.\n\nwell, it was a design choice, falling back to legacy MPU during config change window was also a safe practice.","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"beb155f5561f41c782c8652a2671e7c06518d34d","unresolved":true,"context_lines":[{"line_number":192,"context_line":"        if \u0027X-Amz-Copy-Source\u0027 in req.headers:"},{"line_number":193,"context_line":"            # note: checksum re-calculation while copying is not yet supported"},{"line_number":194,"context_line":"            req.check_copy_source(self.app)"},{"line_number":195,"context_line":"        elif self.conf.allow_store_checksums:"},{"line_number":196,"context_line":"            req.enable_checksum_persistence()"},{"line_number":197,"context_line":"        if not req.headers.get(\u0027Content-Type\u0027):"},{"line_number":198,"context_line":"            # can\u0027t setdefault because it can be None for some reason"}],"source_content_type":"text/x-python","patch_set":155,"id":"1ba7ca0b_dc7b880b","line":195,"in_reply_to":"f41c3308_1a6c5c34","updated":"2026-11-05 16:25:23.000000000","message":"for as long as we have multiple patches I\u0027d like to keep the right changes in the right patches; it\u0027s too confusing to have changes to UploadPart behaviour happening in this patch that revert changes in the previous patch.","commit_id":"ab189051b65e8746011e2e7e56fda9881020897d"}],"swift/common/middleware/s3api/s3request.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"3e87b736e476a693936493349bcf4a8036e59d8c","unresolved":false,"context_lines":[{"line_number":70,"context_line":"    utf8encode, S3Timestamp, mktime, MULTIUPLOAD_SUFFIX,"},{"line_number":71,"context_line":"    CHECKSUM_TYPE_FULL_OBJECT, CHECKSUM_TYPE_COMPOSITE,"},{"line_number":72,"context_line":"    CHECKSUMS_BY_HEADER, MPU_CHECKSUM_ALGORITHMS, MPU_CHECKSUM_TYPES,"},{"line_number":73,"context_line":"    FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS, COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS, \\"},{"line_number":74,"context_line":"    checksum_header_from_algorithm)"},{"line_number":75,"context_line":"from swift.common.middleware.s3api.subresource import decode_acl, encode_acl"},{"line_number":76,"context_line":"from swift.common.middleware.s3api.utils import sysmeta_header, \\"}],"source_content_type":"text/x-python","patch_set":27,"id":"d8da21b2_15c8c98c","line":73,"updated":"2026-07-06 20:34:36.000000000","message":"pep8: E501 line too long (80 \u003e 79 characters)","commit_id":"ce6e1a9d51c808d33436e45847f5ae50d2ba4243"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"3e87b736e476a693936493349bcf4a8036e59d8c","unresolved":false,"context_lines":[{"line_number":70,"context_line":"    utf8encode, S3Timestamp, mktime, MULTIUPLOAD_SUFFIX,"},{"line_number":71,"context_line":"    CHECKSUM_TYPE_FULL_OBJECT, CHECKSUM_TYPE_COMPOSITE,"},{"line_number":72,"context_line":"    CHECKSUMS_BY_HEADER, MPU_CHECKSUM_ALGORITHMS, MPU_CHECKSUM_TYPES,"},{"line_number":73,"context_line":"    FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS, COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS, \\"},{"line_number":74,"context_line":"    checksum_header_from_algorithm)"},{"line_number":75,"context_line":"from swift.common.middleware.s3api.subresource import decode_acl, encode_acl"},{"line_number":76,"context_line":"from swift.common.middleware.s3api.utils import sysmeta_header, \\"}],"source_content_type":"text/x-python","patch_set":27,"id":"c2ae96b9_16fa9c5f","line":73,"updated":"2026-07-06 20:34:36.000000000","message":"pep8: E502 the backslash is redundant between brackets","commit_id":"ce6e1a9d51c808d33436e45847f5ae50d2ba4243"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"a6860892fd5187bb59be34fa3e58571fa363faab","unresolved":false,"context_lines":[{"line_number":1580,"context_line":"                \u0027checksum algorithm.\u0027 % ("},{"line_number":1581,"context_line":"                    checksum_type, checksum_algorithm.lower()))"},{"line_number":1582,"context_line":"        if checksum_type \u003d\u003d CHECKSUM_TYPE_FULL_OBJECT:"},{"line_number":1583,"context_line":"            checksum_header \u003d checksum_header_from_algorithm(checksum_algorithm)"},{"line_number":1584,"context_line":"            try:"},{"line_number":1585,"context_line":"                checksum_hasher \u003d CHECKSUMS_BY_HEADER[checksum_header]()"},{"line_number":1586,"context_line":"            except NotImplementedError:"}],"source_content_type":"text/x-python","patch_set":30,"id":"500336f5_15236b2d","line":1583,"updated":"2026-07-09 19:42:51.000000000","message":"pep8: E501 line too long (80 \u003e 79 characters)","commit_id":"a3ec2e423c2775ab5fa668dc1a616edf06b7635b"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"e2628269dabc4c493ef10d54716317995cda52ed","unresolved":false,"context_lines":[{"line_number":1884,"context_line":"        Install a callback to persist checksum metadata after validation."},{"line_number":1885,"context_line":"        If checksum calculation fails (say for instance, the connection drops),"},{"line_number":1886,"context_line":"        the PUT fails before a checksum is recorded, so no checksum sysmeta is"},{"line_number":1887,"context_line":"        persisted. Once Swift reads in the entire object, the checksum is finshed"},{"line_number":1888,"context_line":"        and sysmeta is attached to the uploaded whole-object body."},{"line_number":1889,"context_line":"        :param checksum_type: The type of checksum to persist."},{"line_number":1890,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":40,"id":"9b24822b_2bac80fc","line":1887,"updated":"2026-07-20 20:58:14.000000000","message":"pep8: E501 line too long (81 \u003e 79 characters)","commit_id":"6e74348aa3675a298f703afd782f3c6db2b60a56"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"e2628269dabc4c493ef10d54716317995cda52ed","unresolved":false,"context_lines":[{"line_number":1903,"context_line":"    def calculate_checksum_metadata(self, checksum_header,"},{"line_number":1904,"context_line":"                                    checksum_type\u003dNone):"},{"line_number":1905,"context_line":"        \"\"\""},{"line_number":1906,"context_line":"        Specify that in this S3Request, we need to calcuate the checksum for the"},{"line_number":1907,"context_line":"        object because the client did not specify any checksum algorithm."},{"line_number":1908,"context_line":"        :param checksum_header: The header to calcuated for this object."},{"line_number":1909,"context_line":"        :param checksum_type: The type of this checksum for this object."}],"source_content_type":"text/x-python","patch_set":40,"id":"3973d632_84278a4a","line":1906,"updated":"2026-07-20 20:58:14.000000000","message":"pep8: E501 line too long (80 \u003e 79 characters)","commit_id":"6e74348aa3675a298f703afd782f3c6db2b60a56"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"8cac36e9117e7b85caad471786e98c5fe9cd2a2d","unresolved":false,"context_lines":[{"line_number":118,"context_line":"    \u0027x-static-large-object\u0027,"},{"line_number":119,"context_line":"))"},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"def _get_checksum_hasher(header):"},{"line_number":122,"context_line":"    try:"},{"line_number":123,"context_line":"        return CHECKSUMS_BY_HEADER[header]()"},{"line_number":124,"context_line":"    except (KeyError, NotImplementedError):"}],"source_content_type":"text/x-python","patch_set":63,"id":"0b3ad748_5c9abc9b","line":121,"updated":"2026-07-28 19:06:11.000000000","message":"pep8: E302 expected 2 blank lines, found 1","commit_id":"63a4a52cd5120d73c2d2b319e6aacdede8f76942"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":304,"context_line":"        return chunk"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":""},{"line_number":307,"context_line":"class CalculatingChecksumInput(InputProxy):"},{"line_number":308,"context_line":"    \"\"\""},{"line_number":309,"context_line":"    wsgi.input wrapper to calculate an X-Amz-Checksum-* value for internal"},{"line_number":310,"context_line":"    metadata without requiring a client-supplied checksum to validate."}],"source_content_type":"text/x-python","patch_set":87,"id":"e0d75809_091f255a","line":307,"updated":"2026-08-10 16:59:30.000000000","message":"We don\u0027t need two almost identical classes.\n\nOptions:\n\n* A superclass that does no validation, a subclass that validates against checksum_source. A purist might go for this.\n\n* A calculating input that is in turn wrapped by a validating input (i.e. split up the functions of ChecksummingInput). Possibly the best separation of concerns.\n\n* a \u0027validator\u0027 callback is passed to the class that is called at end-of-file. Personally I\u0027d avoid that; can be hard to keep track of callbacks.\n\n* a parameterised single ChecksummingInput with optional checksum_source. Possibly the most pragmatic/least code churn. I tried this out e.g. (may break some tests):\n\n```\ndiff --git a/swift/common/middleware/s3api/s3request.py b/swift/common/middleware/s3api/s3request.py\nindex 56f140177..6bdcc4efd 100644\n--- a/swift/common/middleware/s3api/s3request.py\n+++ b/swift/common/middleware/s3api/s3request.py\n@@ -267,67 +267,34 @@ class ChecksummingInput(InputProxy):\n         \"\"\"\n         return self._matching_checksum\n \n-    def chunk_update(self, chunk, eof, *args, **kwargs):\n-        # Note that \"chunk\" is just whatever was read from the input; this\n-        # says nothing about whether the underlying stream uses aws-chunked\n-        self._checksum_hasher.update(chunk)\n-        if self.bytes_received \u003c self._expected_length:\n-            # wrapped input is likely to have timed out before this clause is\n-            # reached with eof\u003d\u003dTrue, but just in case...\n-            error \u003d eof\n-        elif self.bytes_received \u003d\u003d self._expected_length:\n-            # Lazy fetch checksum value because it may have come in trailers\n-            b64digest \u003d self._checksum_source.get(self.checksum_key)\n-            try:\n-                expected_raw_checksum \u003d _validate_checksum_value(\n-                    self._checksum_hasher, b64digest)\n-            except ValueError:\n-                # If the checksum value came in a header then it would have\n-                # been validated before the body was read, so if the validation\n-                # fails here then we can infer that the checksum value came in\n-                # a trailer. The S3InputChecksumTrailerInvalid raised here will\n-                # propagate all the way back up the middleware stack to s3api\n-                # where it is caught and translated to an InvalidRequest.\n-                raise S3InputChecksumTrailerInvalid(self.checksum_key)\n-            error \u003d self._checksum_hasher.digest() !\u003d expected_raw_checksum\n-            if not error:\n-                self._matching_checksum \u003d b64digest\n-        else:\n-            # the underlying wsgi.Input stops reading at content-length so we\n-            # don\u0027t expect to reach this clause, but just in case...\n-            error \u003d True\n-\n-        if error:\n-            self.close()\n-            # Since we don\u0027t return the last chunk, the PUT never completes\n-            raise S3InputChecksumMismatch(self._checksum_hasher.name.upper())\n-        return chunk\n-\n \n-class CalculatingChecksumInput(InputProxy):\n-    \"\"\"\n-    wsgi.input wrapper to calculate an X-Amz-Checksum-* value for internal\n-    metadata without requiring a client-supplied checksum to validate.\n-\n-    :param wsgi_input: file-like object to be wrapped.\n-    :param content_length: the expected number of bytes to be read.\n-    :param checksum_hasher: a hasher to calculate the checksum of read bytes.\n-    :param checksum_header: the checksum header name represented by the\n-        calculated checksum.\n-    \"\"\"\n-\n-    def __init__(self, wsgi_input, content_length, checksum_hasher,\n-                 checksum_header):\n-        super().__init__(wsgi_input)\n-        self._expected_length \u003d content_length\n-        self._checksum_hasher \u003d checksum_hasher\n-        self.checksum_key \u003d checksum_header\n-        self._matching_checksum \u003d None\n+    def _validate_checksum(self):\n+        \"\"\"\n+        If a checksum_source has been provided then compare the calculated\n+        checksum with the expected value from the checksum_source, and return\n+        the value if it matches, otherwise return None.\n+        \"\"\"\n+        if not self._checksum_source:\n+            return base64_str(\n+                self._checksum_hasher.digest())\n \n-    @property\n-    def matching_checksum(self):\n-        \"\"\"Return the checksum value after the whole input is read.\"\"\"\n-        return self._matching_checksum\n+        # Lazy fetch checksum value because it may have come in trailers\n+        b64digest \u003d self._checksum_source.get(self.checksum_key)\n+        try:\n+            expected_raw_checksum \u003d _validate_checksum_value(\n+                self._checksum_hasher, b64digest)\n+        except ValueError:\n+            # If the checksum value came in a header then it would have\n+            # been validated before the body was read, so if the validation\n+            # fails here then we can infer that the checksum value came in\n+            # a trailer. The S3InputChecksumTrailerInvalid raised here will\n+            # propagate all the way back up the middleware stack to s3api\n+            # where it is caught and translated to an InvalidRequest.\n+            raise S3InputChecksumTrailerInvalid(self.checksum_key)\n+\n+        if self._checksum_hasher.digest() \u003d\u003d expected_raw_checksum:\n+            return b64digest\n+        return None\n \n     def chunk_update(self, chunk, eof, *args, **kwargs):\n         # Note that \"chunk\" is just whatever was read from the input; this\n@@ -338,9 +305,8 @@ class CalculatingChecksumInput(InputProxy):\n             # reached with eof\u003d\u003dTrue, but just in case...\n             error \u003d eof\n         elif self.bytes_received \u003d\u003d self._expected_length:\n-            error \u003d False\n-            self._matching_checksum \u003d base64_str(\n-                self._checksum_hasher.digest())\n+            self._matching_checksum \u003d self._validate_checksum()\n+            error \u003d self._matching_checksum is None\n         else:\n             # the underlying wsgi.Input stops reading at content-length so we\n             # don\u0027t expect to reach this clause, but just in case...\n@@ -1789,11 +1755,12 @@ class S3Request(swob.Request):\n         \"\"\"\n         Install and return the input wrapper that calculates the checksum.\n         \"\"\"\n-        calculating_input \u003d CalculatingChecksumInput(\n+        calculating_input \u003d ChecksummingInput(\n             self.environ[\u0027wsgi.input\u0027],\n             self.content_length,\n             checksum_hasher,\n             checksum_header,\n+            None\n         )\n         self.environ[\u0027wsgi.input\u0027] \u003d calculating_input\n         return calculating_input\ndiff --git a/test/unit/common/middleware/s3api/test_s3request.py b/test/unit/common/middleware/s3api/test_s3request.py\nindex e35501233..b15f555fc 100644\n--- a/test/unit/common/middleware/s3api/test_s3request.py\n+++ b/test/unit/common/middleware/s3api/test_s3request.py\n@@ -3468,8 +3468,8 @@ class TestSigV4Request(S3ApiTestCase):\n class TestCalculatingChecksumInput(S3ApiTestCase):\n     def test_too_short(self):\n         raw \u003d b\u0027123456789\u0027\n-        wrapped \u003d s3request.CalculatingChecksumInput(\n-            BytesIO(raw), 10, checksum.crc32(), \u0027x-amz-checksum-crc32\u0027)\n+        wrapped \u003d s3request.ChecksummingInput(\n+            BytesIO(raw), 10, checksum.crc32(), \u0027x-amz-checksum-crc32\u0027, None)\n \n         self.assertIsNone(wrapped.matching_checksum)\n         with self.assertRaises(S3InputChecksumMismatch):\n@@ -3479,8 +3479,8 @@ class TestCalculatingChecksumInput(S3ApiTestCase):\n \n     def test_too_long(self):\n         raw \u003d b\u0027123456789\u0027\n-        wrapped \u003d s3request.CalculatingChecksumInput(\n-            BytesIO(raw), 8, checksum.crc32(), \u0027x-amz-checksum-crc32\u0027)\n+        wrapped \u003d s3request.ChecksummingInput(\n+            BytesIO(raw), 8, checksum.crc32(), \u0027x-amz-checksum-crc32\u0027, None)\n \n         self.assertIsNone(wrapped.matching_checksum)\n         with self.assertRaises(S3InputChecksumMismatch):\n```","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":304,"context_line":"        return chunk"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":""},{"line_number":307,"context_line":"class CalculatingChecksumInput(InputProxy):"},{"line_number":308,"context_line":"    \"\"\""},{"line_number":309,"context_line":"    wsgi.input wrapper to calculate an X-Amz-Checksum-* value for internal"},{"line_number":310,"context_line":"    metadata without requiring a client-supplied checksum to validate."}],"source_content_type":"text/x-python","patch_set":87,"id":"f6903e44_8d19f640","line":307,"in_reply_to":"e0d75809_091f255a","updated":"2026-08-11 01:06:16.000000000","message":"This is PROBABLY good if we choose\n\n\u003ea parameterised single ChecksummingInput with optional checksum_source. Possibly the most pragmatic/least code churn. I tried this out e.g. (may break some tests):\n\nI feel its best to visualize too","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":304,"context_line":"        return chunk"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":""},{"line_number":307,"context_line":"class CalculatingChecksumInput(InputProxy):"},{"line_number":308,"context_line":"    \"\"\""},{"line_number":309,"context_line":"    wsgi.input wrapper to calculate an X-Amz-Checksum-* value for internal"},{"line_number":310,"context_line":"    metadata without requiring a client-supplied checksum to validate."}],"source_content_type":"text/x-python","patch_set":87,"id":"12f3b431_9ae8c4bd","line":307,"in_reply_to":"f6903e44_8d19f640","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1163,"context_line":"        # We might not always want to persist the part checksum,"},{"line_number":1164,"context_line":"        # like when a client provides a part checksum and the MPU"},{"line_number":1165,"context_line":"        # was not defined with one."},{"line_number":1166,"context_line":"        self.persist_part_checksum \u003d False"},{"line_number":1167,"context_line":"        self.access_key, self.signature \u003d self._parse_auth_info()"},{"line_number":1168,"context_line":"        self.bucket_in_host \u003d parse_host(self.environ,"},{"line_number":1169,"context_line":"                                         self.conf.storage_domains)"}],"source_content_type":"text/x-python","patch_set":87,"id":"f8b93ecb_8e988044","line":1166,"updated":"2026-08-10 16:59:30.000000000","message":"I\u0027m concerned about how much controller specific behaviour is bleeding into the S3Request class","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1163,"context_line":"        # We might not always want to persist the part checksum,"},{"line_number":1164,"context_line":"        # like when a client provides a part checksum and the MPU"},{"line_number":1165,"context_line":"        # was not defined with one."},{"line_number":1166,"context_line":"        self.persist_part_checksum \u003d False"},{"line_number":1167,"context_line":"        self.access_key, self.signature \u003d self._parse_auth_info()"},{"line_number":1168,"context_line":"        self.bucket_in_host \u003d parse_host(self.environ,"},{"line_number":1169,"context_line":"                                         self.conf.storage_domains)"}],"source_content_type":"text/x-python","patch_set":87,"id":"7f918c8c_33bcd77b","line":1166,"in_reply_to":"8b1495e4_ec0616bf","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1163,"context_line":"        # We might not always want to persist the part checksum,"},{"line_number":1164,"context_line":"        # like when a client provides a part checksum and the MPU"},{"line_number":1165,"context_line":"        # was not defined with one."},{"line_number":1166,"context_line":"        self.persist_part_checksum \u003d False"},{"line_number":1167,"context_line":"        self.access_key, self.signature \u003d self._parse_auth_info()"},{"line_number":1168,"context_line":"        self.bucket_in_host \u003d parse_host(self.environ,"},{"line_number":1169,"context_line":"                                         self.conf.storage_domains)"}],"source_content_type":"text/x-python","patch_set":87,"id":"8b1495e4_ec0616bf","line":1166,"in_reply_to":"f8b93ecb_8e988044","updated":"2026-08-11 01:06:16.000000000","message":"Yea I see it too, we can probabaly add ways to manipulate the s3request externally, or just have controller functions that mainpulate said req.","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1186,"context_line":"            # checksum with a -N suffix, not as a checksum of the XML request"},{"line_number":1187,"context_line":"            # body."},{"line_number":1188,"context_line":"            validate_checksum_value \u003d not ("},{"line_number":1189,"context_line":"                self.method \u003d\u003d \u0027POST\u0027 and \u0027uploadId\u0027 in self.params)"},{"line_number":1190,"context_line":"            checksum_hasher, checksum_header, checksum_trailer \u003d \\"},{"line_number":1191,"context_line":"                self._validate_checksum_headers(validate_checksum_value)"},{"line_number":1192,"context_line":"            if _is_streaming(aws_sha256):"}],"source_content_type":"text/x-python","patch_set":87,"id":"077f5fbc_be4a53e9","line":1189,"updated":"2026-08-10 16:59:30.000000000","message":"MPU specific behaviour here","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1186,"context_line":"            # checksum with a -N suffix, not as a checksum of the XML request"},{"line_number":1187,"context_line":"            # body."},{"line_number":1188,"context_line":"            validate_checksum_value \u003d not ("},{"line_number":1189,"context_line":"                self.method \u003d\u003d \u0027POST\u0027 and \u0027uploadId\u0027 in self.params)"},{"line_number":1190,"context_line":"            checksum_hasher, checksum_header, checksum_trailer \u003d \\"},{"line_number":1191,"context_line":"                self._validate_checksum_headers(validate_checksum_value)"},{"line_number":1192,"context_line":"            if _is_streaming(aws_sha256):"}],"source_content_type":"text/x-python","patch_set":87,"id":"a726ec7b_91ffabdb","line":1189,"in_reply_to":"077f5fbc_be4a53e9","updated":"2026-08-11 01:06:16.000000000","message":"I moved out the MPU specific behavior, though I am kinda conflicted since the `S3Request` already validates all checksums that enter the request, BUT for MPUs they pass in a COMPOSITE checksum... which will not be validated correctly...\n\nI think we can just update this to make sure enforcement only happens on `PUT requests` or `POST?delete` requests\n\nNot sure if this is the best approach","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1186,"context_line":"            # checksum with a -N suffix, not as a checksum of the XML request"},{"line_number":1187,"context_line":"            # body."},{"line_number":1188,"context_line":"            validate_checksum_value \u003d not ("},{"line_number":1189,"context_line":"                self.method \u003d\u003d \u0027POST\u0027 and \u0027uploadId\u0027 in self.params)"},{"line_number":1190,"context_line":"            checksum_hasher, checksum_header, checksum_trailer \u003d \\"},{"line_number":1191,"context_line":"                self._validate_checksum_headers(validate_checksum_value)"},{"line_number":1192,"context_line":"            if _is_streaming(aws_sha256):"}],"source_content_type":"text/x-python","patch_set":87,"id":"df4c864b_9a4a4b9d","line":1189,"in_reply_to":"a726ec7b_91ffabdb","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1619,"context_line":"        _validate_checksum_header_cardinality(len(checksum_headers))"},{"line_number":1620,"context_line":"        return checksum_headers"},{"line_number":1621,"context_line":""},{"line_number":1622,"context_line":"    def _validate_mpu_initiate_checksum_headers(self):"},{"line_number":1623,"context_line":"        \"\"\""},{"line_number":1624,"context_line":"        Validate CreateMultipartUpload checksum algorithm and type headers."},{"line_number":1625,"context_line":""}],"source_content_type":"text/x-python","patch_set":87,"id":"94caefc6_9952f38b","line":1622,"range":{"start_line":1622,"start_character":17,"end_line":1622,"end_character":21},"updated":"2026-08-10 16:59:30.000000000","message":"mpu-specific - could this be implemented by the controller in a setup hook?","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1619,"context_line":"        _validate_checksum_header_cardinality(len(checksum_headers))"},{"line_number":1620,"context_line":"        return checksum_headers"},{"line_number":1621,"context_line":""},{"line_number":1622,"context_line":"    def _validate_mpu_initiate_checksum_headers(self):"},{"line_number":1623,"context_line":"        \"\"\""},{"line_number":1624,"context_line":"        Validate CreateMultipartUpload checksum algorithm and type headers."},{"line_number":1625,"context_line":""}],"source_content_type":"text/x-python","patch_set":87,"id":"a257a6ea_fc81de27","line":1622,"range":{"start_line":1622,"start_character":17,"end_line":1622,"end_character":21},"in_reply_to":"57a488fe_70887375","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1619,"context_line":"        _validate_checksum_header_cardinality(len(checksum_headers))"},{"line_number":1620,"context_line":"        return checksum_headers"},{"line_number":1621,"context_line":""},{"line_number":1622,"context_line":"    def _validate_mpu_initiate_checksum_headers(self):"},{"line_number":1623,"context_line":"        \"\"\""},{"line_number":1624,"context_line":"        Validate CreateMultipartUpload checksum algorithm and type headers."},{"line_number":1625,"context_line":""}],"source_content_type":"text/x-python","patch_set":87,"id":"57a488fe_70887375","line":1622,"range":{"start_line":1622,"start_character":17,"end_line":1622,"end_character":21},"in_reply_to":"94caefc6_9952f38b","updated":"2026-08-11 01:06:16.000000000","message":"Yea I think this is a better idea","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1718,"context_line":"            None."},{"line_number":1719,"context_line":"        \"\"\""},{"line_number":1720,"context_line":"        if (self.method \u003d\u003d \u0027POST\u0027 and self.is_object_request and"},{"line_number":1721,"context_line":"                \u0027uploads\u0027 in self.params):"},{"line_number":1722,"context_line":"            self._mpu_checksum_configuration \u003d \\"},{"line_number":1723,"context_line":"                self._validate_mpu_initiate_checksum_headers()"},{"line_number":1724,"context_line":""}],"source_content_type":"text/x-python","patch_set":87,"id":"044cc522_f04a96b2","line":1721,"range":{"start_line":1721,"start_character":15,"end_line":1721,"end_character":26},"updated":"2026-08-10 16:59:30.000000000","message":"mpu specific","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1718,"context_line":"            None."},{"line_number":1719,"context_line":"        \"\"\""},{"line_number":1720,"context_line":"        if (self.method \u003d\u003d \u0027POST\u0027 and self.is_object_request and"},{"line_number":1721,"context_line":"                \u0027uploads\u0027 in self.params):"},{"line_number":1722,"context_line":"            self._mpu_checksum_configuration \u003d \\"},{"line_number":1723,"context_line":"                self._validate_mpu_initiate_checksum_headers()"},{"line_number":1724,"context_line":""}],"source_content_type":"text/x-python","patch_set":87,"id":"147cb358_59e00f2a","line":1721,"range":{"start_line":1721,"start_character":15,"end_line":1721,"end_character":26},"in_reply_to":"044cc522_f04a96b2","updated":"2026-08-11 01:06:16.000000000","message":"Moved this out into the controller","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1718,"context_line":"            None."},{"line_number":1719,"context_line":"        \"\"\""},{"line_number":1720,"context_line":"        if (self.method \u003d\u003d \u0027POST\u0027 and self.is_object_request and"},{"line_number":1721,"context_line":"                \u0027uploads\u0027 in self.params):"},{"line_number":1722,"context_line":"            self._mpu_checksum_configuration \u003d \\"},{"line_number":1723,"context_line":"                self._validate_mpu_initiate_checksum_headers()"},{"line_number":1724,"context_line":""}],"source_content_type":"text/x-python","patch_set":87,"id":"dd5f7cfa_10b81aaf","line":1721,"range":{"start_line":1721,"start_character":15,"end_line":1721,"end_character":26},"in_reply_to":"147cb358_59e00f2a","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1818,"context_line":"            \u0027partNumber\u0027 in self.params)"},{"line_number":1819,"context_line":"        return (self.is_object_request and"},{"line_number":1820,"context_line":"                \u0027X-Amz-Copy-Source\u0027 not in self.headers and"},{"line_number":1821,"context_line":"                (is_object_write or is_upload_part_write))"},{"line_number":1822,"context_line":""},{"line_number":1823,"context_line":"    def _checksum_type_for_request_sysmeta(self):"},{"line_number":1824,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":87,"id":"7be553d4_6d05e234","line":1821,"updated":"2026-08-10 16:59:30.000000000","message":"so here we say handle checksums for part uploads, but later we require persist_part_checksum to also be true?? which I think is maybe to allow for some exceptions.\n\nI\u0027m not yet sure how we alternatively plumb this but I\u0027d like to explore if the controllers can drive the behavior of the request by installing/overriding the checksum behavior in one place. Ideally the request would not know about controller specific behaviours.","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1818,"context_line":"            \u0027partNumber\u0027 in self.params)"},{"line_number":1819,"context_line":"        return (self.is_object_request and"},{"line_number":1820,"context_line":"                \u0027X-Amz-Copy-Source\u0027 not in self.headers and"},{"line_number":1821,"context_line":"                (is_object_write or is_upload_part_write))"},{"line_number":1822,"context_line":""},{"line_number":1823,"context_line":"    def _checksum_type_for_request_sysmeta(self):"},{"line_number":1824,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":87,"id":"be1942ff_9edaa22b","line":1821,"in_reply_to":"7be553d4_6d05e234","updated":"2026-08-11 01:06:16.000000000","message":"Yea moving this outside to the controller would be much better, thanks!","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1818,"context_line":"            \u0027partNumber\u0027 in self.params)"},{"line_number":1819,"context_line":"        return (self.is_object_request and"},{"line_number":1820,"context_line":"                \u0027X-Amz-Copy-Source\u0027 not in self.headers and"},{"line_number":1821,"context_line":"                (is_object_write or is_upload_part_write))"},{"line_number":1822,"context_line":""},{"line_number":1823,"context_line":"    def _checksum_type_for_request_sysmeta(self):"},{"line_number":1824,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":87,"id":"e8273788_e4e405c2","line":1821,"in_reply_to":"be1942ff_9edaa22b","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1836,"context_line":"            return None"},{"line_number":1837,"context_line":"        return CHECKSUM_TYPE_FULL_OBJECT"},{"line_number":1838,"context_line":""},{"line_number":1839,"context_line":"    def get_mpu_initiate_checksum_headers(self):"},{"line_number":1840,"context_line":"        \"\"\""},{"line_number":1841,"context_line":"        Return validated CreateMultipartUpload checksum header outputs."},{"line_number":1842,"context_line":""}],"source_content_type":"text/x-python","patch_set":87,"id":"e7dd6c63_33774a8d","line":1839,"updated":"2026-08-10 16:59:30.000000000","message":"why is this in S3Request? it\u0027s only called by the MPU controller, so it should be implemented there","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1836,"context_line":"            return None"},{"line_number":1837,"context_line":"        return CHECKSUM_TYPE_FULL_OBJECT"},{"line_number":1838,"context_line":""},{"line_number":1839,"context_line":"    def get_mpu_initiate_checksum_headers(self):"},{"line_number":1840,"context_line":"        \"\"\""},{"line_number":1841,"context_line":"        Return validated CreateMultipartUpload checksum header outputs."},{"line_number":1842,"context_line":""}],"source_content_type":"text/x-python","patch_set":87,"id":"cfa7d945_42fc5318","line":1839,"in_reply_to":"565cdc80_8cfdb3c6","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1836,"context_line":"            return None"},{"line_number":1837,"context_line":"        return CHECKSUM_TYPE_FULL_OBJECT"},{"line_number":1838,"context_line":""},{"line_number":1839,"context_line":"    def get_mpu_initiate_checksum_headers(self):"},{"line_number":1840,"context_line":"        \"\"\""},{"line_number":1841,"context_line":"        Return validated CreateMultipartUpload checksum header outputs."},{"line_number":1842,"context_line":""}],"source_content_type":"text/x-python","patch_set":87,"id":"565cdc80_8cfdb3c6","line":1839,"in_reply_to":"e7dd6c63_33774a8d","updated":"2026-08-11 01:06:16.000000000","message":"I agree, this is much better","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"ae3cd1c8faffeb36634f6ccf0cb58f460d9a1cf8","unresolved":true,"context_lines":[{"line_number":2353,"context_line":"            # Swift does not echo newly persisted sysmeta headers on PUT, so"},{"line_number":2354,"context_line":"            # inject the checksum response headers after validation succeeds."},{"line_number":2355,"context_line":"            # GET/HEAD responses use the stored sysmeta echoed from Swift."},{"line_number":2356,"context_line":"            if (method \u003d\u003d \u0027PUT\u0027 and not self.checksum_response_headers and"},{"line_number":2357,"context_line":"                    self._checksumming_input is not None and"},{"line_number":2358,"context_line":"                    self._checksumming_input.matching_checksum):"},{"line_number":2359,"context_line":"                sysmeta_headers \u003d checksum_sysmeta_headers("}],"source_content_type":"text/x-python","patch_set":89,"id":"eaf36a64_b7cc6deb","line":2356,"updated":"2026-08-11 13:42:10.000000000","message":"In PS87 this used `_should_handle_request_checksum()`, which itself used `if self.is_object_request`. With this patchset, the checksum is also returned on a bucket create - and AFAICT this should not be the case?","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":2353,"context_line":"            # Swift does not echo newly persisted sysmeta headers on PUT, so"},{"line_number":2354,"context_line":"            # inject the checksum response headers after validation succeeds."},{"line_number":2355,"context_line":"            # GET/HEAD responses use the stored sysmeta echoed from Swift."},{"line_number":2356,"context_line":"            if (method \u003d\u003d \u0027PUT\u0027 and not self.checksum_response_headers and"},{"line_number":2357,"context_line":"                    self._checksumming_input is not None and"},{"line_number":2358,"context_line":"                    self._checksumming_input.matching_checksum):"},{"line_number":2359,"context_line":"                sysmeta_headers \u003d checksum_sysmeta_headers("}],"source_content_type":"text/x-python","patch_set":89,"id":"e8ffc6be_a545b1ea","line":2356,"in_reply_to":"d052838e_d664512a","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c43e33e36ab46d3d31001b91ab9b2a64bbd54057","unresolved":true,"context_lines":[{"line_number":2353,"context_line":"            # Swift does not echo newly persisted sysmeta headers on PUT, so"},{"line_number":2354,"context_line":"            # inject the checksum response headers after validation succeeds."},{"line_number":2355,"context_line":"            # GET/HEAD responses use the stored sysmeta echoed from Swift."},{"line_number":2356,"context_line":"            if (method \u003d\u003d \u0027PUT\u0027 and not self.checksum_response_headers and"},{"line_number":2357,"context_line":"                    self._checksumming_input is not None and"},{"line_number":2358,"context_line":"                    self._checksumming_input.matching_checksum):"},{"line_number":2359,"context_line":"                sysmeta_headers \u003d checksum_sysmeta_headers("}],"source_content_type":"text/x-python","patch_set":89,"id":"d052838e_d664512a","line":2356,"in_reply_to":"eaf36a64_b7cc6deb","updated":"2026-08-11 15:59:03.000000000","message":"Oh yes the `self.is_object_request`!\nI was struggling with how the new updates to `ChecksummingInput` allow metadata to exist even when we have no source to fact check said data, which this current approach opens that possibly for checksum metadata to exist in places it should not in the response (i.e bucket create).\n\nI\u0027ll update this to make sure only for object requests, that we echo checksum metadata, not sure if there is a case elsewhere when we echo checksum metadata. Thanks for this!","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"}],"swift/common/middleware/s3api/schema/complete_multipart_upload.rng":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8446d5c28527f906b68ab3bdce4f72c15a7e258d","unresolved":true,"context_lines":[{"line_number":42,"context_line":"              \u003c/element\u003e"},{"line_number":43,"context_line":"            \u003c/optional\u003e"},{"line_number":44,"context_line":"            \u003coptional\u003e"},{"line_number":45,"context_line":"              \u003celement name\u003d\"ChecksumSHA512\"\u003e"},{"line_number":46,"context_line":"                \u003cdata type\u003d\"string\"/\u003e"},{"line_number":47,"context_line":"              \u003c/element\u003e"},{"line_number":48,"context_line":"            \u003c/optional\u003e"}],"source_content_type":"application/xml","patch_set":6,"id":"44265704_343e3eaf","line":45,"range":{"start_line":45,"start_character":29,"end_line":45,"end_character":43},"updated":"2026-06-17 23:01:52.000000000","message":"These newly-supported checksum types were quietly added in https://review.opendev.org/c/openstack/swift/+/991516 yeah? Would it maybe be better to add support all in one commit that touches both these schemas and `s3request.py`?","commit_id":"4a1b6c4dab7d6c288fb59a05129353a0d01e2355"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"116beb77313d00c0084287129b974a605ca574f9","unresolved":true,"context_lines":[{"line_number":42,"context_line":"              \u003c/element\u003e"},{"line_number":43,"context_line":"            \u003c/optional\u003e"},{"line_number":44,"context_line":"            \u003coptional\u003e"},{"line_number":45,"context_line":"              \u003celement name\u003d\"ChecksumSHA512\"\u003e"},{"line_number":46,"context_line":"                \u003cdata type\u003d\"string\"/\u003e"},{"line_number":47,"context_line":"              \u003c/element\u003e"},{"line_number":48,"context_line":"            \u003c/optional\u003e"}],"source_content_type":"application/xml","patch_set":6,"id":"7d272e4f_a2e660b2","line":45,"range":{"start_line":45,"start_character":29,"end_line":45,"end_character":43},"in_reply_to":"44265704_343e3eaf","updated":"2026-06-22 18:45:52.000000000","message":"I agree, I\u0027ll make a individual patch in include these","commit_id":"4a1b6c4dab7d6c288fb59a05129353a0d01e2355"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3f6e0f8bfe2641f46fe165977cfe26a45ff5276e","unresolved":false,"context_lines":[{"line_number":42,"context_line":"              \u003c/element\u003e"},{"line_number":43,"context_line":"            \u003c/optional\u003e"},{"line_number":44,"context_line":"            \u003coptional\u003e"},{"line_number":45,"context_line":"              \u003celement name\u003d\"ChecksumSHA512\"\u003e"},{"line_number":46,"context_line":"                \u003cdata type\u003d\"string\"/\u003e"},{"line_number":47,"context_line":"              \u003c/element\u003e"},{"line_number":48,"context_line":"            \u003c/optional\u003e"}],"source_content_type":"application/xml","patch_set":6,"id":"c54a43f1_34e41188","line":45,"range":{"start_line":45,"start_character":29,"end_line":45,"end_character":43},"in_reply_to":"7d272e4f_a2e660b2","updated":"2026-06-23 18:27:35.000000000","message":"Alright, new checksums can be found at\nhttps://review.opendev.org/c/openstack/swift/+/994518","commit_id":"4a1b6c4dab7d6c288fb59a05129353a0d01e2355"}],"swift/common/middleware/s3api/utils.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"3e87b736e476a693936493349bcf4a8036e59d8c","unresolved":false,"context_lines":[{"line_number":51,"context_line":"    \u0027x-amz-checksum-sha1\u0027: \u0027ChecksumSHA1\u0027,"},{"line_number":52,"context_line":"    \u0027x-amz-checksum-sha256\u0027: \u0027ChecksumSHA256\u0027,"},{"line_number":53,"context_line":"}"},{"line_number":54,"context_line":"def checksum_header_from_algorithm(algorithm):"},{"line_number":55,"context_line":"    \"\"\""},{"line_number":56,"context_line":"    Return the canonical x-amz-checksum-* header for an S3 checksum algorithm."},{"line_number":57,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":27,"id":"6ea39e88_889e7efe","line":54,"updated":"2026-07-06 20:34:36.000000000","message":"pep8: E302 expected 2 blank lines, found 0","commit_id":"ce6e1a9d51c808d33436e45847f5ae50d2ba4243"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":33,"context_line":"CHECKSUM_TYPE_FULL_OBJECT \u003d \u0027FULL_OBJECT\u0027"},{"line_number":34,"context_line":"CHECKSUM_TYPE_COMPOSITE \u003d \u0027COMPOSITE\u0027"},{"line_number":35,"context_line":"MPU_CHECKSUM_ALGORITHMS \u003d ("},{"line_number":36,"context_line":"    \u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027, \u0027SHA1\u0027, \u0027SHA256\u0027)"},{"line_number":37,"context_line":"MPU_CHECKSUM_TYPES \u003d (CHECKSUM_TYPE_COMPOSITE, CHECKSUM_TYPE_FULL_OBJECT)"},{"line_number":38,"context_line":"FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS \u003d (\u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027)"},{"line_number":39,"context_line":"COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS \u003d (\u0027CRC64NVME\u0027,)"}],"source_content_type":"text/x-python","patch_set":89,"id":"6a2d2d01_bcf582c3","line":36,"updated":"2026-08-11 17:04:46.000000000","message":"SHA* are included","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":true,"context_lines":[{"line_number":33,"context_line":"CHECKSUM_TYPE_FULL_OBJECT \u003d \u0027FULL_OBJECT\u0027"},{"line_number":34,"context_line":"CHECKSUM_TYPE_COMPOSITE \u003d \u0027COMPOSITE\u0027"},{"line_number":35,"context_line":"MPU_CHECKSUM_ALGORITHMS \u003d ("},{"line_number":36,"context_line":"    \u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027, \u0027SHA1\u0027, \u0027SHA256\u0027)"},{"line_number":37,"context_line":"MPU_CHECKSUM_TYPES \u003d (CHECKSUM_TYPE_COMPOSITE, CHECKSUM_TYPE_FULL_OBJECT)"},{"line_number":38,"context_line":"FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS \u003d (\u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027)"},{"line_number":39,"context_line":"COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS \u003d (\u0027CRC64NVME\u0027,)"}],"source_content_type":"text/x-python","patch_set":89,"id":"af1e5ac7_7d36c049","line":36,"in_reply_to":"6a2d2d01_bcf582c3","updated":"2026-08-12 01:33:28.000000000","message":"Yea this `MPU_CHECKSUM_ALGORITHMS` is pretty redundant i\u0027d say, mainly `FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS` and `COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS` are needed. Maybe we should change `COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS` to be `COMPOSITE_MPU_CHECKSUM_ALGORITHMS` instead??","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":33,"context_line":"CHECKSUM_TYPE_FULL_OBJECT \u003d \u0027FULL_OBJECT\u0027"},{"line_number":34,"context_line":"CHECKSUM_TYPE_COMPOSITE \u003d \u0027COMPOSITE\u0027"},{"line_number":35,"context_line":"MPU_CHECKSUM_ALGORITHMS \u003d ("},{"line_number":36,"context_line":"    \u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027, \u0027SHA1\u0027, \u0027SHA256\u0027)"},{"line_number":37,"context_line":"MPU_CHECKSUM_TYPES \u003d (CHECKSUM_TYPE_COMPOSITE, CHECKSUM_TYPE_FULL_OBJECT)"},{"line_number":38,"context_line":"FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS \u003d (\u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027)"},{"line_number":39,"context_line":"COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS \u003d (\u0027CRC64NVME\u0027,)"}],"source_content_type":"text/x-python","patch_set":89,"id":"d9158091_555c8657","line":36,"in_reply_to":"af1e5ac7_7d36c049","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":35,"context_line":"MPU_CHECKSUM_ALGORITHMS \u003d ("},{"line_number":36,"context_line":"    \u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027, \u0027SHA1\u0027, \u0027SHA256\u0027)"},{"line_number":37,"context_line":"MPU_CHECKSUM_TYPES \u003d (CHECKSUM_TYPE_COMPOSITE, CHECKSUM_TYPE_FULL_OBJECT)"},{"line_number":38,"context_line":"FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS \u003d (\u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027)"},{"line_number":39,"context_line":"COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS \u003d (\u0027CRC64NVME\u0027,)"},{"line_number":40,"context_line":"CHECKSUMS_BY_HEADER \u003d {"},{"line_number":41,"context_line":"    \u0027x-amz-checksum-crc32\u0027: checksum.crc32,"}],"source_content_type":"text/x-python","patch_set":89,"id":"71d2b0a1_9f1367d1","line":38,"updated":"2026-08-11 17:04:46.000000000","message":"so SHA* are NOT supported here?\n\nA; Apparently this is an API constraint","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":35,"context_line":"MPU_CHECKSUM_ALGORITHMS \u003d ("},{"line_number":36,"context_line":"    \u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027, \u0027SHA1\u0027, \u0027SHA256\u0027)"},{"line_number":37,"context_line":"MPU_CHECKSUM_TYPES \u003d (CHECKSUM_TYPE_COMPOSITE, CHECKSUM_TYPE_FULL_OBJECT)"},{"line_number":38,"context_line":"FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS \u003d (\u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027)"},{"line_number":39,"context_line":"COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS \u003d (\u0027CRC64NVME\u0027,)"},{"line_number":40,"context_line":"CHECKSUMS_BY_HEADER \u003d {"},{"line_number":41,"context_line":"    \u0027x-amz-checksum-crc32\u0027: checksum.crc32,"}],"source_content_type":"text/x-python","patch_set":89,"id":"3ef28d92_dea0f24d","line":38,"in_reply_to":"71d2b0a1_9f1367d1","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"26b9238fc9a59406fc149c8fc323a2443c0c1e73","unresolved":true,"context_lines":[{"line_number":36,"context_line":"    \u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027, \u0027SHA1\u0027, \u0027SHA256\u0027)"},{"line_number":37,"context_line":"MPU_CHECKSUM_TYPES \u003d (CHECKSUM_TYPE_COMPOSITE, CHECKSUM_TYPE_FULL_OBJECT)"},{"line_number":38,"context_line":"FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS \u003d (\u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027)"},{"line_number":39,"context_line":"COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS \u003d (\u0027CRC64NVME\u0027,)"},{"line_number":40,"context_line":"CHECKSUMS_BY_HEADER \u003d {"},{"line_number":41,"context_line":"    \u0027x-amz-checksum-crc32\u0027: checksum.crc32,"},{"line_number":42,"context_line":"    \u0027x-amz-checksum-crc32c\u0027: checksum.crc32c,"}],"source_content_type":"text/x-python","patch_set":89,"id":"79ed66b4_bd2ec736","line":39,"updated":"2026-08-11 17:04:46.000000000","message":"We have tuples of algos that are supported but this one exception of algo that is *unsupported* - can we just stick to tuples of *supported*?","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c5ef7a3e3f42c4c2c081ba3fd2d775df4c36b2a2","unresolved":true,"context_lines":[{"line_number":36,"context_line":"    \u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027, \u0027SHA1\u0027, \u0027SHA256\u0027)"},{"line_number":37,"context_line":"MPU_CHECKSUM_TYPES \u003d (CHECKSUM_TYPE_COMPOSITE, CHECKSUM_TYPE_FULL_OBJECT)"},{"line_number":38,"context_line":"FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS \u003d (\u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027)"},{"line_number":39,"context_line":"COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS \u003d (\u0027CRC64NVME\u0027,)"},{"line_number":40,"context_line":"CHECKSUMS_BY_HEADER \u003d {"},{"line_number":41,"context_line":"    \u0027x-amz-checksum-crc32\u0027: checksum.crc32,"},{"line_number":42,"context_line":"    \u0027x-amz-checksum-crc32c\u0027: checksum.crc32c,"}],"source_content_type":"text/x-python","patch_set":89,"id":"93a6b0fe_e0a24ee1","line":39,"in_reply_to":"79ed66b4_bd2ec736","updated":"2026-08-12 01:33:28.000000000","message":"Yep I think this is better","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    \u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027, \u0027SHA1\u0027, \u0027SHA256\u0027)"},{"line_number":37,"context_line":"MPU_CHECKSUM_TYPES \u003d (CHECKSUM_TYPE_COMPOSITE, CHECKSUM_TYPE_FULL_OBJECT)"},{"line_number":38,"context_line":"FULL_OBJECT_MPU_CHECKSUM_ALGORITHMS \u003d (\u0027CRC32\u0027, \u0027CRC32C\u0027, \u0027CRC64NVME\u0027)"},{"line_number":39,"context_line":"COMPOSITE_MPU_UNSUPPORTED_ALGORITHMS \u003d (\u0027CRC64NVME\u0027,)"},{"line_number":40,"context_line":"CHECKSUMS_BY_HEADER \u003d {"},{"line_number":41,"context_line":"    \u0027x-amz-checksum-crc32\u0027: checksum.crc32,"},{"line_number":42,"context_line":"    \u0027x-amz-checksum-crc32c\u0027: checksum.crc32c,"}],"source_content_type":"text/x-python","patch_set":89,"id":"e8707cf6_fb761f99","line":39,"in_reply_to":"93a6b0fe_e0a24ee1","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a9eaf2f962f67e5f78729d2ab242c44dbb964fff"}],"swift/common/middleware/slo.py":[{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"631c414471bcfdc40e9dbadd784e59fb07340166","unresolved":true,"context_lines":[{"line_number":1196,"context_line":"                continue"},{"line_number":1197,"context_line":"            seg_dict.pop(\u0027content_type\u0027, None)"},{"line_number":1198,"context_line":"            seg_dict.pop(\u0027last_modified\u0027, None)"},{"line_number":1199,"context_line":"            seg_dict.pop(\u0027sub_slo\u0027, None)"},{"line_number":1200,"context_line":"            seg_dict[\u0027path\u0027] \u003d seg_dict.pop(\u0027name\u0027, None)"},{"line_number":1201,"context_line":"            seg_dict[\u0027size_bytes\u0027] \u003d seg_dict.pop(\u0027bytes\u0027, None)"},{"line_number":1202,"context_line":"            seg_dict[\u0027etag\u0027] \u003d seg_dict.pop(\u0027hash\u0027, None)"}],"source_content_type":"text/x-python","patch_set":98,"id":"bace771f_8c417c18","line":1199,"updated":"2026-08-18 14:49:44.000000000","message":"This needs (at least) `seg_dict.pop(\u0027s3api_checksum\u0027, None)` to address the blocker","commit_id":"a3c3c8aab342416d520a57f8787140e525bc3744"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"84a83ad1ba84b82ce801a37c60d7eed61c8b9d2a","unresolved":true,"context_lines":[{"line_number":1196,"context_line":"                continue"},{"line_number":1197,"context_line":"            seg_dict.pop(\u0027content_type\u0027, None)"},{"line_number":1198,"context_line":"            seg_dict.pop(\u0027last_modified\u0027, None)"},{"line_number":1199,"context_line":"            seg_dict.pop(\u0027sub_slo\u0027, None)"},{"line_number":1200,"context_line":"            seg_dict[\u0027path\u0027] \u003d seg_dict.pop(\u0027name\u0027, None)"},{"line_number":1201,"context_line":"            seg_dict[\u0027size_bytes\u0027] \u003d seg_dict.pop(\u0027bytes\u0027, None)"},{"line_number":1202,"context_line":"            seg_dict[\u0027etag\u0027] \u003d seg_dict.pop(\u0027hash\u0027, None)"}],"source_content_type":"text/x-python","patch_set":98,"id":"eb84ccac_13479718","line":1199,"in_reply_to":"7a75f546_e428e6ae","updated":"2026-08-18 17:15:28.000000000","message":"This means, just getting rid of this SLO manifest key all together","commit_id":"a3c3c8aab342416d520a57f8787140e525bc3744"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"586820f611a9f8aa1f45c9b0903b0f452387bfd5","unresolved":true,"context_lines":[{"line_number":1196,"context_line":"                continue"},{"line_number":1197,"context_line":"            seg_dict.pop(\u0027content_type\u0027, None)"},{"line_number":1198,"context_line":"            seg_dict.pop(\u0027last_modified\u0027, None)"},{"line_number":1199,"context_line":"            seg_dict.pop(\u0027sub_slo\u0027, None)"},{"line_number":1200,"context_line":"            seg_dict[\u0027path\u0027] \u003d seg_dict.pop(\u0027name\u0027, None)"},{"line_number":1201,"context_line":"            seg_dict[\u0027size_bytes\u0027] \u003d seg_dict.pop(\u0027bytes\u0027, None)"},{"line_number":1202,"context_line":"            seg_dict[\u0027etag\u0027] \u003d seg_dict.pop(\u0027hash\u0027, None)"}],"source_content_type":"text/x-python","patch_set":98,"id":"7a75f546_e428e6ae","line":1199,"in_reply_to":"bace771f_8c417c18","updated":"2026-08-18 17:12:19.000000000","message":"It is probably not good to mix s3api specific stuff with SLO specific stuff IMHO. I am thinking a better approach to this might be to have to HEAD the part that the user is request if that part has a checksum on it (which is only for COMPOSITE MPUs FYI), and if someone GETs a part, we can just check the sysmeta headers that are returned on the GET.","commit_id":"a3c3c8aab342416d520a57f8787140e525bc3744"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1196,"context_line":"                continue"},{"line_number":1197,"context_line":"            seg_dict.pop(\u0027content_type\u0027, None)"},{"line_number":1198,"context_line":"            seg_dict.pop(\u0027last_modified\u0027, None)"},{"line_number":1199,"context_line":"            seg_dict.pop(\u0027sub_slo\u0027, None)"},{"line_number":1200,"context_line":"            seg_dict[\u0027path\u0027] \u003d seg_dict.pop(\u0027name\u0027, None)"},{"line_number":1201,"context_line":"            seg_dict[\u0027size_bytes\u0027] \u003d seg_dict.pop(\u0027bytes\u0027, None)"},{"line_number":1202,"context_line":"            seg_dict[\u0027etag\u0027] \u003d seg_dict.pop(\u0027hash\u0027, None)"}],"source_content_type":"text/x-python","patch_set":98,"id":"8f5757da_03bcc82f","line":1199,"in_reply_to":"eb84ccac_13479718","updated":"2026-08-19 23:49:24.000000000","message":"Yea we won\u0027t be doing this.","commit_id":"a3c3c8aab342416d520a57f8787140e525bc3744"}],"swift/common/utils/checksum.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8446d5c28527f906b68ab3bdce4f72c15a7e258d","unresolved":true,"context_lines":[{"line_number":188,"context_line":"    return [_gf2_matrix_times(matrix, row) for row in matrix]"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"def _crc_shift(crc, length, polynomial, width):"},{"line_number":192,"context_line":"    \"\"\""},{"line_number":193,"context_line":"    Shift a CRC across ``length`` zero bytes for CRC combine math."},{"line_number":194,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":6,"id":"8e8c935b_2c8ac2f4","line":191,"updated":"2026-06-17 23:01:52.000000000","message":"Are we sure we want to implement this in Python? Might be worth seeing whether `anycrc` is available, and using their `combine` that does it in C.","commit_id":"4a1b6c4dab7d6c288fb59a05129353a0d01e2355"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"116beb77313d00c0084287129b974a605ca574f9","unresolved":false,"context_lines":[{"line_number":188,"context_line":"    return [_gf2_matrix_times(matrix, row) for row in matrix]"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"def _crc_shift(crc, length, polynomial, width):"},{"line_number":192,"context_line":"    \"\"\""},{"line_number":193,"context_line":"    Shift a CRC across ``length`` zero bytes for CRC combine math."},{"line_number":194,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":6,"id":"25732966_d36db7ef","line":191,"in_reply_to":"8e8c935b_2c8ac2f4","updated":"2026-06-22 18:45:52.000000000","message":"Yes I agree with this","commit_id":"4a1b6c4dab7d6c288fb59a05129353a0d01e2355"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8446d5c28527f906b68ab3bdce4f72c15a7e258d","unresolved":true,"context_lines":[{"line_number":216,"context_line":"        odd \u003d _gf2_matrix_square(even)"},{"line_number":217,"context_line":"        if length \u0026 1:"},{"line_number":218,"context_line":"            crc \u003d _gf2_matrix_times(odd, crc)"},{"line_number":219,"context_line":"        length \u003e\u003e\u003d 1"},{"line_number":220,"context_line":"    return crc \u0026 mask"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"4cfa3442_5fea8fad","line":219,"updated":"2026-06-17 23:01:52.000000000","message":"Am I right to read that this even/odd business is just some loop unrolling? Is that mainly for performance, or is there something more going on here?\n\nFWIW, tests still pass with something like\n```\ndiff --git a/swift/common/utils/checksum.py b/swift/common/utils/checksum.py\nindex f1dc511cd..d22c2aed8 100644\n--- a/swift/common/utils/checksum.py\n+++ b/swift/common/utils/checksum.py\n@@ -204,19 +204,12 @@ def _crc_shift(crc, length, polynomial, width):\n         row \u003c\u003c\u003d 1\n\n     even \u003d _gf2_matrix_square(odd)\n-    odd \u003d _gf2_matrix_square(even)\n+    even \u003d _gf2_matrix_square(even)\n     while length:\n-        even \u003d _gf2_matrix_square(odd)\n+        even \u003d _gf2_matrix_square(even)\n         if length \u0026 1:\n             crc \u003d _gf2_matrix_times(even, crc)\n         length \u003e\u003e\u003d 1\n-        if not length:\n-            break\n-\n-        odd \u003d _gf2_matrix_square(even)\n-        if length \u0026 1:\n-            crc \u003d _gf2_matrix_times(odd, crc)\n-        length \u003e\u003e\u003d 1\n     return crc \u0026 mask\n\n\n```\napplied.","commit_id":"4a1b6c4dab7d6c288fb59a05129353a0d01e2355"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"116beb77313d00c0084287129b974a605ca574f9","unresolved":false,"context_lines":[{"line_number":216,"context_line":"        odd \u003d _gf2_matrix_square(even)"},{"line_number":217,"context_line":"        if length \u0026 1:"},{"line_number":218,"context_line":"            crc \u003d _gf2_matrix_times(odd, crc)"},{"line_number":219,"context_line":"        length \u003e\u003e\u003d 1"},{"line_number":220,"context_line":"    return crc \u0026 mask"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"d4c21052_2522d1e5","line":219,"in_reply_to":"4cfa3442_5fea8fad","updated":"2026-06-22 18:45:52.000000000","message":"Yes it is loop unrolling, nothing more. With using anycrc for crc_combine(), we won\u0027t be needing this anymore","commit_id":"4a1b6c4dab7d6c288fb59a05129353a0d01e2355"}],"test/s3api/test_input_errors.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"72fd2e436cde744529bfac1d8c9978d7f6fdda88","unresolved":false,"context_lines":[{"line_number":24,"context_line":"import requests.models"},{"line_number":25,"context_line":"import struct"},{"line_number":26,"context_line":"import zlib"},{"line_number":27,"context_line":"from unittest import SkipTest"},{"line_number":28,"context_line":"from urllib.parse import urlsplit, urlunsplit, quote"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"from swift.common import bufferedhttp"}],"source_content_type":"text/x-python","patch_set":136,"id":"d39f0bf8_e5ee58f5","line":27,"updated":"2026-09-16 19:25:24.000000000","message":"pep8: F401 \u0027unittest.SkipTest\u0027 imported but unused","commit_id":"d69d2b5dc82a9d0c40147ab67d93bb4cbc396ba4"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"72fd2e436cde744529bfac1d8c9978d7f6fdda88","unresolved":false,"context_lines":[{"line_number":28,"context_line":"from urllib.parse import urlsplit, urlunsplit, quote"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"from swift.common import bufferedhttp"},{"line_number":31,"context_line":"from swift.common.utils.checksum import anycrc, crc32"},{"line_number":32,"context_line":"from swift.common.utils.ipaddrs import parse_socket_string"},{"line_number":33,"context_line":"from test import requires_crc32_combine"},{"line_number":34,"context_line":""}],"source_content_type":"text/x-python","patch_set":136,"id":"89f3e56e_4ffc0626","line":31,"updated":"2026-09-16 19:25:24.000000000","message":"pep8: F401 \u0027swift.common.utils.checksum.anycrc\u0027 imported but unused","commit_id":"d69d2b5dc82a9d0c40147ab67d93bb4cbc396ba4"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"72fd2e436cde744529bfac1d8c9978d7f6fdda88","unresolved":false,"context_lines":[{"line_number":28,"context_line":"from urllib.parse import urlsplit, urlunsplit, quote"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"from swift.common import bufferedhttp"},{"line_number":31,"context_line":"from swift.common.utils.checksum import anycrc, crc32"},{"line_number":32,"context_line":"from swift.common.utils.ipaddrs import parse_socket_string"},{"line_number":33,"context_line":"from test import requires_crc32_combine"},{"line_number":34,"context_line":""}],"source_content_type":"text/x-python","patch_set":136,"id":"8d66ec05_cce2b7b1","line":31,"updated":"2026-09-16 19:25:24.000000000","message":"pep8: F401 \u0027swift.common.utils.checksum.crc32\u0027 imported but unused","commit_id":"d69d2b5dc82a9d0c40147ab67d93bb4cbc396ba4"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":2614,"context_line":"                Bucket\u003dself.bucket_name, Key\u003dobj_name, UploadId\u003dupload_id)"},{"line_number":2615,"context_line":""},{"line_number":2616,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2617,"context_line":"    def test_strm_unsgnd_pyld_trl_upload_part_persistence(self):"},{"line_number":2618,"context_line":"        client \u003d get_s3_client(1)"},{"line_number":2619,"context_line":"        obj_name \u003d self.create_name("},{"line_number":2620,"context_line":"            \u0027aws-chunked-trailer-mpu-persistence\u0027)"}],"source_content_type":"text/x-python","patch_set":145,"id":"ae9c3e50_559c61e7","line":2617,"updated":"2026-10-22 03:32:04.000000000","message":"this test case is covered by ``TestObjectChecksumCRC32.test_mpu_composite_checksum_round_trip``.\n\nWith checksum_type \u003d\u003d \u0027COMPOSITE\u0027 and ChecksumAlgorithm\u003d\u0027CRC32\u0027 added to self.upload_part, botocore sends STREAMING-UNSIGNED-PAYLOAD-TRAILER with x-amz-trailer: x-amz-checksum-crc32, which is exactly same as this test setup.","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":2614,"context_line":"                Bucket\u003dself.bucket_name, Key\u003dobj_name, UploadId\u003dupload_id)"},{"line_number":2615,"context_line":""},{"line_number":2616,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2617,"context_line":"    def test_strm_unsgnd_pyld_trl_upload_part_persistence(self):"},{"line_number":2618,"context_line":"        client \u003d get_s3_client(1)"},{"line_number":2619,"context_line":"        obj_name \u003d self.create_name("},{"line_number":2620,"context_line":"            \u0027aws-chunked-trailer-mpu-persistence\u0027)"}],"source_content_type":"text/x-python","patch_set":145,"id":"0c102c46_5a122a79","line":2617,"in_reply_to":"ae9c3e50_559c61e7","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"89a69ac46d9adf414d51903f5071acf8cfb78813","unresolved":true,"context_lines":[{"line_number":2710,"context_line":"                    Key\u003dobj_name,"},{"line_number":2711,"context_line":"                    UploadId\u003dupload_id)"},{"line_number":2712,"context_line":""},{"line_number":2713,"context_line":"    def assertNotServerError(self, resp):"},{"line_number":2714,"context_line":"        respbody \u003d resp.content"},{"line_number":2715,"context_line":"        if not isinstance(respbody, str):"},{"line_number":2716,"context_line":"            respbody \u003d respbody.decode(\u0027utf8\u0027, \u0027replace\u0027)"}],"source_content_type":"text/x-python","patch_set":158,"id":"e7da4ec0_c42b3676","line":2713,"updated":"2026-11-06 16:03:43.000000000","message":"wait, do we not know what status code to expect?? or is this allowing for some incompatibility?\n\nUPDATE: Swift allows CompleteMultipartUpload bodies to be streaming, AWS does\n    not seem to allow this (at least, I could not get AWS to accept the\n    request). The tests pass with 400s from AWS and 200s from\n    Swift.\n    \nsee sq? CompleteMultipartUpload: stop hiding swift s3 incompatibility  https://review.opendev.org/c/openstack/swift/+/1014551","commit_id":"a9734eb9f2502c0bb44000f71bff578a31e5ccfa"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"350ddd6db6466d5538590e5bd68a2546e36a8139","unresolved":false,"context_lines":[{"line_number":2629,"context_line":"                                 resp.headers[\u0027x-amz-checksum-crc32\u0027])"},{"line_number":2630,"context_line":"            else:"},{"line_number":2631,"context_line":"                # TODO: Swift does not return the checksum when the MPU has"},{"line_number":2632,"context_line":"                #  no checksum settings. Change Swift to return it as AWS"},{"line_number":2633,"context_line":"                #  does."},{"line_number":2634,"context_line":"                self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, resp.headers)"},{"line_number":2635,"context_line":"            self.assertNotIn(\u0027x-amz-checksum-type\u0027, resp.headers)"}],"source_content_type":"text/x-python","patch_set":160,"id":"3b32dac0_e221e571","line":2632,"updated":"2026-11-09 21:42:33.000000000","message":"1. swift -\u003e s3api\n2. mention it\u0027s on master as well.","commit_id":"77cdd92842321d013b81170a98d0a1ca6954a511"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3c302cddc8e5b656afbf33b36e6306ac3f6df208","unresolved":true,"context_lines":[{"line_number":2631,"context_line":"                self.assertEqual(_crc32(TEST_BODY),"},{"line_number":2632,"context_line":"                                 resp.headers[\u0027x-amz-checksum-crc32\u0027])"},{"line_number":2633,"context_line":"            else:"},{"line_number":2634,"context_line":"                # TODO: Swift does not return the checksum when the MPU has"},{"line_number":2635,"context_line":"                #  no checksum settings. Change Swift to return it as AWS"},{"line_number":2636,"context_line":"                #  does."},{"line_number":2637,"context_line":"                self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, resp.headers)"}],"source_content_type":"text/x-python","patch_set":161,"id":"7a9296a8_1f88cb83","line":2634,"updated":"2026-11-09 11:35:19.000000000","message":"I am not aware of any tracking system that alerts us to the continued presence of this TODO","commit_id":"13df7adae84fa01fd6fe63bcc448eef2b9c30aff"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"350ddd6db6466d5538590e5bd68a2546e36a8139","unresolved":true,"context_lines":[{"line_number":2631,"context_line":"                self.assertEqual(_crc32(TEST_BODY),"},{"line_number":2632,"context_line":"                                 resp.headers[\u0027x-amz-checksum-crc32\u0027])"},{"line_number":2633,"context_line":"            else:"},{"line_number":2634,"context_line":"                # TODO: Swift does not return the checksum when the MPU has"},{"line_number":2635,"context_line":"                #  no checksum settings. Change Swift to return it as AWS"},{"line_number":2636,"context_line":"                #  does."},{"line_number":2637,"context_line":"                self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, resp.headers)"}],"source_content_type":"text/x-python","patch_set":161,"id":"f04656d5_50762565","line":2634,"in_reply_to":"7a9296a8_1f88cb83","updated":"2026-11-09 21:42:33.000000000","message":"this will be solved by \"1014627: s3api: Return verified checksums in upload responses | https://review.opendev.org/c/openstack/swift/+/1014627\"","commit_id":"13df7adae84fa01fd6fe63bcc448eef2b9c30aff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3c302cddc8e5b656afbf33b36e6306ac3f6df208","unresolved":true,"context_lines":[{"line_number":2650,"context_line":"            if code_from_error(err) not in (\u0027NoSuchUpload\u0027, \u0027NoSuchKey\u0027):"},{"line_number":2651,"context_line":"                raise"},{"line_number":2652,"context_line":""},{"line_number":2653,"context_line":"    def _complete_mpu_after_streamed_part("},{"line_number":2654,"context_line":"            self, checksum_type, streamed_complete\u003dFalse):"},{"line_number":2655,"context_line":"        client \u003d get_s3_client(1)"},{"line_number":2656,"context_line":"        obj_name \u003d self.create_name("}],"source_content_type":"text/x-python","patch_set":161,"id":"86779688_28ef1a02","line":2653,"updated":"2026-11-09 11:35:19.000000000","message":"there\u0027s too much going on in this method, and it handles 4 different scenarios\n\nthe sq? I had here was rejected, but I think the refactoring was helpful i.e. separate the part upload (for which Swift IS compatible) from the completion (for which Swift is not compatible in the streaming case)","commit_id":"13df7adae84fa01fd6fe63bcc448eef2b9c30aff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3c302cddc8e5b656afbf33b36e6306ac3f6df208","unresolved":true,"context_lines":[{"line_number":2737,"context_line":"                (\u0027Error\u0027, \u0027InvalidRequest\u0027,"},{"line_number":2738,"context_line":"                 \u0027The value of x-amz-content-sha256 header is invalid.\u0027),"},{"line_number":2739,"context_line":"                (root.tag, root.findtext(\u0027Code\u0027), root.findtext(\u0027Message\u0027)))"},{"line_number":2740,"context_line":"            return"},{"line_number":2741,"context_line":""},{"line_number":2742,"context_line":"        # S3 can return an error document with HTTP 200, so parse the result."},{"line_number":2743,"context_line":"        # Remove heartbeat whitespace that can come before the XML."}],"source_content_type":"text/x-python","patch_set":161,"id":"87299705_fb5fa10b","line":2740,"updated":"2026-11-09 11:35:19.000000000","message":"-1. so Swift is incompatible, but the test asserts its incompatible response and passes. Why would we do that?","commit_id":"13df7adae84fa01fd6fe63bcc448eef2b9c30aff"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"350ddd6db6466d5538590e5bd68a2546e36a8139","unresolved":true,"context_lines":[{"line_number":2737,"context_line":"                (\u0027Error\u0027, \u0027InvalidRequest\u0027,"},{"line_number":2738,"context_line":"                 \u0027The value of x-amz-content-sha256 header is invalid.\u0027),"},{"line_number":2739,"context_line":"                (root.tag, root.findtext(\u0027Code\u0027), root.findtext(\u0027Message\u0027)))"},{"line_number":2740,"context_line":"            return"},{"line_number":2741,"context_line":""},{"line_number":2742,"context_line":"        # S3 can return an error document with HTTP 200, so parse the result."},{"line_number":2743,"context_line":"        # Remove heartbeat whitespace that can come before the XML."}],"source_content_type":"text/x-python","patch_set":161,"id":"e8afc0f8_9934ac4d","line":2740,"in_reply_to":"87299705_fb5fa10b","updated":"2026-11-09 21:42:33.000000000","message":"this will be solved by \"1014715: s3api: Reject unsigned streaming MPU completion | https://review.opendev.org/c/openstack/swift/+/1014715\"","commit_id":"13df7adae84fa01fd6fe63bcc448eef2b9c30aff"}],"test/s3api/test_object_checksums.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"a6860892fd5187bb59be34fa3e58571fa363faab","unresolved":false,"context_lines":[{"line_number":1309,"context_line":"                \u0027recomputation\u0027)"},{"line_number":1310,"context_line":""},{"line_number":1311,"context_line":"        algorithm \u003d \u0027CRC32\u0027"},{"line_number":1312,"context_line":"        src_name \u003d self.create_name(\u0027mpu-copy-full-object-checksum-mismatch-src\u0027)"},{"line_number":1313,"context_line":"        dst_name \u003d self.create_name(\u0027mpu-copy-full-object-checksum-mismatch-dst\u0027)"},{"line_number":1314,"context_line":"        put_resp \u003d self.client.put_object("},{"line_number":1315,"context_line":"            Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":30,"id":"7294960a_5672d14e","line":1312,"updated":"2026-07-09 19:42:51.000000000","message":"pep8: E501 line too long (81 \u003e 79 characters)","commit_id":"a3ec2e423c2775ab5fa668dc1a616edf06b7635b"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"a6860892fd5187bb59be34fa3e58571fa363faab","unresolved":false,"context_lines":[{"line_number":1310,"context_line":""},{"line_number":1311,"context_line":"        algorithm \u003d \u0027CRC32\u0027"},{"line_number":1312,"context_line":"        src_name \u003d self.create_name(\u0027mpu-copy-full-object-checksum-mismatch-src\u0027)"},{"line_number":1313,"context_line":"        dst_name \u003d self.create_name(\u0027mpu-copy-full-object-checksum-mismatch-dst\u0027)"},{"line_number":1314,"context_line":"        put_resp \u003d self.client.put_object("},{"line_number":1315,"context_line":"            Bucket\u003dself.bucket_name,"},{"line_number":1316,"context_line":"            Key\u003dsrc_name,"}],"source_content_type":"text/x-python","patch_set":30,"id":"ebc6c5f3_90626b8b","line":1313,"updated":"2026-07-09 19:42:51.000000000","message":"pep8: E501 line too long (81 \u003e 79 characters)","commit_id":"a3ec2e423c2775ab5fa668dc1a616edf06b7635b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"feda87b53af26feadcd2f13637ecfc04f382570b","unresolved":true,"context_lines":[{"line_number":1333,"context_line":"            except botocore.exceptions.ClientError:"},{"line_number":1334,"context_line":"                pass"},{"line_number":1335,"context_line":""},{"line_number":1336,"context_line":"    def test_mpu_full_object_upload_part_requires_checksum(self):"},{"line_number":1337,"context_line":"        algorithm \u003d \u0027CRC32\u0027"},{"line_number":1338,"context_line":"        if anycrc is None:"},{"line_number":1339,"context_line":"            raise SkipTest("}],"source_content_type":"text/x-python","patch_set":39,"id":"73fd1729_e4a8bab8","line":1336,"updated":"2026-07-18 01:42:01.000000000","message":"this didn\u0027t track with my observed aws s3 behavior:\n\n```\n  Then I ran the existing AWS-backed s3api tests in the VM with SWIFT_TEST_AWS_CONFIG_FILE\u003d/vagrant/.scratch/s3api_test_aws.conf. The first run skipped full-object tests until I installed anycrc in the VM user env; after that:\n\n  test/s3api/test_object_checksums.py .F. [100%]\n  FAILED test_mpu_full_object_upload_part_requires_checksum\n  E AssertionError: ClientError not raised\n\n  So AWS says:\n\n  - test_mpu_composite_upload_part_requires_checksum: passed\n  - test_mpu_full_object_checksum_round_trip: passed\n  - test_mpu_full_object_upload_part_requires_checksum: failed because AWS allowed the checksum-less UploadPart\n\n  That means the existing strict full-object compat test is encoding behavior that AWS does not have.\n```\n\n997804: sq? Allow optional full-object MPU part checksums | https://review.opendev.org/c/openstack/swift/+/997804","commit_id":"65e4364e0b6ff406ca68c14b920a01655b6e9c6c"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"89a483d2cfb0a294f50e2325d3ca72405b9fed73","unresolved":false,"context_lines":[{"line_number":1333,"context_line":"            except botocore.exceptions.ClientError:"},{"line_number":1334,"context_line":"                pass"},{"line_number":1335,"context_line":""},{"line_number":1336,"context_line":"    def test_mpu_full_object_upload_part_requires_checksum(self):"},{"line_number":1337,"context_line":"        algorithm \u003d \u0027CRC32\u0027"},{"line_number":1338,"context_line":"        if anycrc is None:"},{"line_number":1339,"context_line":"            raise SkipTest("}],"source_content_type":"text/x-python","patch_set":39,"id":"763aa4a2_1ae6b332","line":1336,"in_reply_to":"73fd1729_e4a8bab8","updated":"2026-07-20 19:27:57.000000000","message":"Sqaushed!","commit_id":"65e4364e0b6ff406ca68c14b920a01655b6e9c6c"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1bf8d7fe1db8a32411f51d3a32080a5db91b8745","unresolved":false,"context_lines":[{"line_number":1077,"context_line":"            \u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":1078,"context_line":""},{"line_number":1079,"context_line":""},{"line_number":1080,"context_line":"    def test_mpu_full_object_upload_part_checksum_optional(self):"},{"line_number":1081,"context_line":"        algorithm \u003d \u0027CRC32\u0027"},{"line_number":1082,"context_line":"        if anycrc is None:"},{"line_number":1083,"context_line":"            raise SkipTest("}],"source_content_type":"text/x-python","patch_set":54,"id":"28b53a15_65b4c2ed","line":1080,"updated":"2026-07-27 16:48:49.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"ec149cf11a388d06847beeb09b7f69ce02d59b13"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":1012,"context_line":"        self.assertEqual(204, abort_resp["},{"line_number":1013,"context_line":"            \u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":1014,"context_line":""},{"line_number":1015,"context_line":"    def test_multipart_mpu_composite_checksum(self):"},{"line_number":1016,"context_line":"        obj_name \u003d self.create_name(\u0027composite-checksum-mpu\u0027)"},{"line_number":1017,"context_line":"        create_mpu_resp \u003d self.client.create_multipart_upload("},{"line_number":1018,"context_line":"            Bucket\u003dself.bucket_name, Key\u003dobj_name,"}],"source_content_type":"text/x-python","patch_set":145,"id":"4ad48767_89c1d7f5","line":1015,"updated":"2026-10-22 03:32:04.000000000","message":"this test is covered by new added tests:\n ``TestObjectChecksumCRC32.test_mpu_composite_checksum_round_trip``: allow_store_checksums\u003dtrue\n and\n ``TestObjectChecksumsMPUs.test_complete_checksum_request_persistence_disabled`` : allow_store_checksums\u003dfalse","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":1012,"context_line":"        self.assertEqual(204, abort_resp["},{"line_number":1013,"context_line":"            \u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":1014,"context_line":""},{"line_number":1015,"context_line":"    def test_multipart_mpu_composite_checksum(self):"},{"line_number":1016,"context_line":"        obj_name \u003d self.create_name(\u0027composite-checksum-mpu\u0027)"},{"line_number":1017,"context_line":"        create_mpu_resp \u003d self.client.create_multipart_upload("},{"line_number":1018,"context_line":"            Bucket\u003dself.bucket_name, Key\u003dobj_name,"}],"source_content_type":"text/x-python","patch_set":145,"id":"6917cd5c_f4bbd8ee","line":1015,"in_reply_to":"4ad48767_89c1d7f5","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":1856,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":1857,"context_line":""},{"line_number":1858,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":1859,"context_line":"    def test_reuploaded_part_replaces_checksum(self):"},{"line_number":1860,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-reuploaded-part\u0027)"},{"line_number":1861,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":1862,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"18ba599d_053ff661","line":1859,"updated":"2026-10-22 03:32:04.000000000","message":"Reuse the existing upload_part helper for all three uploads and their returned manifest entries.","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":1856,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":1857,"context_line":""},{"line_number":1858,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":1859,"context_line":"    def test_reuploaded_part_replaces_checksum(self):"},{"line_number":1860,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-reuploaded-part\u0027)"},{"line_number":1861,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":1862,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"13c1dc40_c15b70de","line":1859,"in_reply_to":"18ba599d_053ff661","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":1939,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":1940,"context_line":""},{"line_number":1941,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":1942,"context_line":"    def test_bad_final_checksum_can_retry(self):"},{"line_number":1943,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-bad-final-checksum-retry\u0027)"},{"line_number":1944,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027FULL_OBJECT\u0027)"},{"line_number":1945,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"61cc6c34_ec60a57d","line":1942,"updated":"2026-10-22 03:32:04.000000000","message":"Remove the exact standalone BadDigest rejection already tested and use the existing upload_part helper","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":1939,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":1940,"context_line":""},{"line_number":1941,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":1942,"context_line":"    def test_bad_final_checksum_can_retry(self):"},{"line_number":1943,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-bad-final-checksum-retry\u0027)"},{"line_number":1944,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027FULL_OBJECT\u0027)"},{"line_number":1945,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"80e94a60_635758a2","line":1942,"in_reply_to":"61cc6c34_ec60a57d","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":2090,"context_line":"            200, complete_resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":2091,"context_line":""},{"line_number":2092,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2093,"context_line":"    def test_complete_composite_rejects_malformed_final_checksum(self):"},{"line_number":2094,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum(\u0027COMPOSITE\u0027)"},{"line_number":2095,"context_line":""},{"line_number":2096,"context_line":"    @skip_if_checksum_persistence_disabled"}],"source_content_type":"text/x-python","patch_set":145,"id":"cf7def1b_bf978f1f","line":2093,"updated":"2026-10-22 03:32:04.000000000","message":"this one is duplicate of ``TestObjectChecksumsMPUs.test_complete_composite_checksum_bad_value``","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":2090,"context_line":"            200, complete_resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":2091,"context_line":""},{"line_number":2092,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2093,"context_line":"    def test_complete_composite_rejects_malformed_final_checksum(self):"},{"line_number":2094,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum(\u0027COMPOSITE\u0027)"},{"line_number":2095,"context_line":""},{"line_number":2096,"context_line":"    @skip_if_checksum_persistence_disabled"}],"source_content_type":"text/x-python","patch_set":145,"id":"9e90b8f5_b89d8ff2","line":2093,"in_reply_to":"cf7def1b_bf978f1f","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":2094,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum(\u0027COMPOSITE\u0027)"},{"line_number":2095,"context_line":""},{"line_number":2096,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2097,"context_line":"    def test_complete_full_object_rejects_malformed_final_checksum(self):"},{"line_number":2098,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum(\u0027FULL_OBJECT\u0027)"},{"line_number":2099,"context_line":""},{"line_number":2100,"context_line":"    @skip_if_checksum_persistence_disabled"}],"source_content_type":"text/x-python","patch_set":145,"id":"1da80ac7_33795c01","line":2097,"updated":"2026-10-22 03:32:04.000000000","message":"this one can be merged into ``TestObjectChecksumsMPUs.test_complete_composite_checksum_bad_value``","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":2094,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum(\u0027COMPOSITE\u0027)"},{"line_number":2095,"context_line":""},{"line_number":2096,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2097,"context_line":"    def test_complete_full_object_rejects_malformed_final_checksum(self):"},{"line_number":2098,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum(\u0027FULL_OBJECT\u0027)"},{"line_number":2099,"context_line":""},{"line_number":2100,"context_line":"    @skip_if_checksum_persistence_disabled"}],"source_content_type":"text/x-python","patch_set":145,"id":"c95f6487_3ed90b78","line":2097,"in_reply_to":"1da80ac7_33795c01","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":2189,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":2190,"context_line":""},{"line_number":2191,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2192,"context_line":"    def test_complete_mpu_retry_is_idempotent(self):"},{"line_number":2193,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-complete-retry-composite\u0027)"},{"line_number":2194,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":2195,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"40faef13_145af0fa","line":2192,"updated":"2026-10-22 03:32:04.000000000","message":"this can be merged into ``test_complete_retry_ignores_any_request_checksums_and_types``","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":2189,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":2190,"context_line":""},{"line_number":2191,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2192,"context_line":"    def test_complete_mpu_retry_is_idempotent(self):"},{"line_number":2193,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-complete-retry-composite\u0027)"},{"line_number":2194,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":2195,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"b7165986_4ead06b9","line":2192,"in_reply_to":"40faef13_145af0fa","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":2613,"context_line":"            checksum_type\u003d\u0027FULL_OBJECT\u0027)"},{"line_number":2614,"context_line":""},{"line_number":2615,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2616,"context_line":"    def test_full_object_upload_part_no_checksum_complete_no_checksum(self):"},{"line_number":2617,"context_line":"        obj_name \u003d self.create_name("},{"line_number":2618,"context_line":"            \u0027mpu-full-object-upload-part-checksum-optional\u0027)"},{"line_number":2619,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027FULL_OBJECT\u0027)"}],"source_content_type":"text/x-python","patch_set":145,"id":"4a0670d1_6677fbfc","line":2616,"updated":"2026-10-22 03:32:04.000000000","message":"can be merged into ``test_full_object_upload_part_no_checksum_complete_has_checksum``","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":2613,"context_line":"            checksum_type\u003d\u0027FULL_OBJECT\u0027)"},{"line_number":2614,"context_line":""},{"line_number":2615,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2616,"context_line":"    def test_full_object_upload_part_no_checksum_complete_no_checksum(self):"},{"line_number":2617,"context_line":"        obj_name \u003d self.create_name("},{"line_number":2618,"context_line":"            \u0027mpu-full-object-upload-part-checksum-optional\u0027)"},{"line_number":2619,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027FULL_OBJECT\u0027)"}],"source_content_type":"text/x-python","patch_set":145,"id":"d9b7268b_8e53d39c","line":2616,"in_reply_to":"4a0670d1_6677fbfc","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":2789,"context_line":"                event_name, inject_unknown_checksum)"},{"line_number":2790,"context_line":""},{"line_number":2791,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2792,"context_line":"    def test_complete_rejects_checksum_algorithm_mismatch(self):"},{"line_number":2793,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-complete-checksum-algorithm-mismatch\u0027)"},{"line_number":2794,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":2795,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"7ac17400_74bfdb73","line":2792,"updated":"2026-10-22 03:32:04.000000000","message":"can be merged into test_complete_retry_ignores_any_request_checksums_and_types","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":2789,"context_line":"                event_name, inject_unknown_checksum)"},{"line_number":2790,"context_line":""},{"line_number":2791,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2792,"context_line":"    def test_complete_rejects_checksum_algorithm_mismatch(self):"},{"line_number":2793,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-complete-checksum-algorithm-mismatch\u0027)"},{"line_number":2794,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":2795,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"6e14b406_cc232d18","line":2792,"in_reply_to":"7ac17400_74bfdb73","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":2821,"context_line":"                \u0027we received.\u0027))"},{"line_number":2822,"context_line":""},{"line_number":2823,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2824,"context_line":"    def test_complete_rejects_checksum_type_mismatch(self):"},{"line_number":2825,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-complete-checksum-type-mismatch\u0027)"},{"line_number":2826,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":2827,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"981e152c_f4ba8427","line":2824,"updated":"2026-10-22 03:32:04.000000000","message":"can be merged into test_complete_retry_ignores_any_request_checksums_and_types","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":2821,"context_line":"                \u0027we received.\u0027))"},{"line_number":2822,"context_line":""},{"line_number":2823,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2824,"context_line":"    def test_complete_rejects_checksum_type_mismatch(self):"},{"line_number":2825,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-complete-checksum-type-mismatch\u0027)"},{"line_number":2826,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":2827,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"f300511a_31c14dcc","line":2824,"in_reply_to":"981e152c_f4ba8427","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":2888,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":2889,"context_line":""},{"line_number":2890,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2891,"context_line":"    def test_complete_full_object_bad_checksum(self):"},{"line_number":2892,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-complete-full-object-bad-checksum\u0027)"},{"line_number":2893,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027FULL_OBJECT\u0027)"},{"line_number":2894,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"3cbfc72a_035b0207","line":2891,"updated":"2026-10-22 03:32:04.000000000","message":"merge into test_bad_final_checksum_can_retry","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":2888,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":2889,"context_line":""},{"line_number":2890,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2891,"context_line":"    def test_complete_full_object_bad_checksum(self):"},{"line_number":2892,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-complete-full-object-bad-checksum\u0027)"},{"line_number":2893,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027FULL_OBJECT\u0027)"},{"line_number":2894,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"c17144bb_398603d8","line":2891,"in_reply_to":"3cbfc72a_035b0207","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":2911,"context_line":"                \u0027the calculated checksum.\u0027))"},{"line_number":2912,"context_line":""},{"line_number":2913,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2914,"context_line":"    def test_same_key_checksum_are_isolated(self):"},{"line_number":2915,"context_line":"        obj_name \u003d self.create_name(\u0027same-key-checksum-mpus\u0027)"},{"line_number":2916,"context_line":"        first_upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":2917,"context_line":"        second_upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"}],"source_content_type":"text/x-python","patch_set":145,"id":"a74bd3d8_2ed64234","line":2914,"updated":"2026-10-22 03:32:04.000000000","message":"Reuse upload_part for identical response assertions","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":2911,"context_line":"                \u0027the calculated checksum.\u0027))"},{"line_number":2912,"context_line":""},{"line_number":2913,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2914,"context_line":"    def test_same_key_checksum_are_isolated(self):"},{"line_number":2915,"context_line":"        obj_name \u003d self.create_name(\u0027same-key-checksum-mpus\u0027)"},{"line_number":2916,"context_line":"        first_upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":2917,"context_line":"        second_upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"}],"source_content_type":"text/x-python","patch_set":145,"id":"b5f6fb7b_c2c15745","line":2914,"in_reply_to":"a74bd3d8_2ed64234","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"1efed53535ef9d93d0db3d091abc7b7d18133545","unresolved":true,"context_lines":[{"line_number":1193,"context_line":"        else:"},{"line_number":1194,"context_line":"            # TODO: Swift does not return the checksum when the MPU has"},{"line_number":1195,"context_line":"            #  no checksum settings. Change Swift to return it as AWS does."},{"line_number":1196,"context_line":"            self.assertNotIn(\u0027ChecksumCRC32\u0027, part_resp)"},{"line_number":1197,"context_line":"            self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, headers)"},{"line_number":1198,"context_line":"        self.assertNotIn(\u0027ChecksumType\u0027, part_resp)"},{"line_number":1199,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"}],"source_content_type":"text/x-python","patch_set":161,"id":"378651ca_fcbdb686","line":1196,"updated":"2026-11-09 15:01:20.000000000","message":"This just failed on us-east-1:\n\n    AssertionError: \u0027ChecksumCRC32\u0027 unexpectedly found in {\u0027ResponseMetadata\u0027: ...}","commit_id":"13df7adae84fa01fd6fe63bcc448eef2b9c30aff"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3c302cddc8e5b656afbf33b36e6306ac3f6df208","unresolved":true,"context_lines":[{"line_number":1194,"context_line":"            # TODO: Swift does not return the checksum when the MPU has"},{"line_number":1195,"context_line":"            #  no checksum settings. Change Swift to return it as AWS does."},{"line_number":1196,"context_line":"            self.assertNotIn(\u0027ChecksumCRC32\u0027, part_resp)"},{"line_number":1197,"context_line":"            self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, headers)"},{"line_number":1198,"context_line":"        self.assertNotIn(\u0027ChecksumType\u0027, part_resp)"},{"line_number":1199,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"},{"line_number":1200,"context_line":"        part \u003d {\u0027ETag\u0027: part_resp[\u0027ETag\u0027], \u0027PartNumber\u0027: 1}"}],"source_content_type":"text/x-python","patch_set":161,"id":"603f665d_0b8f66f2","line":1197,"updated":"2026-11-09 11:35:19.000000000","message":"I\u0027m not convinced that proliferating this if/else pattern to assert incompatibilities is wise. We don\u0027t track TODOs.","commit_id":"13df7adae84fa01fd6fe63bcc448eef2b9c30aff"}],"test/unit/common/middleware/crypto/test_encryption.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"b64ed9a6bcc48ca293c9904f91c117e4182f9689","unresolved":true,"context_lines":[{"line_number":422,"context_line":"        create_headers \u003d dict(auth_headers)"},{"line_number":423,"context_line":"        create_headers.update({"},{"line_number":424,"context_line":"            \u0027X-Amz-Checksum-Algorithm\u0027: \u0027CRC32\u0027,"},{"line_number":425,"context_line":"            \u0027X-Amz-Checksum-Type\u0027: \u0027COMPOSITE\u0027,"},{"line_number":426,"context_line":"        })"},{"line_number":427,"context_line":"        req \u003d Request.blank("},{"line_number":428,"context_line":"            s3_path + \u0027?uploads\u0027, method\u003d\u0027POST\u0027, headers\u003dcreate_headers)"}],"source_content_type":"text/x-python","patch_set":137,"id":"967e5c20_35c02f26","line":425,"updated":"2026-09-17 22:17:17.000000000","message":"need to add completed FULL_OBJECT MPU through crypto as well","commit_id":"35cf83abf941253916b1b5a3a1729f041c44a42c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"7f56857b528747191de0b98d14d7b23ce2a55faf","unresolved":false,"context_lines":[{"line_number":422,"context_line":"        create_headers \u003d dict(auth_headers)"},{"line_number":423,"context_line":"        create_headers.update({"},{"line_number":424,"context_line":"            \u0027X-Amz-Checksum-Algorithm\u0027: \u0027CRC32\u0027,"},{"line_number":425,"context_line":"            \u0027X-Amz-Checksum-Type\u0027: \u0027COMPOSITE\u0027,"},{"line_number":426,"context_line":"        })"},{"line_number":427,"context_line":"        req \u003d Request.blank("},{"line_number":428,"context_line":"            s3_path + \u0027?uploads\u0027, method\u003d\u0027POST\u0027, headers\u003dcreate_headers)"}],"source_content_type":"text/x-python","patch_set":137,"id":"50d0ea57_05ddb841","line":425,"in_reply_to":"967e5c20_35c02f26","updated":"2026-09-17 22:20:32.000000000","message":"Done","commit_id":"35cf83abf941253916b1b5a3a1729f041c44a42c"}],"test/unit/common/middleware/s3api/test_etree.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"f8fafbd456d535caf70da25890202a94deb2af89","unresolved":false,"context_lines":[{"line_number":130,"context_line":"        with self.assertRaises(etree.DocumentInvalid):"},{"line_number":131,"context_line":"            etree.fromstring(xml, \u0027CompleteMultipartUploadResult\u0027)"},{"line_number":132,"context_line":""},{"line_number":133,"context_line":"if __name__ \u003d\u003d \u0027__main__\u0027:"},{"line_number":134,"context_line":"    unittest.main()"}],"source_content_type":"text/x-python","patch_set":70,"id":"a40d8b67_5f114b34","line":133,"updated":"2026-07-31 21:23:32.000000000","message":"pep8: E305 expected 2 blank lines after class or function definition, found 1","commit_id":"e570e414b6bf68dcd451f515963124a8b33f38e4"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":68,"context_line":"        self.assertEqual(text, b\u0027\\xef\\xbc\\xa1\u0027.decode(\u0027utf8\u0027))"},{"line_number":69,"context_line":"        self.assertIsInstance(text, str)"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    def test_complete_multipart_upload_result_with_checksum(self):"},{"line_number":72,"context_line":"        xml \u003d \u0027\u0027\u0027"},{"line_number":73,"context_line":"            \u003cCompleteMultipartUploadResult\u003e"},{"line_number":74,"context_line":"              \u003cLocation\u003ehttp://localhost/bucket/object\u003c/Location\u003e"}],"source_content_type":"text/x-python","patch_set":145,"id":"712b39f9_8902aeff","line":71,"updated":"2026-10-22 03:32:04.000000000","message":"merge with test_complete_multipart_upload_result_with_checksum_type","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":68,"context_line":"        self.assertEqual(text, b\u0027\\xef\\xbc\\xa1\u0027.decode(\u0027utf8\u0027))"},{"line_number":69,"context_line":"        self.assertIsInstance(text, str)"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    def test_complete_multipart_upload_result_with_checksum(self):"},{"line_number":72,"context_line":"        xml \u003d \u0027\u0027\u0027"},{"line_number":73,"context_line":"            \u003cCompleteMultipartUploadResult\u003e"},{"line_number":74,"context_line":"              \u003cLocation\u003ehttp://localhost/bucket/object\u003c/Location\u003e"}],"source_content_type":"text/x-python","patch_set":145,"id":"ccd0e04c_7809a67b","line":71,"in_reply_to":"712b39f9_8902aeff","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":101,"context_line":"        self.assertEqual(\u0027AAAAAA\u003d\u003d-2\u0027, elem.find(\u0027ChecksumCRC32\u0027).text)"},{"line_number":102,"context_line":"        self.assertEqual(\u0027COMPOSITE\u0027, elem.find(\u0027ChecksumType\u0027).text)"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    def test_complete_multipart_upload_result_rejects_two_checksums(self):"},{"line_number":105,"context_line":"        xml \u003d \u0027\u0027\u0027"},{"line_number":106,"context_line":"            \u003cCompleteMultipartUploadResult\u003e"},{"line_number":107,"context_line":"              \u003cLocation\u003ehttp://localhost/bucket/object\u003c/Location\u003e"}],"source_content_type":"text/x-python","patch_set":145,"id":"c6fa5362_51911ff4","line":104,"updated":"2026-10-22 03:32:04.000000000","message":"merge with test_complete_multipart_upload_result_rejects_type_only","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":101,"context_line":"        self.assertEqual(\u0027AAAAAA\u003d\u003d-2\u0027, elem.find(\u0027ChecksumCRC32\u0027).text)"},{"line_number":102,"context_line":"        self.assertEqual(\u0027COMPOSITE\u0027, elem.find(\u0027ChecksumType\u0027).text)"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    def test_complete_multipart_upload_result_rejects_two_checksums(self):"},{"line_number":105,"context_line":"        xml \u003d \u0027\u0027\u0027"},{"line_number":106,"context_line":"            \u003cCompleteMultipartUploadResult\u003e"},{"line_number":107,"context_line":"              \u003cLocation\u003ehttp://localhost/bucket/object\u003c/Location\u003e"}],"source_content_type":"text/x-python","patch_set":145,"id":"aa28afe5_855f6d50","line":104,"in_reply_to":"c6fa5362_51911ff4","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"}],"test/unit/common/middleware/s3api/test_multi_get.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":124,"context_line":"        self.assertEqual(headers[\u0027Etag\u0027], \u0027\"%s\"\u0027 % self.s3_etag)"},{"line_number":125,"context_line":"        self.assertNotIn(\u0027X-Amz-Mp-Parts-Count\u0027, headers)"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"    def test_checksum_mpu_GET_checksum_mode_enabled(self):"},{"line_number":128,"context_line":"        req \u003d swob.Request.blank(\u0027/bucket/checksum-mpu\u0027, headers\u003d{"},{"line_number":129,"context_line":"            \u0027Authorization\u0027: \u0027AWS test:tester:hmac\u0027,"},{"line_number":130,"context_line":"            \u0027Date\u0027: self.get_date_header(),"}],"source_content_type":"text/x-python","patch_set":145,"id":"05bc4e13_9609aa0b","line":127,"updated":"2026-10-22 03:32:04.000000000","message":"merge with test_checksum_mpu_HEAD_checksum_mode_enabled","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":124,"context_line":"        self.assertEqual(headers[\u0027Etag\u0027], \u0027\"%s\"\u0027 % self.s3_etag)"},{"line_number":125,"context_line":"        self.assertNotIn(\u0027X-Amz-Mp-Parts-Count\u0027, headers)"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"    def test_checksum_mpu_GET_checksum_mode_enabled(self):"},{"line_number":128,"context_line":"        req \u003d swob.Request.blank(\u0027/bucket/checksum-mpu\u0027, headers\u003d{"},{"line_number":129,"context_line":"            \u0027Authorization\u0027: \u0027AWS test:tester:hmac\u0027,"},{"line_number":130,"context_line":"            \u0027Date\u0027: self.get_date_header(),"}],"source_content_type":"text/x-python","patch_set":145,"id":"37d59fbd_22f1a736","line":127,"in_reply_to":"05bc4e13_9609aa0b","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":155,"context_line":"        self.assertEqual(\u0027AAAAAA\u003d\u003d-3\u0027, headers[\u0027x-amz-checksum-crc32\u0027])"},{"line_number":156,"context_line":"        self.assertEqual(\u0027COMPOSITE\u0027, headers[\u0027x-amz-checksum-type\u0027])"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    def test_checksum_mpu_GET_range_omits_checksum_headers(self):"},{"line_number":159,"context_line":"        req \u003d swob.Request.blank(\u0027/bucket/checksum-mpu\u0027, headers\u003d{"},{"line_number":160,"context_line":"            \u0027Authorization\u0027: \u0027AWS test:tester:hmac\u0027,"},{"line_number":161,"context_line":"            \u0027Date\u0027: self.get_date_header(),"}],"source_content_type":"text/x-python","patch_set":145,"id":"f1d2d461_9c750e14","line":158,"updated":"2026-10-22 03:32:04.000000000","message":"merge with test_checksum_mpu_HEAD_range_omits_checksum_headers","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":155,"context_line":"        self.assertEqual(\u0027AAAAAA\u003d\u003d-3\u0027, headers[\u0027x-amz-checksum-crc32\u0027])"},{"line_number":156,"context_line":"        self.assertEqual(\u0027COMPOSITE\u0027, headers[\u0027x-amz-checksum-type\u0027])"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    def test_checksum_mpu_GET_range_omits_checksum_headers(self):"},{"line_number":159,"context_line":"        req \u003d swob.Request.blank(\u0027/bucket/checksum-mpu\u0027, headers\u003d{"},{"line_number":160,"context_line":"            \u0027Authorization\u0027: \u0027AWS test:tester:hmac\u0027,"},{"line_number":161,"context_line":"            \u0027Date\u0027: self.get_date_header(),"}],"source_content_type":"text/x-python","patch_set":145,"id":"82a877d2_4358030b","line":158,"in_reply_to":"f1d2d461_9c750e14","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":190,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, headers)"},{"line_number":191,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":"    def test_checksum_mpu_GET_without_checksum_mode_omits_checksum_headers("},{"line_number":194,"context_line":"            self):"},{"line_number":195,"context_line":"        req \u003d swob.Request.blank(\u0027/bucket/checksum-mpu\u0027, headers\u003d{"},{"line_number":196,"context_line":"            \u0027Authorization\u0027: \u0027AWS test:tester:hmac\u0027,"}],"source_content_type":"text/x-python","patch_set":145,"id":"60caca3b_0f06362e","line":193,"updated":"2026-10-22 03:32:04.000000000","message":"merge with test_checksum_mpu_HEAD_without_checksum_mode_omits_checksum_headers","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":190,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, headers)"},{"line_number":191,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":"    def test_checksum_mpu_GET_without_checksum_mode_omits_checksum_headers("},{"line_number":194,"context_line":"            self):"},{"line_number":195,"context_line":"        req \u003d swob.Request.blank(\u0027/bucket/checksum-mpu\u0027, headers\u003d{"},{"line_number":196,"context_line":"            \u0027Authorization\u0027: \u0027AWS test:tester:hmac\u0027,"}],"source_content_type":"text/x-python","patch_set":145,"id":"19cf21c7_4f7ae51e","line":193,"in_reply_to":"60caca3b_0f06362e","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"}],"test/unit/common/middleware/s3api/test_multi_upload.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"be0b03b9d892243685506a1483fdf8bfbc904f74","unresolved":true,"context_lines":[{"line_number":2725,"context_line":"        finally:"},{"line_number":2726,"context_line":"            self.app.app \u003d original_app"},{"line_number":2727,"context_line":""},{"line_number":2728,"context_line":"        self.assertEqual(status, \u0027400 Bad Request\u0027)"},{"line_number":2729,"context_line":"        self.assertEqual(\u0027InvalidPart\u0027, self._get_error_code(body))"},{"line_number":2730,"context_line":"        self.assertEqual(["},{"line_number":2731,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/AUTH_test\u0027),"}],"source_content_type":"text/x-python","patch_set":92,"id":"5668e09a_b50c2c84","line":2728,"updated":"2026-08-12 16:06:26.000000000","message":"this is only true if slo yields the error response body within 10 seconds of the start of the response; otherwise multi_upload will return 200.\n\nSee my comment in multi_upload re reiterate\n\nWith this diff the test fails, but if you reduce the time step it passes. There\u0027s more than one call to time in the path so 6 is sufficient to reach to timeout of 10\n```\ndiff --git a/test/unit/common/middleware/s3api/test_multi_upload.py b/test/unit/common/middleware/s3api/test_multi_upload.py\nindex e076130ce..0b403ecb5 100644\n--- a/test/unit/common/middleware/s3api/test_multi_upload.py\n+++ b/test/unit/common/middleware/s3api/test_multi_upload.py\n@@ -16,6 +16,8 @@\n import base64\n import binascii\n import hashlib\n+import itertools\n+from unittest import mock\n from unittest.mock import MagicMock, patch\n import os\n import time\n@@ -2721,7 +2723,11 @@ class TestS3ApiMultiUpload(BaseS3ApiMultiUpload, S3ApiTestCase):\n         original_app \u003d self.app.app\n         self.app.app \u003d slo.filter_factory({})(self.swift)\n         try:\n-            status, headers, body \u003d self.call_s3api(req)\n+            now \u003d time.time()\n+            with mock.patch(\u0027swift.common.middleware.s3api.controllers.\u0027\n+                            \u0027multi_upload.time.time\u0027,\n+                            side_effect\u003ditertools.count(start\u003dnow, step\u003d6)):\n+                status, headers, body \u003d self.call_s3api(req)\n         finally:\n             self.app.app \u003d original_app\n \n\n```","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":2725,"context_line":"        finally:"},{"line_number":2726,"context_line":"            self.app.app \u003d original_app"},{"line_number":2727,"context_line":""},{"line_number":2728,"context_line":"        self.assertEqual(status, \u0027400 Bad Request\u0027)"},{"line_number":2729,"context_line":"        self.assertEqual(\u0027InvalidPart\u0027, self._get_error_code(body))"},{"line_number":2730,"context_line":"        self.assertEqual(["},{"line_number":2731,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/AUTH_test\u0027),"}],"source_content_type":"text/x-python","patch_set":92,"id":"0acf102b_282487b2","line":2728,"in_reply_to":"18a03bf9_024d568e","updated":"2026-08-19 23:49:24.000000000","message":"Added tests in `test_multi_upload.py` to handle this\n`test_checksum_mpu_bad_part_checksum_delays_heartbeat`","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3e05b45c3062aeed117e41f50c3cdb33487a532d","unresolved":true,"context_lines":[{"line_number":2725,"context_line":"        finally:"},{"line_number":2726,"context_line":"            self.app.app \u003d original_app"},{"line_number":2727,"context_line":""},{"line_number":2728,"context_line":"        self.assertEqual(status, \u0027400 Bad Request\u0027)"},{"line_number":2729,"context_line":"        self.assertEqual(\u0027InvalidPart\u0027, self._get_error_code(body))"},{"line_number":2730,"context_line":"        self.assertEqual(["},{"line_number":2731,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/AUTH_test\u0027),"}],"source_content_type":"text/x-python","patch_set":92,"id":"18a03bf9_024d568e","line":2728,"in_reply_to":"5668e09a_b50c2c84","updated":"2026-08-13 23:44:17.000000000","message":"Add some more unit tests to showcase this, also the sq patch 1000853: sq? make mpu manifest hook cache errors | https://review.opendev.org/c/openstack/swift/+/1000853 should help us here too!","commit_id":"a9fdb8c9b0997ab5ad524f9373e9c990f798ace8"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"254b09cd3d187c7e9ab3009665706a104606215c","unresolved":false,"context_lines":[{"line_number":40,"context_line":"    checksum_xml_element_from_header"},{"line_number":41,"context_line":"from swift.common.middleware.s3api.controllers.multi_upload import \\"},{"line_number":42,"context_line":"    MPUChecksumAttrs, _CompleteMultipartUploadSloManifestHook"},{"line_number":43,"context_line":"from swift.common.middleware.s3api.utils import sysmeta_header, mktime, \\"},{"line_number":44,"context_line":"    S3Timestamp"},{"line_number":45,"context_line":"from swift.common.middleware.s3api.s3request import MAX_32BIT_INT"},{"line_number":46,"context_line":"from swift.common.storage_policy import StoragePolicy, POLICIES"}],"source_content_type":"text/x-python","patch_set":107,"id":"c3b12987_ac0515d6","line":43,"updated":"2026-08-20 17:01:30.000000000","message":"pep8: F401 \u0027swift.common.middleware.s3api.utils.mktime\u0027 imported but unused","commit_id":"f38758035f117274f2214c977352826702c09bfd"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c43861d91f11abdd8696e5ab6da7e328f4e9b321","unresolved":true,"context_lines":[{"line_number":1368,"context_line":"            self.swift.register("},{"line_number":1369,"context_line":"                \u0027HEAD\u0027, \u0027%s/%s\u0027 % (self.segment_bucket, part_name),"},{"line_number":1370,"context_line":"                swob.HTTPOk, {"},{"line_number":1371,"context_line":"                    \u0027Etag\u0027: obj[\u0027hash\u0027] * 2,"},{"line_number":1372,"context_line":"                    \u0027Content-Length\u0027: str("},{"line_number":1373,"context_line":"                        obj[\u0027bytes\u0027] if content_length is None"},{"line_number":1374,"context_line":"                        else content_length),"}],"source_content_type":"text/x-python","patch_set":134,"id":"48b78da3_0bb29778","line":1371,"range":{"start_line":1371,"start_character":39,"end_line":1371,"end_character":43},"updated":"2026-09-14 19:58:24.000000000","message":"Off-topic: Huh. Well that\u0027s slightly insane...","commit_id":"4aedf6761dea26ea5f7c69ec1b75718f2f420e9e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"490b7e450cabf098550cfc62978ff43d5f19e614","unresolved":false,"context_lines":[{"line_number":1368,"context_line":"            self.swift.register("},{"line_number":1369,"context_line":"                \u0027HEAD\u0027, \u0027%s/%s\u0027 % (self.segment_bucket, part_name),"},{"line_number":1370,"context_line":"                swob.HTTPOk, {"},{"line_number":1371,"context_line":"                    \u0027Etag\u0027: obj[\u0027hash\u0027] * 2,"},{"line_number":1372,"context_line":"                    \u0027Content-Length\u0027: str("},{"line_number":1373,"context_line":"                        obj[\u0027bytes\u0027] if content_length is None"},{"line_number":1374,"context_line":"                        else content_length),"}],"source_content_type":"text/x-python","patch_set":134,"id":"31daa823_c19c7f6a","line":1371,"range":{"start_line":1371,"start_character":39,"end_line":1371,"end_character":43},"in_reply_to":"012b78db_d1304dcd","updated":"2026-09-16 19:53:05.000000000","message":"Thanks -- I didn\u0027t really mean to force the issue, it was just something I bumped into while working on a follow-up.","commit_id":"4aedf6761dea26ea5f7c69ec1b75718f2f420e9e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0a70fc21f1287872786a623c93de2170cba79a9b","unresolved":true,"context_lines":[{"line_number":1368,"context_line":"            self.swift.register("},{"line_number":1369,"context_line":"                \u0027HEAD\u0027, \u0027%s/%s\u0027 % (self.segment_bucket, part_name),"},{"line_number":1370,"context_line":"                swob.HTTPOk, {"},{"line_number":1371,"context_line":"                    \u0027Etag\u0027: obj[\u0027hash\u0027] * 2,"},{"line_number":1372,"context_line":"                    \u0027Content-Length\u0027: str("},{"line_number":1373,"context_line":"                        obj[\u0027bytes\u0027] if content_length is None"},{"line_number":1374,"context_line":"                        else content_length),"}],"source_content_type":"text/x-python","patch_set":134,"id":"012b78db_d1304dcd","line":1371,"range":{"start_line":1371,"start_character":39,"end_line":1371,"end_character":43},"in_reply_to":"48b78da3_0bb29778","updated":"2026-09-16 15:03:27.000000000","message":"fixed in parent patch","commit_id":"4aedf6761dea26ea5f7c69ec1b75718f2f420e9e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0685a51f81f74568ad61287222cdb7a7e76dccdc","unresolved":true,"context_lines":[{"line_number":3369,"context_line":"            with self.subTest(stored_upload_id\u003dstored_upload_id):"},{"line_number":3370,"context_line":"                self._register_checksum_upload_marker()"},{"line_number":3371,"context_line":"                self._register_part_checksum(1, part_one_checksum)"},{"line_number":3372,"context_line":"                part_two_headers \u003d {"},{"line_number":3373,"context_line":"                    \u0027Etag\u0027: part_two[\u0027hash\u0027],"},{"line_number":3374,"context_line":"                    \u0027Content-Length\u0027: str(part_two[\u0027bytes\u0027]),"},{"line_number":3375,"context_line":"                    \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027: \u0027CRC32\u0027,"},{"line_number":3376,"context_line":"                    \u0027x-object-sysmeta-sensitive-s3api-checksum-value\u0027:"},{"line_number":3377,"context_line":"                        part_two_checksum,"},{"line_number":3378,"context_line":"                }"},{"line_number":3379,"context_line":"                if stored_upload_id is not None:"},{"line_number":3380,"context_line":"                    part_two_headers["},{"line_number":3381,"context_line":"                        \u0027x-object-sysmeta-s3api-checksum-upload-id\u0027] \u003d ("},{"line_number":3382,"context_line":"                            stored_upload_id)"},{"line_number":3383,"context_line":"                self.swift.register("},{"line_number":3384,"context_line":"                    \u0027HEAD\u0027, self.segment_bucket + \u0027/object/X/2\u0027,"},{"line_number":3385,"context_line":"                    swob.HTTPOk, part_two_headers, None)"}],"source_content_type":"text/x-python","patch_set":139,"id":"9d601ac3_ac39f275","line":3382,"range":{"start_line":3372,"start_character":16,"end_line":3382,"end_character":45},"updated":"2026-09-18 10:39:31.000000000","message":"I think it would be clearer if the subtest loop iterated over a list of `part_two_headers` variations, rather than needing this further conditional behaviour based on `stored_upload_id`","commit_id":"20c59d9bd2d964045ef583798f5b5a931492ffe3"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"d5e92a59427d5f329dd2bfeb753ed44727534a56","unresolved":true,"context_lines":[{"line_number":3369,"context_line":"            with self.subTest(stored_upload_id\u003dstored_upload_id):"},{"line_number":3370,"context_line":"                self._register_checksum_upload_marker()"},{"line_number":3371,"context_line":"                self._register_part_checksum(1, part_one_checksum)"},{"line_number":3372,"context_line":"                part_two_headers \u003d {"},{"line_number":3373,"context_line":"                    \u0027Etag\u0027: part_two[\u0027hash\u0027],"},{"line_number":3374,"context_line":"                    \u0027Content-Length\u0027: str(part_two[\u0027bytes\u0027]),"},{"line_number":3375,"context_line":"                    \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027: \u0027CRC32\u0027,"},{"line_number":3376,"context_line":"                    \u0027x-object-sysmeta-sensitive-s3api-checksum-value\u0027:"},{"line_number":3377,"context_line":"                        part_two_checksum,"},{"line_number":3378,"context_line":"                }"},{"line_number":3379,"context_line":"                if stored_upload_id is not None:"},{"line_number":3380,"context_line":"                    part_two_headers["},{"line_number":3381,"context_line":"                        \u0027x-object-sysmeta-s3api-checksum-upload-id\u0027] \u003d ("},{"line_number":3382,"context_line":"                            stored_upload_id)"},{"line_number":3383,"context_line":"                self.swift.register("},{"line_number":3384,"context_line":"                    \u0027HEAD\u0027, self.segment_bucket + \u0027/object/X/2\u0027,"},{"line_number":3385,"context_line":"                    swob.HTTPOk, part_two_headers, None)"}],"source_content_type":"text/x-python","patch_set":139,"id":"d63a13e9_45625e30","line":3382,"range":{"start_line":3372,"start_character":16,"end_line":3382,"end_character":45},"in_reply_to":"9d601ac3_ac39f275","updated":"2026-09-20 04:29:14.000000000","message":"if we try below loop which iterates over a list of part_two_headers, the for loop itself then becomes not that clear as before?\n```\nfor part_two_headers in (\n        part_two_headers,\n        dict(part_two_headers, **{\n            \u0027x-object-sysmeta-s3api-checksum-upload-id\u0027: \u0027Y\u0027,\n        })):\n```","commit_id":"20c59d9bd2d964045ef583798f5b5a931492ffe3"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":false,"context_lines":[{"line_number":3369,"context_line":"            with self.subTest(stored_upload_id\u003dstored_upload_id):"},{"line_number":3370,"context_line":"                self._register_checksum_upload_marker()"},{"line_number":3371,"context_line":"                self._register_part_checksum(1, part_one_checksum)"},{"line_number":3372,"context_line":"                part_two_headers \u003d {"},{"line_number":3373,"context_line":"                    \u0027Etag\u0027: part_two[\u0027hash\u0027],"},{"line_number":3374,"context_line":"                    \u0027Content-Length\u0027: str(part_two[\u0027bytes\u0027]),"},{"line_number":3375,"context_line":"                    \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027: \u0027CRC32\u0027,"},{"line_number":3376,"context_line":"                    \u0027x-object-sysmeta-sensitive-s3api-checksum-value\u0027:"},{"line_number":3377,"context_line":"                        part_two_checksum,"},{"line_number":3378,"context_line":"                }"},{"line_number":3379,"context_line":"                if stored_upload_id is not None:"},{"line_number":3380,"context_line":"                    part_two_headers["},{"line_number":3381,"context_line":"                        \u0027x-object-sysmeta-s3api-checksum-upload-id\u0027] \u003d ("},{"line_number":3382,"context_line":"                            stored_upload_id)"},{"line_number":3383,"context_line":"                self.swift.register("},{"line_number":3384,"context_line":"                    \u0027HEAD\u0027, self.segment_bucket + \u0027/object/X/2\u0027,"},{"line_number":3385,"context_line":"                    swob.HTTPOk, part_two_headers, None)"}],"source_content_type":"text/x-python","patch_set":139,"id":"2620c9d3_ea03c85c","line":3382,"range":{"start_line":3372,"start_character":16,"end_line":3382,"end_character":45},"in_reply_to":"d63a13e9_45625e30","updated":"2026-10-22 03:32:04.000000000","message":"Acknowledged","commit_id":"20c59d9bd2d964045ef583798f5b5a931492ffe3"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":3005,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket+segments/object/X/2\u0027),"},{"line_number":3006,"context_line":"        ], self.swift.calls)"},{"line_number":3007,"context_line":""},{"line_number":3008,"context_line":"    def test_complete_legacy_mpu_with_request_checksum(self):"},{"line_number":3009,"context_line":"        self.swift.register("},{"line_number":3010,"context_line":"            \u0027HEAD\u0027, self.segment_bucket + \u0027/object/X/1\u0027,"},{"line_number":3011,"context_line":"            swob.HTTPOk, {"}],"source_content_type":"text/x-python","patch_set":145,"id":"fc8af0c5_bea999d6","line":3008,"updated":"2026-10-22 03:32:04.000000000","message":"merge into test_complete_legacy_checksum_request","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":3005,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket+segments/object/X/2\u0027),"},{"line_number":3006,"context_line":"        ], self.swift.calls)"},{"line_number":3007,"context_line":""},{"line_number":3008,"context_line":"    def test_complete_legacy_mpu_with_request_checksum(self):"},{"line_number":3009,"context_line":"        self.swift.register("},{"line_number":3010,"context_line":"            \u0027HEAD\u0027, self.segment_bucket + \u0027/object/X/1\u0027,"},{"line_number":3011,"context_line":"            swob.HTTPOk, {"}],"source_content_type":"text/x-python","patch_set":145,"id":"e56a60d5_36777a8b","line":3008,"in_reply_to":"fc8af0c5_bea999d6","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":3324,"context_line":"                    \u0027x-object-sysmeta-s3api-checksum-type\u0027):"},{"line_number":3325,"context_line":"            self.assertNotIn(key, put_call.footers)"},{"line_number":3326,"context_line":""},{"line_number":3327,"context_line":"    def test_complete_checksum_aware_missing_value_falls_back(self):"},{"line_number":3328,"context_line":"        part_one_checksum \u003d base64.b64encode("},{"line_number":3329,"context_line":"            checksum.crc32(b\u0027part one\u0027).digest()).decode(\u0027ascii\u0027)"},{"line_number":3330,"context_line":"        part_two_checksum \u003d base64.b64encode("}],"source_content_type":"text/x-python","patch_set":145,"id":"23c2ff33_7cf40c69","line":3327,"updated":"2026-10-22 03:32:04.000000000","message":"merge with test_complete_checksum_aware_missing_value_falls_back","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":3324,"context_line":"                    \u0027x-object-sysmeta-s3api-checksum-type\u0027):"},{"line_number":3325,"context_line":"            self.assertNotIn(key, put_call.footers)"},{"line_number":3326,"context_line":""},{"line_number":3327,"context_line":"    def test_complete_checksum_aware_missing_value_falls_back(self):"},{"line_number":3328,"context_line":"        part_one_checksum \u003d base64.b64encode("},{"line_number":3329,"context_line":"            checksum.crc32(b\u0027part one\u0027).digest()).decode(\u0027ascii\u0027)"},{"line_number":3330,"context_line":"        part_two_checksum \u003d base64.b64encode("}],"source_content_type":"text/x-python","patch_set":145,"id":"eae23503_d3bf3689","line":3327,"in_reply_to":"23c2ff33_7cf40c69","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":3897,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket+segments/object/X/2\u0027),"},{"line_number":3898,"context_line":"        ], self.swift.calls)"},{"line_number":3899,"context_line":""},{"line_number":3900,"context_line":"    def test_complete_composite_checksum_mismatch_reports_failing_part(self):"},{"line_number":3901,"context_line":"        part_one_checksum \u003d base64.b64encode("},{"line_number":3902,"context_line":"            checksum.crc32(b\u0027part one\u0027).digest()).decode(\u0027ascii\u0027)"},{"line_number":3903,"context_line":"        part_two_checksum \u003d base64.b64encode("}],"source_content_type":"text/x-python","patch_set":145,"id":"0e8de9aa_db48536f","line":3900,"updated":"2026-10-22 03:32:04.000000000","message":"merge into test_object_multipart_upload_complete_composite_checksum_mismatch","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":3897,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket+segments/object/X/2\u0027),"},{"line_number":3898,"context_line":"        ], self.swift.calls)"},{"line_number":3899,"context_line":""},{"line_number":3900,"context_line":"    def test_complete_composite_checksum_mismatch_reports_failing_part(self):"},{"line_number":3901,"context_line":"        part_one_checksum \u003d base64.b64encode("},{"line_number":3902,"context_line":"            checksum.crc32(b\u0027part one\u0027).digest()).decode(\u0027ascii\u0027)"},{"line_number":3903,"context_line":"        part_two_checksum \u003d base64.b64encode("}],"source_content_type":"text/x-python","patch_set":145,"id":"db8a1cb9_5f561ea9","line":3900,"in_reply_to":"0e8de9aa_db48536f","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":4045,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket+segments/object/X\u0027),"},{"line_number":4046,"context_line":"        ], self.swift.calls)"},{"line_number":4047,"context_line":""},{"line_number":4048,"context_line":"    def test_complete_composite_rejects_final_checksum_bad_base64(self):"},{"line_number":4049,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum(\u0027!!!!\u0027)"},{"line_number":4050,"context_line":""},{"line_number":4051,"context_line":"    def test_complete_composite_rejects_final_checksum_wrong_digest_size(self):"}],"source_content_type":"text/x-python","patch_set":145,"id":"477413e1_6a8db1e7","line":4048,"updated":"2026-10-22 03:32:04.000000000","message":"merge into test_complete_rejects_malformed_final_checksum","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":4045,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket+segments/object/X\u0027),"},{"line_number":4046,"context_line":"        ], self.swift.calls)"},{"line_number":4047,"context_line":""},{"line_number":4048,"context_line":"    def test_complete_composite_rejects_final_checksum_bad_base64(self):"},{"line_number":4049,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum(\u0027!!!!\u0027)"},{"line_number":4050,"context_line":""},{"line_number":4051,"context_line":"    def test_complete_composite_rejects_final_checksum_wrong_digest_size(self):"}],"source_content_type":"text/x-python","patch_set":145,"id":"6c0fdbeb_e8fdb911","line":4048,"in_reply_to":"477413e1_6a8db1e7","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":4048,"context_line":"    def test_complete_composite_rejects_final_checksum_bad_base64(self):"},{"line_number":4049,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum(\u0027!!!!\u0027)"},{"line_number":4050,"context_line":""},{"line_number":4051,"context_line":"    def test_complete_composite_rejects_final_checksum_wrong_digest_size(self):"},{"line_number":4052,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum("},{"line_number":4053,"context_line":"            base64.b64encode(b\u0027\\x00\u0027 * 32).decode(\u0027ascii\u0027) + \u0027-2\u0027)"},{"line_number":4054,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"6e4c8e72_b3030625","line":4051,"updated":"2026-10-22 03:32:04.000000000","message":"merge into test_complete_rejects_malformed_final_checksum","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":4048,"context_line":"    def test_complete_composite_rejects_final_checksum_bad_base64(self):"},{"line_number":4049,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum(\u0027!!!!\u0027)"},{"line_number":4050,"context_line":""},{"line_number":4051,"context_line":"    def test_complete_composite_rejects_final_checksum_wrong_digest_size(self):"},{"line_number":4052,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum("},{"line_number":4053,"context_line":"            base64.b64encode(b\u0027\\x00\u0027 * 32).decode(\u0027ascii\u0027) + \u0027-2\u0027)"},{"line_number":4054,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"d60a0b4d_773927f0","line":4051,"in_reply_to":"6e4c8e72_b3030625","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":4052,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum("},{"line_number":4053,"context_line":"            base64.b64encode(b\u0027\\x00\u0027 * 32).decode(\u0027ascii\u0027) + \u0027-2\u0027)"},{"line_number":4054,"context_line":""},{"line_number":4055,"context_line":"    def test_complete_composite_rejects_final_checksum_bad_part_count(self):"},{"line_number":4056,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum("},{"line_number":4057,"context_line":"            base64.b64encode(b\u0027\\x00\u0027 * 4).decode(\u0027ascii\u0027) + \u0027-abc\u0027)"},{"line_number":4058,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"f1e3a4d0_cce014eb","line":4055,"updated":"2026-10-22 03:32:04.000000000","message":"merge into test_complete_rejects_malformed_final_checksum","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":4052,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum("},{"line_number":4053,"context_line":"            base64.b64encode(b\u0027\\x00\u0027 * 32).decode(\u0027ascii\u0027) + \u0027-2\u0027)"},{"line_number":4054,"context_line":""},{"line_number":4055,"context_line":"    def test_complete_composite_rejects_final_checksum_bad_part_count(self):"},{"line_number":4056,"context_line":"        self._do_test_complete_rejects_malformed_final_checksum("},{"line_number":4057,"context_line":"            base64.b64encode(b\u0027\\x00\u0027 * 4).decode(\u0027ascii\u0027) + \u0027-abc\u0027)"},{"line_number":4058,"context_line":""}],"source_content_type":"text/x-python","patch_set":145,"id":"4295deab_2741fe17","line":4055,"in_reply_to":"f1e3a4d0_cce014eb","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":4224,"context_line":"        self.assertNotIn(\u0027swift.callback.update_footers\u0027, put_call.env)"},{"line_number":4225,"context_line":"        self.assertFalse(put_call.footers)"},{"line_number":4226,"context_line":""},{"line_number":4227,"context_line":"    def test_object_multipart_upload_complete_legacy_part_checksum("},{"line_number":4228,"context_line":"            self):"},{"line_number":4229,"context_line":"        part_checksum \u003d base64.b64encode("},{"line_number":4230,"context_line":"            checksum.crc32(b\u0027part one\u0027).digest()).decode(\u0027ascii\u0027)"}],"source_content_type":"text/x-python","patch_set":145,"id":"d99d5cb6_fbb86452","line":4227,"updated":"2026-10-22 03:32:04.000000000","message":"merge with test_object_multipart_upload_complete_legacy_checksum_type","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":4224,"context_line":"        self.assertNotIn(\u0027swift.callback.update_footers\u0027, put_call.env)"},{"line_number":4225,"context_line":"        self.assertFalse(put_call.footers)"},{"line_number":4226,"context_line":""},{"line_number":4227,"context_line":"    def test_object_multipart_upload_complete_legacy_part_checksum("},{"line_number":4228,"context_line":"            self):"},{"line_number":4229,"context_line":"        part_checksum \u003d base64.b64encode("},{"line_number":4230,"context_line":"            checksum.crc32(b\u0027part one\u0027).digest()).decode(\u0027ascii\u0027)"}],"source_content_type":"text/x-python","patch_set":145,"id":"b838d088_251d086f","line":4227,"in_reply_to":"d99d5cb6_fbb86452","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":4667,"context_line":"        self.assertEqual(\u0027FULL_OBJECT\u0027, put_call.footers.get("},{"line_number":4668,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-type\u0027))"},{"line_number":4669,"context_line":""},{"line_number":4670,"context_line":"    def test_complete_full_object_missing_part_metadata(self):"},{"line_number":4671,"context_line":"        part_one_checksum \u003d base64.b64encode("},{"line_number":4672,"context_line":"            checksum.crc32(b\u0027part one\u0027).digest()).decode(\u0027ascii\u0027)"},{"line_number":4673,"context_line":"        part_two_checksum \u003d base64.b64encode("}],"source_content_type":"text/x-python","patch_set":145,"id":"05789ed9_a7e74888","line":4670,"updated":"2026-10-22 03:32:04.000000000","message":"Merge the four stored-metadata variants with the same part request and no checksum response.","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":4667,"context_line":"        self.assertEqual(\u0027FULL_OBJECT\u0027, put_call.footers.get("},{"line_number":4668,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-type\u0027))"},{"line_number":4669,"context_line":""},{"line_number":4670,"context_line":"    def test_complete_full_object_missing_part_metadata(self):"},{"line_number":4671,"context_line":"        part_one_checksum \u003d base64.b64encode("},{"line_number":4672,"context_line":"            checksum.crc32(b\u0027part one\u0027).digest()).decode(\u0027ascii\u0027)"},{"line_number":4673,"context_line":"        part_two_checksum \u003d base64.b64encode("}],"source_content_type":"text/x-python","patch_set":145,"id":"aba2e4e8_7439c30c","line":4670,"in_reply_to":"05789ed9_a7e74888","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":4935,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket+segments/object/X/2\u0027),"},{"line_number":4936,"context_line":"        ], self.swift.calls)"},{"line_number":4937,"context_line":""},{"line_number":4938,"context_line":"    def test_object_multipart_upload_complete_full_object_type_mismatch("},{"line_number":4939,"context_line":"            self):"},{"line_number":4940,"context_line":"        part_one_checksum \u003d base64.b64encode("},{"line_number":4941,"context_line":"            checksum.crc32(b\u0027part one\u0027).digest()).decode(\u0027ascii\u0027)"}],"source_content_type":"text/x-python","patch_set":145,"id":"8f54116f_9219ce74","line":4938,"updated":"2026-10-22 03:32:04.000000000","message":"merge into new test_complete_rejects_final_checksum_algorithm_mismatch","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":4935,"context_line":"            (\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket+segments/object/X/2\u0027),"},{"line_number":4936,"context_line":"        ], self.swift.calls)"},{"line_number":4937,"context_line":""},{"line_number":4938,"context_line":"    def test_object_multipart_upload_complete_full_object_type_mismatch("},{"line_number":4939,"context_line":"            self):"},{"line_number":4940,"context_line":"        part_one_checksum \u003d base64.b64encode("},{"line_number":4941,"context_line":"            checksum.crc32(b\u0027part one\u0027).digest()).decode(\u0027ascii\u0027)"}],"source_content_type":"text/x-python","patch_set":145,"id":"0edb0669_477171d4","line":4938,"in_reply_to":"8f54116f_9219ce74","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":5484,"context_line":"            checksum_value\u003d\u0027AAAAAA\u003d\u003d-2\u0027,"},{"line_number":5485,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":5486,"context_line":""},{"line_number":5487,"context_line":"    def test_object_multipart_upload_retry_complete_with_matching_checksum("},{"line_number":5488,"context_line":"            self):"},{"line_number":5489,"context_line":"        self._do_test_object_multipart_upload_retry_complete("},{"line_number":5490,"context_line":"            extra_headers\u003d{\u0027X-Amz-Checksum-Crc32\u0027: \u0027AAAAAA\u003d\u003d-2\u0027},"}],"source_content_type":"text/x-python","patch_set":145,"id":"22112651_c3f7cd6b","line":5487,"updated":"2026-10-22 03:32:04.000000000","message":"merge with test_object_multipart_upload_retry_complete_with_checksum","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":5484,"context_line":"            checksum_value\u003d\u0027AAAAAA\u003d\u003d-2\u0027,"},{"line_number":5485,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":5486,"context_line":""},{"line_number":5487,"context_line":"    def test_object_multipart_upload_retry_complete_with_matching_checksum("},{"line_number":5488,"context_line":"            self):"},{"line_number":5489,"context_line":"        self._do_test_object_multipart_upload_retry_complete("},{"line_number":5490,"context_line":"            extra_headers\u003d{\u0027X-Amz-Checksum-Crc32\u0027: \u0027AAAAAA\u003d\u003d-2\u0027},"}],"source_content_type":"text/x-python","patch_set":145,"id":"1443ef6e_4f5937ca","line":5487,"in_reply_to":"22112651_c3f7cd6b","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":5503,"context_line":"            checksum_value\u003d\u0027AAAAAA\u003d\u003d-2\u0027,"},{"line_number":5504,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":5505,"context_line":""},{"line_number":5506,"context_line":"    def test_object_multipart_upload_retry_complete_full_object_part_checksums("},{"line_number":5507,"context_line":"            self):"},{"line_number":5508,"context_line":"        self._do_test_object_multipart_upload_retry_complete("},{"line_number":5509,"context_line":"            body\u003dself._complete_mpu_xml_with_crc32("}],"source_content_type":"text/x-python","patch_set":145,"id":"9017eee5_6d2fc130","line":5506,"updated":"2026-10-22 03:32:04.000000000","message":"merge with test_object_multipart_upload_retry_complete_composite_part_checksums","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":5503,"context_line":"            checksum_value\u003d\u0027AAAAAA\u003d\u003d-2\u0027,"},{"line_number":5504,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":5505,"context_line":""},{"line_number":5506,"context_line":"    def test_object_multipart_upload_retry_complete_full_object_part_checksums("},{"line_number":5507,"context_line":"            self):"},{"line_number":5508,"context_line":"        self._do_test_object_multipart_upload_retry_complete("},{"line_number":5509,"context_line":"            body\u003dself._complete_mpu_xml_with_crc32("}],"source_content_type":"text/x-python","patch_set":145,"id":"69273706_5c0eb763","line":5506,"in_reply_to":"9017eee5_6d2fc130","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":5533,"context_line":"            checksum_value\u003d\u0027AAAAAA\u003d\u003d-2\u0027,"},{"line_number":5534,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":5535,"context_line":""},{"line_number":5536,"context_line":"    def test_object_multipart_upload_retry_complete_ignores_final_algorithm("},{"line_number":5537,"context_line":"            self):"},{"line_number":5538,"context_line":"        # ... nor that the final checksum uses that algorithm"},{"line_number":5539,"context_line":"        self._do_test_object_multipart_upload_retry_complete("}],"source_content_type":"text/x-python","patch_set":145,"id":"a3ae742a_120bddea","line":5536,"updated":"2026-10-22 03:32:04.000000000","message":"merge with ``test_object_multipart_upload_retry_complete_ignores_checksum_type`` and ``test_object_multipart_upload_retry_complete_ignores_checksum_mismatch``","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":5533,"context_line":"            checksum_value\u003d\u0027AAAAAA\u003d\u003d-2\u0027,"},{"line_number":5534,"context_line":"            checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":5535,"context_line":""},{"line_number":5536,"context_line":"    def test_object_multipart_upload_retry_complete_ignores_final_algorithm("},{"line_number":5537,"context_line":"            self):"},{"line_number":5538,"context_line":"        # ... nor that the final checksum uses that algorithm"},{"line_number":5539,"context_line":"        self._do_test_object_multipart_upload_retry_complete("}],"source_content_type":"text/x-python","patch_set":145,"id":"9fb0b354_9461c5b1","line":5536,"in_reply_to":"a3ae742a_120bddea","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":7007,"context_line":"        self.assertNotIn(\u0027x-object-sysmeta-s3api-checksum-type\u0027,"},{"line_number":7008,"context_line":"                         put_call.footers)"},{"line_number":7009,"context_line":""},{"line_number":7010,"context_line":"    def test_upload_part_copy_checksum_aware_completes_without_checksum(self):"},{"line_number":7011,"context_line":"        self._register_checksum_upload_marker()"},{"line_number":7012,"context_line":"        status, headers, body \u003d self._test_copy_for_s3acl("},{"line_number":7013,"context_line":"            \u0027test:tester\u0027,"}],"source_content_type":"text/x-python","patch_set":145,"id":"43940e99_9a770bc8","line":7010,"updated":"2026-10-22 03:32:04.000000000","message":"merge with test_upload_part_copy_range_checksum_aware_completes_without_checksum","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":7007,"context_line":"        self.assertNotIn(\u0027x-object-sysmeta-s3api-checksum-type\u0027,"},{"line_number":7008,"context_line":"                         put_call.footers)"},{"line_number":7009,"context_line":""},{"line_number":7010,"context_line":"    def test_upload_part_copy_checksum_aware_completes_without_checksum(self):"},{"line_number":7011,"context_line":"        self._register_checksum_upload_marker()"},{"line_number":7012,"context_line":"        status, headers, body \u003d self._test_copy_for_s3acl("},{"line_number":7013,"context_line":"            \u0027test:tester\u0027,"}],"source_content_type":"text/x-python","patch_set":145,"id":"fe65d29b_ded2c0ea","line":7010,"in_reply_to":"43940e99_9a770bc8","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"}],"test/unit/common/middleware/s3api/test_s3request.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"a6860892fd5187bb59be34fa3e58571fa363faab","unresolved":false,"context_lines":[{"line_number":2655,"context_line":"                                     \u0027X-Amz-Checksum-Type\u0027: \u0027full_object\u0027})"},{"line_number":2656,"context_line":""},{"line_number":2657,"context_line":"        with mock.patch.object(checksum, \u0027crc32_combine_anycrc\u0027, None):"},{"line_number":2658,"context_line":"            with self.assertRaises(S3NotImplemented) as cm:"},{"line_number":2659,"context_line":"                S3Request(req.environ)"},{"line_number":2660,"context_line":""},{"line_number":2661,"context_line":"    def test_mpu_initiate_crc32_default_checksum_type(self):"}],"source_content_type":"text/x-python","patch_set":30,"id":"ab740476_8d528472","line":2658,"updated":"2026-07-09 19:42:51.000000000","message":"pep8: F841 local variable \u0027cm\u0027 is assigned to but never used","commit_id":"a3ec2e423c2775ab5fa668dc1a616edf06b7635b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1570,"context_line":"        self.assertNotIsInstance("},{"line_number":1571,"context_line":"            sigv4_req.environ[\u0027wsgi.input\u0027], s3request.ChecksummingInput)"},{"line_number":1572,"context_line":""},{"line_number":1573,"context_line":"    def test_sig_v4_unsgnd_pyld_does_not_install_calculating_input(self):"},{"line_number":1574,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1575,"context_line":"        sigv4_req \u003d self._test_sig_v4_unsigned_payload(body\u003dbody)"},{"line_number":1576,"context_line":"        self.assertNotIsInstance("}],"source_content_type":"text/x-python","patch_set":87,"id":"77d621ce_8e45da51","line":1573,"updated":"2026-08-10 16:59:30.000000000","message":"I\u0027m not sure if this test is necessary. While the test is valid is suggests that there might be a counter-example i.e. a scenario when we DO expect the client request to have a CalculatingChecksumInput, but there isn\u0027t.","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1570,"context_line":"        self.assertNotIsInstance("},{"line_number":1571,"context_line":"            sigv4_req.environ[\u0027wsgi.input\u0027], s3request.ChecksummingInput)"},{"line_number":1572,"context_line":""},{"line_number":1573,"context_line":"    def test_sig_v4_unsgnd_pyld_does_not_install_calculating_input(self):"},{"line_number":1574,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1575,"context_line":"        sigv4_req \u003d self._test_sig_v4_unsigned_payload(body\u003dbody)"},{"line_number":1576,"context_line":"        self.assertNotIsInstance("}],"source_content_type":"text/x-python","patch_set":87,"id":"9621c4b7_3d16088a","line":1573,"in_reply_to":"2180c719_d447d8b5","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1570,"context_line":"        self.assertNotIsInstance("},{"line_number":1571,"context_line":"            sigv4_req.environ[\u0027wsgi.input\u0027], s3request.ChecksummingInput)"},{"line_number":1572,"context_line":""},{"line_number":1573,"context_line":"    def test_sig_v4_unsgnd_pyld_does_not_install_calculating_input(self):"},{"line_number":1574,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1575,"context_line":"        sigv4_req \u003d self._test_sig_v4_unsigned_payload(body\u003dbody)"},{"line_number":1576,"context_line":"        self.assertNotIsInstance("}],"source_content_type":"text/x-python","patch_set":87,"id":"2180c719_d447d8b5","line":1573,"in_reply_to":"77d621ce_8e45da51","updated":"2026-08-11 01:06:16.000000000","message":"I could see that argument","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1597,"context_line":"            sigv4_req.environ[\u0027wsgi.input\u0027], s3request.ChecksummingInput)"},{"line_number":1598,"context_line":"        self.assertFalse(hasattr(sigv4_req, \u0027_checksumming_input\u0027))"},{"line_number":1599,"context_line":""},{"line_number":1600,"context_line":"    def test_sig_v4_unsgnd_pyld_installs_calculating_input(self):"},{"line_number":1601,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1602,"context_line":"        sigv4_req \u003d self._test_sig_v4_unsigned_payload(body\u003dbody)"},{"line_number":1603,"context_line":"        sigv4_req.calculate_checksum_metadata(\u0027x-amz-checksum-crc32\u0027)"}],"source_content_type":"text/x-python","patch_set":87,"id":"8059801a_e7e85b0c","line":1600,"updated":"2026-08-10 16:59:30.000000000","message":"I don\u0027t really like the re-use of the test naming pattern; the pattern is generally used to *construct* a request given different client headers and verify the request properties. So to me the test name suggests that a sig_v4_unsgnd_pyld client request gets a calculating input, which it doesn\u0027t.\n\nThis test is actually testing the ``calculate_checksum_metadata`` method behaviour of an already constructed request, so I suggest renaming to something like ``test_caclculate_checksum_metadata``","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1597,"context_line":"            sigv4_req.environ[\u0027wsgi.input\u0027], s3request.ChecksummingInput)"},{"line_number":1598,"context_line":"        self.assertFalse(hasattr(sigv4_req, \u0027_checksumming_input\u0027))"},{"line_number":1599,"context_line":""},{"line_number":1600,"context_line":"    def test_sig_v4_unsgnd_pyld_installs_calculating_input(self):"},{"line_number":1601,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1602,"context_line":"        sigv4_req \u003d self._test_sig_v4_unsigned_payload(body\u003dbody)"},{"line_number":1603,"context_line":"        sigv4_req.calculate_checksum_metadata(\u0027x-amz-checksum-crc32\u0027)"}],"source_content_type":"text/x-python","patch_set":87,"id":"8e3e206f_62160133","line":1600,"in_reply_to":"0942a766_5b3d8483","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1597,"context_line":"            sigv4_req.environ[\u0027wsgi.input\u0027], s3request.ChecksummingInput)"},{"line_number":1598,"context_line":"        self.assertFalse(hasattr(sigv4_req, \u0027_checksumming_input\u0027))"},{"line_number":1599,"context_line":""},{"line_number":1600,"context_line":"    def test_sig_v4_unsgnd_pyld_installs_calculating_input(self):"},{"line_number":1601,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1602,"context_line":"        sigv4_req \u003d self._test_sig_v4_unsigned_payload(body\u003dbody)"},{"line_number":1603,"context_line":"        sigv4_req.calculate_checksum_metadata(\u0027x-amz-checksum-crc32\u0027)"}],"source_content_type":"text/x-python","patch_set":87,"id":"0942a766_5b3d8483","line":1600,"in_reply_to":"8059801a_e7e85b0c","updated":"2026-08-11 01:06:16.000000000","message":"This is a better name for this test, thanks!","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1605,"context_line":"            sigv4_req.environ[\u0027wsgi.input\u0027],"},{"line_number":1606,"context_line":"            s3request.CalculatingChecksumInput)"},{"line_number":1607,"context_line":"        self.assertFalse(hasattr("},{"line_number":1608,"context_line":"            sigv4_req, \u0027_calculating_checksum_input\u0027))"},{"line_number":1609,"context_line":"        resp_body \u003d sigv4_req.environ[\u0027wsgi.input\u0027].read()"},{"line_number":1610,"context_line":"        self.assertEqual(body, resp_body)"},{"line_number":1611,"context_line":"        self.assertIsInstance("}],"source_content_type":"text/x-python","patch_set":87,"id":"fcc9937b_924b7f6c","line":1608,"updated":"2026-08-10 16:59:30.000000000","message":"why is the test singling out this particular non-existent attribute name?","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1605,"context_line":"            sigv4_req.environ[\u0027wsgi.input\u0027],"},{"line_number":1606,"context_line":"            s3request.CalculatingChecksumInput)"},{"line_number":1607,"context_line":"        self.assertFalse(hasattr("},{"line_number":1608,"context_line":"            sigv4_req, \u0027_calculating_checksum_input\u0027))"},{"line_number":1609,"context_line":"        resp_body \u003d sigv4_req.environ[\u0027wsgi.input\u0027].read()"},{"line_number":1610,"context_line":"        self.assertEqual(body, resp_body)"},{"line_number":1611,"context_line":"        self.assertIsInstance("}],"source_content_type":"text/x-python","patch_set":87,"id":"6dfd9217_3b094be3","line":1608,"in_reply_to":"bae3cac6_179f9045","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1605,"context_line":"            sigv4_req.environ[\u0027wsgi.input\u0027],"},{"line_number":1606,"context_line":"            s3request.CalculatingChecksumInput)"},{"line_number":1607,"context_line":"        self.assertFalse(hasattr("},{"line_number":1608,"context_line":"            sigv4_req, \u0027_calculating_checksum_input\u0027))"},{"line_number":1609,"context_line":"        resp_body \u003d sigv4_req.environ[\u0027wsgi.input\u0027].read()"},{"line_number":1610,"context_line":"        self.assertEqual(body, resp_body)"},{"line_number":1611,"context_line":"        self.assertIsInstance("}],"source_content_type":"text/x-python","patch_set":87,"id":"bae3cac6_179f9045","line":1608,"in_reply_to":"fcc9937b_924b7f6c","updated":"2026-08-11 01:06:16.000000000","message":"During my alterations of the test, this slipped past me, thanks for catching this!","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1610,"context_line":"        self.assertEqual(body, resp_body)"},{"line_number":1611,"context_line":"        self.assertIsInstance("},{"line_number":1612,"context_line":"            sigv4_req.environ[\u0027wsgi.input\u0027],"},{"line_number":1613,"context_line":"            s3request.CalculatingChecksumInput)"},{"line_number":1614,"context_line":""},{"line_number":1615,"context_line":"    def test_sig_v4_unsgnd_pyld_crc32_ok(self):"},{"line_number":1616,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"}],"source_content_type":"text/x-python","patch_set":87,"id":"c05f8fab_be7e180b","line":1613,"updated":"2026-08-10 16:59:30.000000000","message":"so the body was read and the input is still a CalculatingChecksumInput - not sure that is the most interesting thing - what about the value that was read and the caclulated checksum value?","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1610,"context_line":"        self.assertEqual(body, resp_body)"},{"line_number":1611,"context_line":"        self.assertIsInstance("},{"line_number":1612,"context_line":"            sigv4_req.environ[\u0027wsgi.input\u0027],"},{"line_number":1613,"context_line":"            s3request.CalculatingChecksumInput)"},{"line_number":1614,"context_line":""},{"line_number":1615,"context_line":"    def test_sig_v4_unsgnd_pyld_crc32_ok(self):"},{"line_number":1616,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"}],"source_content_type":"text/x-python","patch_set":87,"id":"d80ce1b9_3060f520","line":1613,"in_reply_to":"c05f8fab_be7e180b","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1646,"context_line":"            },"},{"line_number":1647,"context_line":"            sigv4_req._checksum_response_headers)"},{"line_number":1648,"context_line":""},{"line_number":1649,"context_line":"    def test_sig_v4_unsgnd_pyld_calculated_crc32_ok(self):"},{"line_number":1650,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1651,"context_line":"        sigv4_req \u003d self._test_sig_v4_unsigned_payload(body\u003dbody)"},{"line_number":1652,"context_line":"        sigv4_req.calculate_checksum_metadata(\u0027x-amz-checksum-crc32\u0027)"}],"source_content_type":"text/x-python","patch_set":87,"id":"a0de0291_fa8468d7","line":1649,"range":{"start_line":1649,"start_character":8,"end_line":1649,"end_character":51},"updated":"2026-08-10 16:59:30.000000000","message":"as above, this is testing ``calculate_checksum_metadata``","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1646,"context_line":"            },"},{"line_number":1647,"context_line":"            sigv4_req._checksum_response_headers)"},{"line_number":1648,"context_line":""},{"line_number":1649,"context_line":"    def test_sig_v4_unsgnd_pyld_calculated_crc32_ok(self):"},{"line_number":1650,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1651,"context_line":"        sigv4_req \u003d self._test_sig_v4_unsigned_payload(body\u003dbody)"},{"line_number":1652,"context_line":"        sigv4_req.calculate_checksum_metadata(\u0027x-amz-checksum-crc32\u0027)"}],"source_content_type":"text/x-python","patch_set":87,"id":"1bc0f62e_e41bcd4d","line":1649,"range":{"start_line":1649,"start_character":8,"end_line":1649,"end_character":51},"in_reply_to":"a0de0291_fa8468d7","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1672,"context_line":"        self.assertEqual({"},{"line_number":1673,"context_line":"            \u0027x-amz-checksum-crc32\u0027: expected_checksum,"},{"line_number":1674,"context_line":"            \u0027x-amz-checksum-type\u0027: \u0027FULL_OBJECT\u0027,"},{"line_number":1675,"context_line":"        }, sigv4_req._checksum_response_headers)"},{"line_number":1676,"context_line":""},{"line_number":1677,"context_line":"    def test_sig_v4_unsgnd_pyld_crc32_persist_sysmeta(self):"},{"line_number":1678,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"}],"source_content_type":"text/x-python","patch_set":87,"id":"31a3f82a_b5905664","line":1675,"updated":"2026-08-10 16:59:30.000000000","message":"ok this is more useful IMHO - the test actually verifies the behavior of the input - is this test perhaps a superset of the one at line 1600?","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1672,"context_line":"        self.assertEqual({"},{"line_number":1673,"context_line":"            \u0027x-amz-checksum-crc32\u0027: expected_checksum,"},{"line_number":1674,"context_line":"            \u0027x-amz-checksum-type\u0027: \u0027FULL_OBJECT\u0027,"},{"line_number":1675,"context_line":"        }, sigv4_req._checksum_response_headers)"},{"line_number":1676,"context_line":""},{"line_number":1677,"context_line":"    def test_sig_v4_unsgnd_pyld_crc32_persist_sysmeta(self):"},{"line_number":1678,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"}],"source_content_type":"text/x-python","patch_set":87,"id":"bebc6da9_bab74e6a","line":1675,"in_reply_to":"31a3f82a_b5905664","updated":"2026-08-11 01:06:16.000000000","message":"Yes!","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1672,"context_line":"        self.assertEqual({"},{"line_number":1673,"context_line":"            \u0027x-amz-checksum-crc32\u0027: expected_checksum,"},{"line_number":1674,"context_line":"            \u0027x-amz-checksum-type\u0027: \u0027FULL_OBJECT\u0027,"},{"line_number":1675,"context_line":"        }, sigv4_req._checksum_response_headers)"},{"line_number":1676,"context_line":""},{"line_number":1677,"context_line":"    def test_sig_v4_unsgnd_pyld_crc32_persist_sysmeta(self):"},{"line_number":1678,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"}],"source_content_type":"text/x-python","patch_set":87,"id":"3bb51cd0_7d91b8b5","line":1675,"in_reply_to":"bebc6da9_bab74e6a","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1785,"context_line":"        })"},{"line_number":1786,"context_line":""},{"line_number":1787,"context_line":"    @patch.object(S3Request, \u0027_validate_dates\u0027, lambda *a: None)"},{"line_number":1788,"context_line":"    def test_sig_v4_unsgnd_pyld_upload_part_crc32_does_not_persist_sysmeta("},{"line_number":1789,"context_line":"            self):"},{"line_number":1790,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1791,"context_line":"        crc \u003d base64.b64encode(checksum.crc32(body).digest())"}],"source_content_type":"text/x-python","patch_set":87,"id":"490ce75b_a6f03529","line":1788,"range":{"start_line":1788,"start_character":32,"end_line":1788,"end_character":44},"updated":"2026-08-10 16:59:30.000000000","message":"this might be better in test_multi_upload?","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1785,"context_line":"        })"},{"line_number":1786,"context_line":""},{"line_number":1787,"context_line":"    @patch.object(S3Request, \u0027_validate_dates\u0027, lambda *a: None)"},{"line_number":1788,"context_line":"    def test_sig_v4_unsgnd_pyld_upload_part_crc32_does_not_persist_sysmeta("},{"line_number":1789,"context_line":"            self):"},{"line_number":1790,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1791,"context_line":"        crc \u003d base64.b64encode(checksum.crc32(body).digest())"}],"source_content_type":"text/x-python","patch_set":87,"id":"9126c1f4_3db36fb4","line":1788,"range":{"start_line":1788,"start_character":32,"end_line":1788,"end_character":44},"in_reply_to":"490ce75b_a6f03529","updated":"2026-08-11 01:06:16.000000000","message":"We have variations of this test in test_multi_upload, though this was here because `S3Request` changes how it persists metadata depending on the request. THOUGH we probably should be moving this kind of behavior to the controller","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1785,"context_line":"        })"},{"line_number":1786,"context_line":""},{"line_number":1787,"context_line":"    @patch.object(S3Request, \u0027_validate_dates\u0027, lambda *a: None)"},{"line_number":1788,"context_line":"    def test_sig_v4_unsgnd_pyld_upload_part_crc32_does_not_persist_sysmeta("},{"line_number":1789,"context_line":"            self):"},{"line_number":1790,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1791,"context_line":"        crc \u003d base64.b64encode(checksum.crc32(body).digest())"}],"source_content_type":"text/x-python","patch_set":87,"id":"f66a5a4c_96d58314","line":1788,"range":{"start_line":1788,"start_character":32,"end_line":1788,"end_character":44},"in_reply_to":"9126c1f4_3db36fb4","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":1819,"context_line":"        }, sigv4_req._checksum_response_headers)"},{"line_number":1820,"context_line":""},{"line_number":1821,"context_line":"    @patch.object(S3Request, \u0027_validate_dates\u0027, lambda *a: None)"},{"line_number":1822,"context_line":"    def test_sig_v4_unsgnd_pyld_upload_part_crc32_persist_sysmeta(self):"},{"line_number":1823,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1824,"context_line":"        crc \u003d base64.b64encode(checksum.crc32(body).digest())"},{"line_number":1825,"context_line":"        req \u003d self._make_sig_v4_unsigned_payload_req("}],"source_content_type":"text/x-python","patch_set":87,"id":"2e81e54d_68371989","line":1822,"updated":"2026-08-10 16:59:30.000000000","message":"took me a while to perceive the difference in these two test setups... this test sets ``sigv4_req.persist_part_checksum \u003d True``, the previous one didn\u0027t\n\nmight be better named test_persist_part_checksum_[false|true]","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":true,"context_lines":[{"line_number":1819,"context_line":"        }, sigv4_req._checksum_response_headers)"},{"line_number":1820,"context_line":""},{"line_number":1821,"context_line":"    @patch.object(S3Request, \u0027_validate_dates\u0027, lambda *a: None)"},{"line_number":1822,"context_line":"    def test_sig_v4_unsgnd_pyld_upload_part_crc32_persist_sysmeta(self):"},{"line_number":1823,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1824,"context_line":"        crc \u003d base64.b64encode(checksum.crc32(body).digest())"},{"line_number":1825,"context_line":"        req \u003d self._make_sig_v4_unsigned_payload_req("}],"source_content_type":"text/x-python","patch_set":87,"id":"92e35036_50b6ad72","line":1822,"in_reply_to":"2e81e54d_68371989","updated":"2026-08-11 01:06:16.000000000","message":"Yea I think this can be more explicit","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ba1f15c045dc35c9169ebf1122da1b6e1fb0867e","unresolved":false,"context_lines":[{"line_number":1819,"context_line":"        }, sigv4_req._checksum_response_headers)"},{"line_number":1820,"context_line":""},{"line_number":1821,"context_line":"    @patch.object(S3Request, \u0027_validate_dates\u0027, lambda *a: None)"},{"line_number":1822,"context_line":"    def test_sig_v4_unsgnd_pyld_upload_part_crc32_persist_sysmeta(self):"},{"line_number":1823,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1824,"context_line":"        crc \u003d base64.b64encode(checksum.crc32(body).digest())"},{"line_number":1825,"context_line":"        req \u003d self._make_sig_v4_unsigned_payload_req("}],"source_content_type":"text/x-python","patch_set":87,"id":"2998e65c_8229711f","line":1822,"in_reply_to":"92e35036_50b6ad72","updated":"2026-08-19 23:49:24.000000000","message":"Done","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4aedfa7f72f686fbeb303dbd4a062e26ba0d744f","unresolved":true,"context_lines":[{"line_number":3465,"context_line":"                         s3req.controller)"},{"line_number":3466,"context_line":""},{"line_number":3467,"context_line":""},{"line_number":3468,"context_line":"class TestCalculatingChecksumInput(S3ApiTestCase):"},{"line_number":3469,"context_line":"    def test_too_short(self):"},{"line_number":3470,"context_line":"        raw \u003d b\u0027123456789\u0027"},{"line_number":3471,"context_line":"        wrapped \u003d s3request.CalculatingChecksumInput("}],"source_content_type":"text/x-python","patch_set":87,"id":"a46193a9_a1a4f6d6","line":3468,"updated":"2026-08-10 16:59:30.000000000","message":"oh, it seems we have no TestChecksummingInput! So this testcase is at least a start 😀","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a45afcbc18484bf75bd5a2bfcf8c54771b701177","unresolved":false,"context_lines":[{"line_number":3465,"context_line":"                         s3req.controller)"},{"line_number":3466,"context_line":""},{"line_number":3467,"context_line":""},{"line_number":3468,"context_line":"class TestCalculatingChecksumInput(S3ApiTestCase):"},{"line_number":3469,"context_line":"    def test_too_short(self):"},{"line_number":3470,"context_line":"        raw \u003d b\u0027123456789\u0027"},{"line_number":3471,"context_line":"        wrapped \u003d s3request.CalculatingChecksumInput("}],"source_content_type":"text/x-python","patch_set":87,"id":"9f910f56_2b505e1e","line":3468,"in_reply_to":"a46193a9_a1a4f6d6","updated":"2026-08-11 01:06:16.000000000","message":"Acknowledged","commit_id":"a62ccd24c5251047ffebb702bbd568b819169db9"}],"test/unit/common/middleware/test_slo.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":1399,"context_line":"            (\u0027DELETE\u0027, self.segment_container + \u0027/object/X\u0027),"},{"line_number":1400,"context_line":"        ], self.app.calls)"},{"line_number":1401,"context_line":""},{"line_number":1402,"context_line":"    def test_complete_mpu_manifest_hook_invalid_part(self):"},{"line_number":1403,"context_line":"        bad_part_one_checksum \u003d base64.b64encode("},{"line_number":1404,"context_line":"            checksum.crc32(b\u0027not part one\u0027).digest()).decode(\u0027ascii\u0027)"},{"line_number":1405,"context_line":"        self.assertNotEqual("}],"source_content_type":"text/x-python","patch_set":145,"id":"04323b93_41ab809f","line":1402,"updated":"2026-10-22 03:32:04.000000000","message":"covered by ``TestS3ApiMultiUpload.test_complete_composite_checksum_mismatch_reports_failing_part``","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":1399,"context_line":"            (\u0027DELETE\u0027, self.segment_container + \u0027/object/X\u0027),"},{"line_number":1400,"context_line":"        ], self.app.calls)"},{"line_number":1401,"context_line":""},{"line_number":1402,"context_line":"    def test_complete_mpu_manifest_hook_invalid_part(self):"},{"line_number":1403,"context_line":"        bad_part_one_checksum \u003d base64.b64encode("},{"line_number":1404,"context_line":"            checksum.crc32(b\u0027not part one\u0027).digest()).decode(\u0027ascii\u0027)"},{"line_number":1405,"context_line":"        self.assertNotEqual("}],"source_content_type":"text/x-python","patch_set":145,"id":"24423b17_8de2891d","line":1402,"in_reply_to":"04323b93_41ab809f","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":1440,"context_line":"        ], self.app.calls)"},{"line_number":1441,"context_line":""},{"line_number":1442,"context_line":"    @patch(\u0027swift.common.middleware.s3api.controllers.multi_upload.time\u0027)"},{"line_number":1443,"context_line":"    def test_complete_mpu_manifest_hook_success_after_heartbeat("},{"line_number":1444,"context_line":"            self, mock_time):"},{"line_number":1445,"context_line":"        self.slo.yield_frequency \u003d 0"},{"line_number":1446,"context_line":"        raw_part_checksums \u003d ("}],"source_content_type":"text/x-python","patch_set":145,"id":"0026ffdc_e26f510c","line":1443,"updated":"2026-10-22 03:32:04.000000000","message":"this is covered by ``TestS3ApiMultiUpload.test_checksum_mpu_success_delays_heartbeat``","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":1440,"context_line":"        ], self.app.calls)"},{"line_number":1441,"context_line":""},{"line_number":1442,"context_line":"    @patch(\u0027swift.common.middleware.s3api.controllers.multi_upload.time\u0027)"},{"line_number":1443,"context_line":"    def test_complete_mpu_manifest_hook_success_after_heartbeat("},{"line_number":1444,"context_line":"            self, mock_time):"},{"line_number":1445,"context_line":"        self.slo.yield_frequency \u003d 0"},{"line_number":1446,"context_line":"        raw_part_checksums \u003d ("}],"source_content_type":"text/x-python","patch_set":145,"id":"9479b5a5_49491cc8","line":1443,"in_reply_to":"0026ffdc_e26f510c","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"64c4294716c9678cd8bf81740595572dd84cb6bc","unresolved":true,"context_lines":[{"line_number":1493,"context_line":"        ], self.app.calls)"},{"line_number":1494,"context_line":""},{"line_number":1495,"context_line":"    @patch(\u0027swift.common.middleware.s3api.controllers.multi_upload.time\u0027)"},{"line_number":1496,"context_line":"    def test_complete_mpu_manifest_hook_error_after_heartbeat("},{"line_number":1497,"context_line":"            self, mock_time):"},{"line_number":1498,"context_line":"        self.slo.yield_frequency \u003d 0"},{"line_number":1499,"context_line":"        bad_part_one_checksum \u003d base64.b64encode("}],"source_content_type":"text/x-python","patch_set":145,"id":"f9ac551b_8bfeadbe","line":1496,"updated":"2026-10-22 03:32:04.000000000","message":"tested in ``TestS3ApiMultiUpload.test_checksum_mpu_bad_part_checksum_delays_heartbeat``","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ac7bf9bf0ef7f69f1a4b515a3e22a704a67b4e74","unresolved":false,"context_lines":[{"line_number":1493,"context_line":"        ], self.app.calls)"},{"line_number":1494,"context_line":""},{"line_number":1495,"context_line":"    @patch(\u0027swift.common.middleware.s3api.controllers.multi_upload.time\u0027)"},{"line_number":1496,"context_line":"    def test_complete_mpu_manifest_hook_error_after_heartbeat("},{"line_number":1497,"context_line":"            self, mock_time):"},{"line_number":1498,"context_line":"        self.slo.yield_frequency \u003d 0"},{"line_number":1499,"context_line":"        bad_part_one_checksum \u003d base64.b64encode("}],"source_content_type":"text/x-python","patch_set":145,"id":"040a7c00_745f92e4","line":1496,"in_reply_to":"f9ac551b_8bfeadbe","updated":"2026-10-22 03:38:52.000000000","message":"Done","commit_id":"3dba25af630971383b0838560cfbbabcc978004c"}]}
