)]}'
{"/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":"nmartes@NVIDIA.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"}],"/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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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"}],"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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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"}],"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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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_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":"nmartes@NVIDIA.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"}],"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"}],"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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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"}],"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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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":"nmartes@NVIDIA.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"}]}
