)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"623af8a227f0333d100b1de1bfd190b6a98e6cc4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"c18d1cbc_d496087f","updated":"2026-08-25 22:35:31.000000000","message":"This was pulled out of 993193: s3api: Checksum Persistence on MPUs | https://review.opendev.org/c/openstack/swift/+/993193 for ease of reviewing","commit_id":"14e090fb9ec571aea763a87cfdf5800fee7fe8b1"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"246a85a4_11d25ffd","updated":"2026-08-26 16:52:23.000000000","message":"I think my most significant feedback on this patch is can we keep things simple by just always persisting checksum sysmeta *whenever* it is calculated, and just filter response headers when they are not expected to have the checksum headers? My goal being less special cases, and consistent expectations of what we find on disk in object metadata.","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"a521c6ef_2241a77d","in_reply_to":"246a85a4_11d25ffd","updated":"2026-08-27 05:29:48.000000000","message":"\u003e  and just filter response headers when they are not expected to have the checksum headers? My goal being less special cases, and consistent expectations of what we find on disk in object metadata.\n\nYea I think this is more straightfoward, though we don\u0027t need to store that data, it is much eaiser to develop under if every checksummed object that has their sysmeta persisted, is all the same sysmeta","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"cf8a5361a2ad7205166922072366e4165098f391","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":10,"id":"f9b656fe_55e3e0a1","updated":"2026-08-27 22:24:20.000000000","message":"Just so we have it somewhere:\n\nfuture us will have to think of the following situations:\n\nListParts on Checksum MPUs when the client did not make the MPU checksum-aware\n\nAWS does not expose the part checksums in this case, so we need to make sure not to even though every part will have checksum metadata\nGetObject \u0026 HeadObject on Checksum MPUs when the client did not make the MPU checksum-aware\n\nAWS (for COMPOSITE checksum MPUs) exposes part checksum when a client GETs the object part. We should not expose the part checksum even if it exists unless it is a COMPOSITE MPU checksum","commit_id":"3c24b3be1b69799071071840ad7fb92e670e8b0c"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"b61e9fb0f50f45febde6f178293d76ed19cf3857","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"be678a2d_de005ba8","updated":"2026-08-27 22:06:56.000000000","message":"Some things here:\n\nSquashed in 1002659: sq? always persist mpu part checksum sysmeta when available | https://review.opendev.org/c/openstack/swift/+/1002659\n\nI had done refactoring of some test cases, however, I think to get this over the line, we can do that later so I pushed up a patch near the end of the chain for that 1002697: tests: clean up s3api/test_object_checksums | https://review.opendev.org/c/openstack/swift/+/1002697","commit_id":"3c24b3be1b69799071071840ad7fb92e670e8b0c"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"b07f647be614d3047225455cb223ec4b7f54a81e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"4b539ab0_8330a1c9","updated":"2026-09-01 15:32:09.000000000","message":"I\u0027m also pretty confident about this patch.\n\nThe only thing that I\u0027m concerned about is the anycrc runtime requirement but missing addition in the requirements list. This is becoming user-facing with this patch, because a user could see a 501 if it is not installed.","commit_id":"c4841758aa7979be753960c6f22dfde9e1d02c4e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"558e28f4468f6b202ca4458528be06d5c48434a4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"46d1fad2_41c070cc","updated":"2026-08-28 12:10:16.000000000","message":"I\u0027ve run out of time for full review but leaving a +1 to indicate that I\u0027m reasonably confident we\u0027ve got this patch in good shape","commit_id":"c4841758aa7979be753960c6f22dfde9e1d02c4e"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"9048c043d982df74933bcce18a19f08da7514793","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"311cf3c8_566f3835","updated":"2026-09-03 20:51:22.000000000","message":"flag out an anycrc dependency issue","commit_id":"c4841758aa7979be753960c6f22dfde9e1d02c4e"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"6d45942040ac46ef29c65a4d719740374c0c0bca","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"4b24efe4_7678161c","in_reply_to":"4b539ab0_8330a1c9","updated":"2026-09-01 18:07:28.000000000","message":"I\u0027ll make the error code change a follow up patch","commit_id":"c4841758aa7979be753960c6f22dfde9e1d02c4e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"53633203c24107e2dfe1fb6c1b14d97f393cb8e9","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"f1e03d05_a45381be","updated":"2026-09-16 15:02:51.000000000","message":"@Nate I had changes to the whole patch chain to push that were based around patchset 18 so I moved your recent diff 18-\u003e20 out to a sq? patch to consider separately: 1005868: sq? refactor checksum_sysmeta_to_response_headers | https://review.opendev.org/c/openstack/swift/+/1005868","commit_id":"3898c45a365c20aae40e3880aa2c1dcaba27691f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"70ab7c08ec3e5c926525417239b31bc45fcf1555","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"1fa59156_e10d75d0","updated":"2026-09-16 16:14:34.000000000","message":"These make things much better to follow, just remove the header we DONT want in the output 💡 thanks for these! I think I can clean up my 1005868: sq? refactor checksum_sysmeta_to_response_headers | https://review.opendev.org/c/openstack/swift/+/1005868 to not actually touch the sysmeta to response stuff (because I think the caller removing the headers is better) to handle the `anycrc` 501 handling (which is in there...)","commit_id":"3898c45a365c20aae40e3880aa2c1dcaba27691f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"07d92425f88a583989967df2db99e9a71ebe96e5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"b1dfe2ab_00b9b7ad","in_reply_to":"f1e03d05_a45381be","updated":"2026-09-16 16:01:25.000000000","message":"Gotcha seems good to me!","commit_id":"3898c45a365c20aae40e3880aa2c1dcaba27691f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"270e626fd8e159fb451048751f99931faf714f99","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":25,"id":"2ebb4aae_0cc48c81","updated":"2026-09-20 03:20:35.000000000","message":"recheck","commit_id":"f2876cf1951b35de042b95bc28a8c1fef29ee9b6"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"0a5def4a36fd889e2e12e39293b04bd43624d18a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":25,"id":"0590a870_a2ad3084","updated":"2026-09-19 21:24:57.000000000","message":"reheck","commit_id":"f2876cf1951b35de042b95bc28a8c1fef29ee9b6"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":27,"id":"1d03a0b9_a503351e","updated":"2026-10-14 23:38:20.000000000","message":"Rebased to use feature flag, and removed/combined quite a lot of test cases.","commit_id":"0d1f9cfc78766ff2db4213c2b3a339c12d6e8bde"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"6ecb0a135da31e536b8e838f7c4e999455cd91b2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":31,"id":"039b9c63_baeaa564","updated":"2026-10-22 12:40:45.000000000","message":"Agents found a minor issue that should be fixed, but can be done later as well:  1011849: s3api: Always check the part checksum algorithm | https://review.opendev.org/c/openstack/swift/+/1011849","commit_id":"5e850a56002e10e0b631719f34c56fec805d764a"}],"swift/common/middleware/s3api/controllers/multi_upload.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":105,"context_line":"MAX_COMPLETE_UPLOAD_BODY_SIZE \u003d 2048 * 1024"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"def get_checksum_hasher(header):"},{"line_number":109,"context_line":"    \"\"\"Return an S3 checksum hasher or raise an S3 response error.\"\"\""},{"line_number":110,"context_line":"    # This is to avoid cyclical imports between checksum and s3response."},{"line_number":111,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":6,"id":"db056785_db2dd75a","line":108,"updated":"2026-08-26 16:52:23.000000000","message":"in s3request this is underscore prefixed ``_get_checksum_hasher`` so that the import does not need to be aliased. I think it would be better to be consistent and do the same here.\n\nalthough Claude disagrees with me!","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"be3596e58080e312b104b801368b340a2e862ea0","unresolved":false,"context_lines":[{"line_number":105,"context_line":"MAX_COMPLETE_UPLOAD_BODY_SIZE \u003d 2048 * 1024"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"def get_checksum_hasher(header):"},{"line_number":109,"context_line":"    \"\"\"Return an S3 checksum hasher or raise an S3 response error.\"\"\""},{"line_number":110,"context_line":"    # This is to avoid cyclical imports between checksum and s3response."},{"line_number":111,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":6,"id":"7175c72a_cd2939cb","line":108,"in_reply_to":"7971e6fc_03ac7d11","updated":"2026-08-27 06:36:59.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":105,"context_line":"MAX_COMPLETE_UPLOAD_BODY_SIZE \u003d 2048 * 1024"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"def get_checksum_hasher(header):"},{"line_number":109,"context_line":"    \"\"\"Return an S3 checksum hasher or raise an S3 response error.\"\"\""},{"line_number":110,"context_line":"    # This is to avoid cyclical imports between checksum and s3response."},{"line_number":111,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":6,"id":"7971e6fc_03ac7d11","line":108,"in_reply_to":"db056785_db2dd75a","updated":"2026-08-27 05:29:48.000000000","message":"I also disagree with claude here. We should be consist with what we do across files.","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":278,"context_line":"    # which will be COMPOSITE, unless the algorithm cannot"},{"line_number":279,"context_line":"    # be COMPOSITE"},{"line_number":280,"context_line":"    if checksum_attrs.type is None:"},{"line_number":281,"context_line":"        if (checksum_attrs.header not in"},{"line_number":282,"context_line":"                COMPOSITE_MPU_CHECKSUM_HEADERS):"},{"line_number":283,"context_line":"            checksum_attrs.type \u003d CHECKSUM_TYPE_FULL_OBJECT"},{"line_number":284,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":6,"id":"fc41b640_31899bdf","line":281,"updated":"2026-08-26 16:52:23.000000000","message":"nit: the ``not`` can be avoided by inverting the logic of the if/else","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"be3596e58080e312b104b801368b340a2e862ea0","unresolved":false,"context_lines":[{"line_number":278,"context_line":"    # which will be COMPOSITE, unless the algorithm cannot"},{"line_number":279,"context_line":"    # be COMPOSITE"},{"line_number":280,"context_line":"    if checksum_attrs.type is None:"},{"line_number":281,"context_line":"        if (checksum_attrs.header not in"},{"line_number":282,"context_line":"                COMPOSITE_MPU_CHECKSUM_HEADERS):"},{"line_number":283,"context_line":"            checksum_attrs.type \u003d CHECKSUM_TYPE_FULL_OBJECT"},{"line_number":284,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":6,"id":"40d434de_e726ad0e","line":281,"in_reply_to":"5f17bbfb_53096eff","updated":"2026-08-27 06:36:59.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":278,"context_line":"    # which will be COMPOSITE, unless the algorithm cannot"},{"line_number":279,"context_line":"    # be COMPOSITE"},{"line_number":280,"context_line":"    if checksum_attrs.type is None:"},{"line_number":281,"context_line":"        if (checksum_attrs.header not in"},{"line_number":282,"context_line":"                COMPOSITE_MPU_CHECKSUM_HEADERS):"},{"line_number":283,"context_line":"            checksum_attrs.type \u003d CHECKSUM_TYPE_FULL_OBJECT"},{"line_number":284,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f17bbfb_53096eff","line":281,"in_reply_to":"fc41b640_31899bdf","updated":"2026-08-27 05:29:48.000000000","message":"Yea this might look cleaner","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":290,"context_line":"    checksum_hasher \u003d get_checksum_hasher(checksum_attrs.header)"},{"line_number":291,"context_line":"    if checksum_attrs.is_full_object:"},{"line_number":292,"context_line":"        # The current proxy server might not have a crc_combine function"},{"line_number":293,"context_line":"        # so lets not make a MPU we cannot complete"},{"line_number":294,"context_line":"        if checksum_hasher.crc_combine_func is None:"},{"line_number":295,"context_line":"            raise S3NotImplemented("},{"line_number":296,"context_line":"                \u0027The %s algorithm is not supported for full object \u0027"}],"source_content_type":"text/x-python","patch_set":6,"id":"9f6c441b_58c08d5c","line":293,"updated":"2026-08-26 16:52:23.000000000","message":"...although what matters is if the proxy handling the *mpu complete* has anycrc, which leads to an interesting upgrade story.\n\nBut IMHO we should make this early check, here, because if this proxy does not have anycrc then there\u0027s a chance the completing proxy won\u0027t; and also note: we must make the same check during complete.","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":290,"context_line":"    checksum_hasher \u003d get_checksum_hasher(checksum_attrs.header)"},{"line_number":291,"context_line":"    if checksum_attrs.is_full_object:"},{"line_number":292,"context_line":"        # The current proxy server might not have a crc_combine function"},{"line_number":293,"context_line":"        # so lets not make a MPU we cannot complete"},{"line_number":294,"context_line":"        if checksum_hasher.crc_combine_func is None:"},{"line_number":295,"context_line":"            raise S3NotImplemented("},{"line_number":296,"context_line":"                \u0027The %s algorithm is not supported for full object \u0027"}],"source_content_type":"text/x-python","patch_set":6,"id":"a538e330_30d073f7","line":293,"in_reply_to":"9f6c441b_58c08d5c","updated":"2026-08-27 05:29:48.000000000","message":"I agree, I like that the check runs early and we should do the same with CompleteMultiPartUpload","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2bd7377e84358203b53ac6c16ba3466f636da3de","unresolved":false,"context_lines":[{"line_number":290,"context_line":"    checksum_hasher \u003d get_checksum_hasher(checksum_attrs.header)"},{"line_number":291,"context_line":"    if checksum_attrs.is_full_object:"},{"line_number":292,"context_line":"        # The current proxy server might not have a crc_combine function"},{"line_number":293,"context_line":"        # so lets not make a MPU we cannot complete"},{"line_number":294,"context_line":"        if checksum_hasher.crc_combine_func is None:"},{"line_number":295,"context_line":"            raise S3NotImplemented("},{"line_number":296,"context_line":"                \u0027The %s algorithm is not supported for full object \u0027"}],"source_content_type":"text/x-python","patch_set":6,"id":"b9add0a4_dd57e738","line":293,"in_reply_to":"a538e330_30d073f7","updated":"2026-08-27 15:16:04.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":323,"context_line":"        # the wrapper ourselves"},{"line_number":324,"context_line":"        req.install_checksumming_input("},{"line_number":325,"context_line":"            checksum_hasher, checksum_attrs.header, None)"},{"line_number":326,"context_line":"    else:"},{"line_number":327,"context_line":"        raise InvalidRequest("},{"line_number":328,"context_line":"            \u0027Checksum Type mismatch occurred, expected checksum \u0027"},{"line_number":329,"context_line":"            \u0027Type: %s, actual checksum Type: null\u0027 %"}],"source_content_type":"text/x-python","patch_set":6,"id":"4dd14b7f_5da74543","line":326,"updated":"2026-08-26 16:52:23.000000000","message":"I keep tripping up on this; could we add a comment that S3 uses \u0027type\u0027 to refer to algorithm","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"be3596e58080e312b104b801368b340a2e862ea0","unresolved":false,"context_lines":[{"line_number":323,"context_line":"        # the wrapper ourselves"},{"line_number":324,"context_line":"        req.install_checksumming_input("},{"line_number":325,"context_line":"            checksum_hasher, checksum_attrs.header, None)"},{"line_number":326,"context_line":"    else:"},{"line_number":327,"context_line":"        raise InvalidRequest("},{"line_number":328,"context_line":"            \u0027Checksum Type mismatch occurred, expected checksum \u0027"},{"line_number":329,"context_line":"            \u0027Type: %s, actual checksum Type: null\u0027 %"}],"source_content_type":"text/x-python","patch_set":6,"id":"7f5cbb64_94eaf259","line":326,"in_reply_to":"0c3e7337_8d4c464b","updated":"2026-08-27 06:36:59.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":323,"context_line":"        # the wrapper ourselves"},{"line_number":324,"context_line":"        req.install_checksumming_input("},{"line_number":325,"context_line":"            checksum_hasher, checksum_attrs.header, None)"},{"line_number":326,"context_line":"    else:"},{"line_number":327,"context_line":"        raise InvalidRequest("},{"line_number":328,"context_line":"            \u0027Checksum Type mismatch occurred, expected checksum \u0027"},{"line_number":329,"context_line":"            \u0027Type: %s, actual checksum Type: null\u0027 %"}],"source_content_type":"text/x-python","patch_set":6,"id":"0c3e7337_8d4c464b","line":326,"in_reply_to":"4dd14b7f_5da74543","updated":"2026-08-27 05:29:48.000000000","message":"Sure!","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":446,"context_line":"            _validate_upload_part_checksum_headers("},{"line_number":447,"context_line":"                req, mpu_checksum_attrs)"},{"line_number":448,"context_line":"            # Parts persist the checksum header and value without an"},{"line_number":449,"context_line":"            # object-level checksum type."},{"line_number":450,"context_line":"            req.enable_checksum_persistence(None)"},{"line_number":451,"context_line":""},{"line_number":452,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"}],"source_content_type":"text/x-python","patch_set":6,"id":"786375e5_6fca4a32","line":449,"updated":"2026-08-26 16:52:23.000000000","message":"I feel like *Swift\u0027s* internal implementation could be simpler: the type of an object PUT checksum is always FULL_OBJECT, we just don\u0027t return that header with an UploadPartCopy response.\n\nThen we can drop the arg to ``enable_checksum_persistence``, always expect the same set of sysmeta, and just vary the response headers.","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"be3596e58080e312b104b801368b340a2e862ea0","unresolved":false,"context_lines":[{"line_number":446,"context_line":"            _validate_upload_part_checksum_headers("},{"line_number":447,"context_line":"                req, mpu_checksum_attrs)"},{"line_number":448,"context_line":"            # Parts persist the checksum header and value without an"},{"line_number":449,"context_line":"            # object-level checksum type."},{"line_number":450,"context_line":"            req.enable_checksum_persistence(None)"},{"line_number":451,"context_line":""},{"line_number":452,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"}],"source_content_type":"text/x-python","patch_set":6,"id":"665c7df1_3b9656ef","line":449,"in_reply_to":"569507ed_c2c6632b","updated":"2026-08-27 06:36:59.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":446,"context_line":"            _validate_upload_part_checksum_headers("},{"line_number":447,"context_line":"                req, mpu_checksum_attrs)"},{"line_number":448,"context_line":"            # Parts persist the checksum header and value without an"},{"line_number":449,"context_line":"            # object-level checksum type."},{"line_number":450,"context_line":"            req.enable_checksum_persistence(None)"},{"line_number":451,"context_line":""},{"line_number":452,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"}],"source_content_type":"text/x-python","patch_set":6,"id":"569507ed_c2c6632b","line":449,"in_reply_to":"786375e5_6fca4a32","updated":"2026-08-27 05:29:48.000000000","message":"Yea I think this is more straightfoward, though we don\u0027t need to store that data, it is much eaiser to develop under if every checksummed object that has their sysmeta persisted, is all the same sysmeta","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":489,"context_line":""},{"line_number":490,"context_line":"        if req.checksum_sysmeta_footers:"},{"line_number":491,"context_line":"            # UploadPart requests do not echo the type,"},{"line_number":492,"context_line":"            # so do not require it here"},{"line_number":493,"context_line":"            resp.headers.update(checksum_sysmeta_to_response_headers("},{"line_number":494,"context_line":"                req.checksum_sysmeta_footers, require_type\u003dFalse))"},{"line_number":495,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"e38d1739_95079ffd","line":492,"updated":"2026-08-26 16:52:23.000000000","message":"the meaning of the comment is a bit ambiguous without understanding that we don\u0027t persist type for an UploadPart. Can we just keep it simple and always persist ``(type, algorithm, value)`` for any put and then filter out ``type`` in ``UploadPartCopy`` responses?\n\nfewer variations -\u003e less code, less tests -\u003e easier to maintain","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"be3596e58080e312b104b801368b340a2e862ea0","unresolved":false,"context_lines":[{"line_number":489,"context_line":""},{"line_number":490,"context_line":"        if req.checksum_sysmeta_footers:"},{"line_number":491,"context_line":"            # UploadPart requests do not echo the type,"},{"line_number":492,"context_line":"            # so do not require it here"},{"line_number":493,"context_line":"            resp.headers.update(checksum_sysmeta_to_response_headers("},{"line_number":494,"context_line":"                req.checksum_sysmeta_footers, require_type\u003dFalse))"},{"line_number":495,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"dbef6bd7_00dd42d0","line":492,"in_reply_to":"bb7d3866_f45c3f93","updated":"2026-08-27 06:36:59.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":489,"context_line":""},{"line_number":490,"context_line":"        if req.checksum_sysmeta_footers:"},{"line_number":491,"context_line":"            # UploadPart requests do not echo the type,"},{"line_number":492,"context_line":"            # so do not require it here"},{"line_number":493,"context_line":"            resp.headers.update(checksum_sysmeta_to_response_headers("},{"line_number":494,"context_line":"                req.checksum_sysmeta_footers, require_type\u003dFalse))"},{"line_number":495,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"bb7d3866_f45c3f93","line":492,"in_reply_to":"e38d1739_95079ffd","updated":"2026-08-27 05:29:48.000000000","message":"Sure I think it will be easier to maintain too","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"9048c043d982df74933bcce18a19f08da7514793","unresolved":true,"context_lines":[{"line_number":125,"context_line":"        raise S3NotImplemented("},{"line_number":126,"context_line":"            \u0027The %s algorithm is not supported.\u0027 %"},{"line_number":127,"context_line":"            checksum_attrs.algorithm.lower())"},{"line_number":128,"context_line":"    if require_combine and not hasher.can_combine:"},{"line_number":129,"context_line":"        raise S3NotImplemented("},{"line_number":130,"context_line":"            \u0027The %s algorithm supports full object checksums, but this \u0027"},{"line_number":131,"context_line":"            \u0027server is missing the CRC combine support required to \u0027"}],"source_content_type":"text/x-python","patch_set":14,"id":"1331a201_a2b40a82","line":128,"updated":"2026-09-03 20:51:22.000000000","message":"for FULL_OBJECT checksum, CreateMultipartUpload will return 501 if ``anycrc`` is not around. we need to land either “1002436: Add anycrc to global requirements | https://review.opendev.org/c/openstack/requirements/+/1002436” or \"1003875: checksum: Add Python fallback for combine methods | https://review.opendev.org/c/openstack/swift/+/1003875\" ahead of this patch.","commit_id":"c4841758aa7979be753960c6f22dfde9e1d02c4e"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"164f5b826bbc72025c2ec4cb14bd7d9789e1382c","unresolved":true,"context_lines":[{"line_number":125,"context_line":"        raise S3NotImplemented("},{"line_number":126,"context_line":"            \u0027The %s algorithm is not supported.\u0027 %"},{"line_number":127,"context_line":"            checksum_attrs.algorithm.lower())"},{"line_number":128,"context_line":"    if require_combine and not hasher.can_combine:"},{"line_number":129,"context_line":"        raise S3NotImplemented("},{"line_number":130,"context_line":"            \u0027The %s algorithm supports full object checksums, but this \u0027"},{"line_number":131,"context_line":"            \u0027server is missing the CRC combine support required to \u0027"}],"source_content_type":"text/x-python","patch_set":14,"id":"a1f4a50e_b68ab7c4","line":128,"in_reply_to":"1331a201_a2b40a82","updated":"2026-09-15 20:34:02.000000000","message":"So I did some checking and on `CreateMultipartUpload` we actually call `get_checksum_hasher` not `_get_checksum_hasher` that is not very clear...\n\nI added some updates to handle this for CreateMultipartUpload... but I think they can be better","commit_id":"c4841758aa7979be753960c6f22dfde9e1d02c4e"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"df97c7d08caccc6d8455ba55ea2cdc17176a84b5","unresolved":false,"context_lines":[{"line_number":125,"context_line":"        raise S3NotImplemented("},{"line_number":126,"context_line":"            \u0027The %s algorithm is not supported.\u0027 %"},{"line_number":127,"context_line":"            checksum_attrs.algorithm.lower())"},{"line_number":128,"context_line":"    if require_combine and not hasher.can_combine:"},{"line_number":129,"context_line":"        raise S3NotImplemented("},{"line_number":130,"context_line":"            \u0027The %s algorithm supports full object checksums, but this \u0027"},{"line_number":131,"context_line":"            \u0027server is missing the CRC combine support required to \u0027"}],"source_content_type":"text/x-python","patch_set":14,"id":"af22122b_f8900594","line":128,"in_reply_to":"a1f4a50e_b68ab7c4","updated":"2026-10-15 05:10:19.000000000","message":"anycrc is a hard dependency on master now.","commit_id":"c4841758aa7979be753960c6f22dfde9e1d02c4e"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"70ab7c08ec3e5c926525417239b31bc45fcf1555","unresolved":false,"context_lines":[{"line_number":307,"context_line":""},{"line_number":308,"context_line":"    # Do not create an MPU that this proxy cannot calculate checksums for."},{"line_number":309,"context_line":"    _get_checksum_hasher("},{"line_number":310,"context_line":"        checksum_attrs, require_combine\u003dchecksum_attrs.is_full_object)"},{"line_number":311,"context_line":""},{"line_number":312,"context_line":""},{"line_number":313,"context_line":"def _validate_upload_part_checksum_headers("}],"source_content_type":"text/x-python","patch_set":21,"id":"87725442_98948961","line":310,"range":{"start_line":310,"start_character":0,"end_line":310,"end_character":2},"updated":"2026-09-16 16:14:34.000000000","message":"I think this is better because we have the helper \u0027_get_checksum_hasher\u0027 so why use the function we imported, that\u0027ll make things inconsistent.","commit_id":"3898c45a365c20aae40e3880aa2c1dcaba27691f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"70ab7c08ec3e5c926525417239b31bc45fcf1555","unresolved":false,"context_lines":[{"line_number":504,"context_line":"        if req.checksum_sysmeta_footers:"},{"line_number":505,"context_line":"            resp.headers.update(checksum_sysmeta_to_response_headers("},{"line_number":506,"context_line":"                req.checksum_sysmeta_footers))"},{"line_number":507,"context_line":"            resp.headers.pop(\u0027x-amz-checksum-type\u0027, None)"},{"line_number":508,"context_line":"        if \u0027X-Amz-Copy-Source\u0027 in req.headers:"},{"line_number":509,"context_line":"            last_modified_ts \u003d S3Timestamp("},{"line_number":510,"context_line":"                parse_date_header(resp.headers[\u0027Last-Modified\u0027]))"}],"source_content_type":"text/x-python","patch_set":21,"id":"971e6c79_f03bd688","line":507,"range":{"start_line":507,"start_character":0,"end_line":507,"end_character":2},"updated":"2026-09-16 16:14:34.000000000","message":"Oh! well this works too! just give the caller ALL the headers and then the caller clears out what it knows is bad....\n\nhuh... I think this is better too since the only people that would be doing this would be MPU init and UploadPart","commit_id":"3898c45a365c20aae40e3880aa2c1dcaba27691f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5d09de6ccc734f4656518ba180d9079912255b9c","unresolved":true,"context_lines":[{"line_number":465,"context_line":"                # Write down a sentinel header so that we know this part came"},{"line_number":466,"context_line":"                # into the MPU from a new proxy"},{"line_number":467,"context_line":"                req.headers[s3api_sysmeta_header("},{"line_number":468,"context_line":"                    \u0027object\u0027, \u0027checksum-upload-id\u0027)] \u003d upload_id"},{"line_number":469,"context_line":""},{"line_number":470,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"},{"line_number":471,"context_line":"        req.object_name \u003d \u0027%s/%s/%d\u0027 % (req.object_name, upload_id,"}],"source_content_type":"text/x-python","patch_set":22,"id":"fd1db2c6_f3eabb07","line":468,"updated":"2026-09-17 07:43:09.000000000","message":"I\u0027m trying to remember why we added the x-object-sysmeta-checksum-upload-id sentinel? was this to guard against an UploadPartCopy making a ranged copy with incorrect checksum sysmeta, in which case the copied x-object-sysmeta-checksum-upload-id would not match the current upload-id?\n\nI’m wondering if we still need it now that we have a copy hook removing all sysmeta from copies","commit_id":"4a199298f77f6641819d9b7eeec001dc16d7db9f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"f4f615d31881ad30ee89eda315f2ffa86ef12bf7","unresolved":true,"context_lines":[{"line_number":465,"context_line":"                # Write down a sentinel header so that we know this part came"},{"line_number":466,"context_line":"                # into the MPU from a new proxy"},{"line_number":467,"context_line":"                req.headers[s3api_sysmeta_header("},{"line_number":468,"context_line":"                    \u0027object\u0027, \u0027checksum-upload-id\u0027)] \u003d upload_id"},{"line_number":469,"context_line":""},{"line_number":470,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"},{"line_number":471,"context_line":"        req.object_name \u003d \u0027%s/%s/%d\u0027 % (req.object_name, upload_id,"}],"source_content_type":"text/x-python","patch_set":22,"id":"a0e3fffd_8866ba31","line":468,"in_reply_to":"30606850_31863ae2","updated":"2026-09-18 05:23:34.000000000","message":"we haven’t fully utilized the upload_id sentinel yet, this will help: https://review.opendev.org/c/openstack/swift/+/993193/138..139/swift/common/middleware/s3api/controllers/multi_upload.py","commit_id":"4a199298f77f6641819d9b7eeec001dc16d7db9f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"f326e1706dcb9ce0454dc3f63ed0767f5b0aa3e4","unresolved":true,"context_lines":[{"line_number":465,"context_line":"                # Write down a sentinel header so that we know this part came"},{"line_number":466,"context_line":"                # into the MPU from a new proxy"},{"line_number":467,"context_line":"                req.headers[s3api_sysmeta_header("},{"line_number":468,"context_line":"                    \u0027object\u0027, \u0027checksum-upload-id\u0027)] \u003d upload_id"},{"line_number":469,"context_line":""},{"line_number":470,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"},{"line_number":471,"context_line":"        req.object_name \u003d \u0027%s/%s/%d\u0027 % (req.object_name, upload_id,"}],"source_content_type":"text/x-python","patch_set":22,"id":"30606850_31863ae2","line":468,"in_reply_to":"6302e600_dd85e56c","updated":"2026-09-18 04:20:56.000000000","message":"the sentinel was added primarily for mixed proxy versions, @natemartes09@gmail.com\u0027s example is a good one.","commit_id":"4a199298f77f6641819d9b7eeec001dc16d7db9f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"0d10dbb97bd8a0866d601a8f861746e8a398a57c","unresolved":true,"context_lines":[{"line_number":465,"context_line":"                # Write down a sentinel header so that we know this part came"},{"line_number":466,"context_line":"                # into the MPU from a new proxy"},{"line_number":467,"context_line":"                req.headers[s3api_sysmeta_header("},{"line_number":468,"context_line":"                    \u0027object\u0027, \u0027checksum-upload-id\u0027)] \u003d upload_id"},{"line_number":469,"context_line":""},{"line_number":470,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"},{"line_number":471,"context_line":"        req.object_name \u003d \u0027%s/%s/%d\u0027 % (req.object_name, upload_id,"}],"source_content_type":"text/x-python","patch_set":22,"id":"c915d3c6_1786d201","line":468,"in_reply_to":"a0e3fffd_8866ba31","updated":"2026-10-13 03:41:11.000000000","message":"with new feature flag ``allow_store_checksums`` added, this  sentinel is not needed anymore.","commit_id":"4a199298f77f6641819d9b7eeec001dc16d7db9f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"df97c7d08caccc6d8455ba55ea2cdc17176a84b5","unresolved":false,"context_lines":[{"line_number":465,"context_line":"                # Write down a sentinel header so that we know this part came"},{"line_number":466,"context_line":"                # into the MPU from a new proxy"},{"line_number":467,"context_line":"                req.headers[s3api_sysmeta_header("},{"line_number":468,"context_line":"                    \u0027object\u0027, \u0027checksum-upload-id\u0027)] \u003d upload_id"},{"line_number":469,"context_line":""},{"line_number":470,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"},{"line_number":471,"context_line":"        req.object_name \u003d \u0027%s/%s/%d\u0027 % (req.object_name, upload_id,"}],"source_content_type":"text/x-python","patch_set":22,"id":"02149e48_7a0babb0","line":468,"in_reply_to":"c915d3c6_1786d201","updated":"2026-10-15 05:10:19.000000000","message":"Done","commit_id":"4a199298f77f6641819d9b7eeec001dc16d7db9f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"f2a7e59c672b1aaaa8117c5ade9889569e5b5525","unresolved":true,"context_lines":[{"line_number":465,"context_line":"                # Write down a sentinel header so that we know this part came"},{"line_number":466,"context_line":"                # into the MPU from a new proxy"},{"line_number":467,"context_line":"                req.headers[s3api_sysmeta_header("},{"line_number":468,"context_line":"                    \u0027object\u0027, \u0027checksum-upload-id\u0027)] \u003d upload_id"},{"line_number":469,"context_line":""},{"line_number":470,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"},{"line_number":471,"context_line":"        req.object_name \u003d \u0027%s/%s/%d\u0027 % (req.object_name, upload_id,"}],"source_content_type":"text/x-python","patch_set":22,"id":"6302e600_dd85e56c","line":468,"in_reply_to":"fd1db2c6_f3eabb07","updated":"2026-09-17 23:00:32.000000000","message":"\u003e as this to guard against an UploadPartCopy making a ranged copy with incorrect checksum sysmeta, in which case the copied x-object-sysmeta-checksum-upload-id would not match the current upload-id?\n\nYes this was it.\nSince the copy hook is removing all sysmeta (at least all of the checksum sysmeta) then we won\u0027t need this because we can guarantee that any proxy that knows about AWS checksums, also knows not to copy checksum sysmeta ever.\n\nThough that is, what if we have a proxy that does not know about either checksums AND removing all sysmeta?\n\nLets say we have a proxy that knows about checksums (proxy A) and a proxy that does not know about checksums and removing sysmeta on copies (proxy B), then:\n\n1. A client upload a full object called \u0027foo\u0027 with a crc32 checksum on proxy A\n2. A client creates a MPU called \u0027bar\u0027 with a crc32 checksum on proxy A\n3. A client preforms a UploadPartCopy ranged on proxy B, using the MPU \u0027bar\u0027. The source object is \u0027foo\u0027\n4. A client completes the MPU on proxy A\n\nThis would mean that MPU part, which was the source object foo, will have inherited the sysmeta, that being the crc32 checksum from foo.\nWhen the MPU complete is started, and we did not have the x-object-sysmeta-checksum-upload-id, then it would be possible for an old proxy that inherits sysmeta (proxy B) to do a ranged copy into the MPU, leading the final checksum on the MPU to have a checksum that is incorrect.\n\n\nThat was a mouthful. So I think the tl;dr is:\n\nBecause we can have a proxy does not know to remove s3 sysmeta, and one that knows about checksum sysmeta in the same cluster, then it would be possible to have a completed MPU with a bad checksum because of a UploadPartCopy ranged request.","commit_id":"4a199298f77f6641819d9b7eeec001dc16d7db9f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"0d10dbb97bd8a0866d601a8f861746e8a398a57c","unresolved":true,"context_lines":[{"line_number":161,"context_line":"        \"\"\"Initialize a multipart upload checksum configuration.\"\"\""},{"line_number":162,"context_line":"        if checksum_header is not None:"},{"line_number":163,"context_line":"            checksum_header \u003d checksum_header.lower()"},{"line_number":164,"context_line":"        self.header \u003d checksum_header"},{"line_number":165,"context_line":"        self.value \u003d checksum_value"},{"line_number":166,"context_line":"        # S3 normalizes the types"},{"line_number":167,"context_line":"        if checksum_type is not None:"}],"source_content_type":"text/x-python","patch_set":25,"id":"6650e037_07e591d6","line":164,"updated":"2026-10-13 03:41:11.000000000","message":"this is going to be ``x-amz-checksum-crc32`` instead of actual algorithm.","commit_id":"f2876cf1951b35de042b95bc28a8c1fef29ee9b6"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"0d10dbb97bd8a0866d601a8f861746e8a398a57c","unresolved":false,"context_lines":[{"line_number":508,"context_line":"        if \u0027X-Amz-Copy-Source\u0027 in req.headers:"},{"line_number":509,"context_line":"            last_modified_ts \u003d S3Timestamp("},{"line_number":510,"context_line":"                parse_date_header(resp.headers[\u0027Last-Modified\u0027]))"},{"line_number":511,"context_line":"            # UploadPart responses do not echo the type"},{"line_number":512,"context_line":"            resp.append_copy_resp_body(\u0027CopyPartResult\u0027,"},{"line_number":513,"context_line":"                                       last_modified_ts.s3xmlformat)"},{"line_number":514,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"dbae6b77_48ddc61b","line":511,"updated":"2026-10-13 03:41:11.000000000","message":"this should be moved to above line 507","commit_id":"f2876cf1951b35de042b95bc28a8c1fef29ee9b6"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"df97c7d08caccc6d8455ba55ea2cdc17176a84b5","unresolved":false,"context_lines":[{"line_number":296,"context_line":"    _validate_checksum_type_with_checksum_header("},{"line_number":297,"context_line":"        checksum_attrs.type, checksum_attrs.header)"},{"line_number":298,"context_line":""},{"line_number":299,"context_line":"    _get_checksum_hasher(checksum_attrs)"},{"line_number":300,"context_line":""},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"def _validate_upload_part_checksum_headers("}],"source_content_type":"text/x-python","patch_set":27,"id":"af926f8f_2d8f7e77","line":299,"updated":"2026-10-15 05:10:19.000000000","message":"not needed anymore.","commit_id":"0d1f9cfc78766ff2db4213c2b3a339c12d6e8bde"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"df97c7d08caccc6d8455ba55ea2cdc17176a84b5","unresolved":false,"context_lines":[{"line_number":322,"context_line":"                    checksum_attrs.algorithm.lower(),"},{"line_number":323,"context_line":"                    request_checksum_attrs.algorithm.lower()))"},{"line_number":324,"context_line":"    elif checksum_attrs.is_full_object:"},{"line_number":325,"context_line":"        checksum_hasher \u003d _get_checksum_hasher(checksum_attrs)"},{"line_number":326,"context_line":"        # Since the request did not have a header, we have to add"},{"line_number":327,"context_line":"        # the wrapper ourselves"},{"line_number":328,"context_line":"        req.install_checksumming_input("}],"source_content_type":"text/x-python","patch_set":27,"id":"5a52398e_9605db2a","line":325,"updated":"2026-10-15 05:10:19.000000000","message":"since we now have anycrc and ``checksum_attrs.is_full_object`` checks valid header already, this line need to change to\n```\nchecksum_hasher \u003d get_checksum_hasher(checksum_attrs.header)\n```","commit_id":"0d1f9cfc78766ff2db4213c2b3a339c12d6e8bde"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"504f9a5e72f711371df68a06f85e86d9a6ca3a8f","unresolved":true,"context_lines":[{"line_number":281,"context_line":"def _validate_upload_part_checksum_headers("},{"line_number":282,"context_line":"        req, checksum_attrs):"},{"line_number":283,"context_line":"    \"\"\""},{"line_number":284,"context_line":"    Validate UploadPart checksum headers against the MPU configuration."},{"line_number":285,"context_line":""},{"line_number":286,"context_line":"    FULL_OBJECT MPUs may omit a part checksum, in which case this function"},{"line_number":287,"context_line":"    installs an input wrapper to calculate it. COMPOSITE MPUs require the"}],"source_content_type":"text/x-python","patch_set":29,"id":"01869cb1_dcb9bfbe","line":284,"updated":"2026-10-18 20:18:04.000000000","message":"the checks below all assumes that ``is_checksum_aware`` is true and this function is only called with that condition too, let\u0027s make it explicit.","commit_id":"8b10437d3df9be145d1c0210e25830bc188379ba"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"365b09e6853b8df89e638528518772deab70f643","unresolved":false,"context_lines":[{"line_number":281,"context_line":"def _validate_upload_part_checksum_headers("},{"line_number":282,"context_line":"        req, checksum_attrs):"},{"line_number":283,"context_line":"    \"\"\""},{"line_number":284,"context_line":"    Validate UploadPart checksum headers against the MPU configuration."},{"line_number":285,"context_line":""},{"line_number":286,"context_line":"    FULL_OBJECT MPUs may omit a part checksum, in which case this function"},{"line_number":287,"context_line":"    installs an input wrapper to calculate it. COMPOSITE MPUs require the"}],"source_content_type":"text/x-python","patch_set":29,"id":"0207ff01_283c74c7","line":284,"in_reply_to":"01869cb1_dcb9bfbe","updated":"2026-10-18 20:20:02.000000000","message":"Done","commit_id":"8b10437d3df9be145d1c0210e25830bc188379ba"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"504f9a5e72f711371df68a06f85e86d9a6ca3a8f","unresolved":true,"context_lines":[{"line_number":429,"context_line":"                # with the stored MPU checksum attributes"},{"line_number":430,"context_line":"                _validate_upload_part_checksum_headers("},{"line_number":431,"context_line":"                    req, mpu_checksum_attrs)"},{"line_number":432,"context_line":"            req.enable_checksum_persistence()"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"},{"line_number":435,"context_line":"        req.object_name \u003d \u0027%s/%s/%d\u0027 % (req.object_name, upload_id,"}],"source_content_type":"text/x-python","patch_set":29,"id":"d8427a8e_14a866ca","line":432,"updated":"2026-10-18 20:18:04.000000000","message":"this should be within the if branch ``if mpu_checksum_attrs.is_checksum_aware:``.\n\nLegacy UploadPart still validates supplied checksum headers and trailers, but does not store or return the checksum. when ``allowed_store_checksum`` is false, it should follow what legacy UploadPart does.","commit_id":"8b10437d3df9be145d1c0210e25830bc188379ba"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"365b09e6853b8df89e638528518772deab70f643","unresolved":false,"context_lines":[{"line_number":429,"context_line":"                # with the stored MPU checksum attributes"},{"line_number":430,"context_line":"                _validate_upload_part_checksum_headers("},{"line_number":431,"context_line":"                    req, mpu_checksum_attrs)"},{"line_number":432,"context_line":"            req.enable_checksum_persistence()"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"},{"line_number":435,"context_line":"        req.object_name \u003d \u0027%s/%s/%d\u0027 % (req.object_name, upload_id,"}],"source_content_type":"text/x-python","patch_set":29,"id":"bfd53787_150b50d5","line":432,"in_reply_to":"d8427a8e_14a866ca","updated":"2026-10-18 20:20:02.000000000","message":"Done","commit_id":"8b10437d3df9be145d1c0210e25830bc188379ba"}],"swift/common/middleware/s3api/s3api.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":387,"context_line":"            elif hdr_key in (\u0027x-amz-checksum-algorithm\u0027,"},{"line_number":388,"context_line":"                             \u0027x-amz-sdk-checksum-algorithm\u0027):"},{"line_number":389,"context_line":"                hdr_val_normalised \u003d normalize_checksum_algorithm("},{"line_number":390,"context_line":"                    hdr_val).replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":391,"context_line":"                if hdr_val_normalised in WELL_KNOWN_CHECKSUM_ALGORITHMS:"},{"line_number":392,"context_line":"                    label_val \u003d hdr_val_normalised"},{"line_number":393,"context_line":"                else:"}],"source_content_type":"text/x-python","patch_set":6,"id":"eeaa3738_e0649ffb","line":390,"range":{"start_line":390,"start_character":29,"end_line":390,"end_character":45},"updated":"2026-08-26 16:52:23.000000000","message":"let\u0027s do this in the normalize function, and put the commentary above in there too so we have it all in one place.\n\nalso, here\u0027s an opportunity for another small patch up front of chain we could merge \"s3api: introduce normalize_checksum_algorithm helper\", especially if it eliminates s3api.py diff hunks from these patches","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"be3596e58080e312b104b801368b340a2e862ea0","unresolved":false,"context_lines":[{"line_number":387,"context_line":"            elif hdr_key in (\u0027x-amz-checksum-algorithm\u0027,"},{"line_number":388,"context_line":"                             \u0027x-amz-sdk-checksum-algorithm\u0027):"},{"line_number":389,"context_line":"                hdr_val_normalised \u003d normalize_checksum_algorithm("},{"line_number":390,"context_line":"                    hdr_val).replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":391,"context_line":"                if hdr_val_normalised in WELL_KNOWN_CHECKSUM_ALGORITHMS:"},{"line_number":392,"context_line":"                    label_val \u003d hdr_val_normalised"},{"line_number":393,"context_line":"                else:"}],"source_content_type":"text/x-python","patch_set":6,"id":"1b04b6e6_5d54831b","line":390,"range":{"start_line":390,"start_character":29,"end_line":390,"end_character":45},"in_reply_to":"48492cda_79a3bbd8","updated":"2026-08-27 06:36:59.000000000","message":"See 1002583: s3api: add normalize_checksum_algorithm function | https://review.opendev.org/c/openstack/swift/+/1002583","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":387,"context_line":"            elif hdr_key in (\u0027x-amz-checksum-algorithm\u0027,"},{"line_number":388,"context_line":"                             \u0027x-amz-sdk-checksum-algorithm\u0027):"},{"line_number":389,"context_line":"                hdr_val_normalised \u003d normalize_checksum_algorithm("},{"line_number":390,"context_line":"                    hdr_val).replace(\u0027-\u0027, \u0027\u0027)"},{"line_number":391,"context_line":"                if hdr_val_normalised in WELL_KNOWN_CHECKSUM_ALGORITHMS:"},{"line_number":392,"context_line":"                    label_val \u003d hdr_val_normalised"},{"line_number":393,"context_line":"                else:"}],"source_content_type":"text/x-python","patch_set":6,"id":"48492cda_79a3bbd8","line":390,"range":{"start_line":390,"start_character":29,"end_line":390,"end_character":45},"in_reply_to":"eeaa3738_e0649ffb","updated":"2026-08-27 05:29:48.000000000","message":"So we cannot actually put `replace(\u0027-\u0027, \u0027\u0027)` inside of normalize because AWS does not accept checksum algorithm names with hypens in them, so if we normalize them out, we would be fixing what should actually be an error.\n\n```\naws s3api \\\ncreate-multipart-upload \\\n--bucket bar --key foo \\\n--checksum-algorithm sha-256\n\naws: [ERROR]: An error occurred (InvalidRequest)\nwhen calling the CreateMultipartUpload operation: Checksum algorithm \nprovided is unsupported. Please try again with \nany of the valid types: [CRC32, CRC32C, CRC64NVME, MD5, SHA1, SHA256, \nSHA512, XXHASH128, XXHASH3, XXHASH64]\n```\n\nBut I think to move this as a small intro patch is good!","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"}],"swift/common/middleware/s3api/s3checksum.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":85,"context_line":"def checksum_sysmeta_headers(checksum_algorithm, checksum_value,"},{"line_number":86,"context_line":"                             checksum_type):"},{"line_number":87,"context_line":"    \"\"\"Return object sysmeta for a calculated or validated checksum.\"\"\""},{"line_number":88,"context_line":"    return {"},{"line_number":89,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-algorithm\u0027):"},{"line_number":90,"context_line":"            normalize_checksum_algorithm(checksum_algorithm),"},{"line_number":91,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027): checksum_value,"}],"source_content_type":"text/x-python","patch_set":6,"id":"62ef3533_55c1c007","side":"PARENT","line":88,"updated":"2026-08-26 16:52:23.000000000","message":"```\nreturn HeaderKeyDict({...})\n```","commit_id":"4ea9f5841c407c0d9f32e82e51fd60def83c3860"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":85,"context_line":"def checksum_sysmeta_headers(checksum_algorithm, checksum_value,"},{"line_number":86,"context_line":"                             checksum_type):"},{"line_number":87,"context_line":"    \"\"\"Return object sysmeta for a calculated or validated checksum.\"\"\""},{"line_number":88,"context_line":"    return {"},{"line_number":89,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-algorithm\u0027):"},{"line_number":90,"context_line":"            normalize_checksum_algorithm(checksum_algorithm),"},{"line_number":91,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027): checksum_value,"}],"source_content_type":"text/x-python","patch_set":6,"id":"f7590ce2_0600bf39","side":"PARENT","line":88,"in_reply_to":"62ef3533_55c1c007","updated":"2026-08-27 05:29:48.000000000","message":"This is better","commit_id":"4ea9f5841c407c0d9f32e82e51fd60def83c3860"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2bd7377e84358203b53ac6c16ba3466f636da3de","unresolved":false,"context_lines":[{"line_number":85,"context_line":"def checksum_sysmeta_headers(checksum_algorithm, checksum_value,"},{"line_number":86,"context_line":"                             checksum_type):"},{"line_number":87,"context_line":"    \"\"\"Return object sysmeta for a calculated or validated checksum.\"\"\""},{"line_number":88,"context_line":"    return {"},{"line_number":89,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-algorithm\u0027):"},{"line_number":90,"context_line":"            normalize_checksum_algorithm(checksum_algorithm),"},{"line_number":91,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027): checksum_value,"}],"source_content_type":"text/x-python","patch_set":6,"id":"d02c2564_29dbc42c","side":"PARENT","line":88,"in_reply_to":"f7590ce2_0600bf39","updated":"2026-08-27 15:16:04.000000000","message":"Done","commit_id":"4ea9f5841c407c0d9f32e82e51fd60def83c3860"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":114,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-algorithm\u0027):"},{"line_number":115,"context_line":"            normalize_checksum_algorithm(checksum_algorithm),"},{"line_number":116,"context_line":"    }"},{"line_number":117,"context_line":"    if checksum_value is not None:"},{"line_number":118,"context_line":"        headers[s3api_sysmeta_header("},{"line_number":119,"context_line":"            \u0027object\u0027, \u0027checksum-value\u0027)] \u003d checksum_value"},{"line_number":120,"context_line":"    if checksum_type is not None:"}],"source_content_type":"text/x-python","patch_set":6,"id":"93761945_c634188c","line":117,"updated":"2026-08-26 16:52:23.000000000","message":"the conditional setters can be avoided by using a HeaderKeyDict which ignores None values. But, the tests assertions will need to change to expect title-cased header names.","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":114,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-algorithm\u0027):"},{"line_number":115,"context_line":"            normalize_checksum_algorithm(checksum_algorithm),"},{"line_number":116,"context_line":"    }"},{"line_number":117,"context_line":"    if checksum_value is not None:"},{"line_number":118,"context_line":"        headers[s3api_sysmeta_header("},{"line_number":119,"context_line":"            \u0027object\u0027, \u0027checksum-value\u0027)] \u003d checksum_value"},{"line_number":120,"context_line":"    if checksum_type is not None:"}],"source_content_type":"text/x-python","patch_set":6,"id":"a1499e95_3a2613c4","line":117,"in_reply_to":"93761945_c634188c","updated":"2026-08-27 05:29:48.000000000","message":"That can be done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"be3596e58080e312b104b801368b340a2e862ea0","unresolved":false,"context_lines":[{"line_number":114,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-algorithm\u0027):"},{"line_number":115,"context_line":"            normalize_checksum_algorithm(checksum_algorithm),"},{"line_number":116,"context_line":"    }"},{"line_number":117,"context_line":"    if checksum_value is not None:"},{"line_number":118,"context_line":"        headers[s3api_sysmeta_header("},{"line_number":119,"context_line":"            \u0027object\u0027, \u0027checksum-value\u0027)] \u003d checksum_value"},{"line_number":120,"context_line":"    if checksum_type is not None:"}],"source_content_type":"text/x-python","patch_set":6,"id":"14830900_74643f50","line":117,"in_reply_to":"a1499e95_3a2613c4","updated":"2026-08-27 06:36:59.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":141,"context_line":"        checksum_sysmeta_values(sysmeta_headers)"},{"line_number":142,"context_line":"    if (not checksum_algorithm or not checksum_value or"},{"line_number":143,"context_line":"            (require_type and not checksum_type)):"},{"line_number":144,"context_line":"        return {}"},{"line_number":145,"context_line":"    checksum_header \u003d checksum_header_from_algorithm(checksum_algorithm)"},{"line_number":146,"context_line":"    headers \u003d {checksum_header: checksum_value}"},{"line_number":147,"context_line":"    if checksum_type:"}],"source_content_type":"text/x-python","patch_set":6,"id":"51662c50_8924e3df","line":144,"updated":"2026-08-26 16:52:23.000000000","message":"I feel like it would be easier to just know that Swift always writes down all or none of the 3 sysmeta headers, and not have to remember that one may be missing if we\u0027re looking at an MPU part","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"be3596e58080e312b104b801368b340a2e862ea0","unresolved":false,"context_lines":[{"line_number":141,"context_line":"        checksum_sysmeta_values(sysmeta_headers)"},{"line_number":142,"context_line":"    if (not checksum_algorithm or not checksum_value or"},{"line_number":143,"context_line":"            (require_type and not checksum_type)):"},{"line_number":144,"context_line":"        return {}"},{"line_number":145,"context_line":"    checksum_header \u003d checksum_header_from_algorithm(checksum_algorithm)"},{"line_number":146,"context_line":"    headers \u003d {checksum_header: checksum_value}"},{"line_number":147,"context_line":"    if checksum_type:"}],"source_content_type":"text/x-python","patch_set":6,"id":"ef36dc47_cf63260d","line":144,"in_reply_to":"49ea0405_e685df51","updated":"2026-08-27 06:36:59.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":141,"context_line":"        checksum_sysmeta_values(sysmeta_headers)"},{"line_number":142,"context_line":"    if (not checksum_algorithm or not checksum_value or"},{"line_number":143,"context_line":"            (require_type and not checksum_type)):"},{"line_number":144,"context_line":"        return {}"},{"line_number":145,"context_line":"    checksum_header \u003d checksum_header_from_algorithm(checksum_algorithm)"},{"line_number":146,"context_line":"    headers \u003d {checksum_header: checksum_value}"},{"line_number":147,"context_line":"    if checksum_type:"}],"source_content_type":"text/x-python","patch_set":6,"id":"49ea0405_e685df51","line":144,"in_reply_to":"51662c50_8924e3df","updated":"2026-08-27 05:29:48.000000000","message":"I think so too...","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":149,"context_line":"    return headers"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"class ChecksummingInput(InputProxy):"},{"line_number":153,"context_line":"    \"\"\""},{"line_number":154,"context_line":"    wsgi.input wrapper to calculate the X-Amz-Checksum-* of the input as it\u0027s"},{"line_number":155,"context_line":"    read. The calculated value is checked against an expected value that is"}],"source_content_type":"text/x-python","patch_set":6,"id":"01ab5b68_34b803ad","line":152,"range":{"start_line":152,"start_character":6,"end_line":152,"end_character":23},"updated":"2026-08-26 16:52:23.000000000","message":"FWIW I\u0027m happy that this has not changed it\u0027s name, IIRC it did at one point and it felt unnecessary","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":false,"context_lines":[{"line_number":149,"context_line":"    return headers"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"class ChecksummingInput(InputProxy):"},{"line_number":153,"context_line":"    \"\"\""},{"line_number":154,"context_line":"    wsgi.input wrapper to calculate the X-Amz-Checksum-* of the input as it\u0027s"},{"line_number":155,"context_line":"    read. The calculated value is checked against an expected value that is"}],"source_content_type":"text/x-python","patch_set":6,"id":"e7d66603_1f0f3c03","line":152,"range":{"start_line":152,"start_character":6,"end_line":152,"end_character":23},"in_reply_to":"01ab5b68_34b803ad","updated":"2026-08-27 05:29:48.000000000","message":"Yea we had `CalculateChecksumMetadata` which we really did not need","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"08604d4f17e31c114862e6e33b4c1d7b26be3d41","unresolved":true,"context_lines":[{"line_number":141,"context_line":"    checksum_algorithm, checksum_value, checksum_type \u003d \\"},{"line_number":142,"context_line":"        checksum_sysmeta_values(sysmeta_headers)"},{"line_number":143,"context_line":"    if not checksum_algorithm:"},{"line_number":144,"context_line":"        return {}"},{"line_number":145,"context_line":"    headers \u003d {"},{"line_number":146,"context_line":"        checksum_header_from_algorithm(checksum_algorithm): checksum_value}"},{"line_number":147,"context_line":"    if include_type:"}],"source_content_type":"text/x-python","patch_set":16,"id":"c2239c28_79b4a09d","line":144,"updated":"2026-09-11 11:51:53.000000000","message":"I\u0027m not sure why the condition to return empty {} changed to be oly requiring the algorithm; see also tests removed in test_obj.py that covered the stronger condition in the previous patch","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"bfcd87c3aed1f5824961ffa607890a204dba1973","unresolved":true,"context_lines":[{"line_number":141,"context_line":"    checksum_algorithm, checksum_value, checksum_type \u003d \\"},{"line_number":142,"context_line":"        checksum_sysmeta_values(sysmeta_headers)"},{"line_number":143,"context_line":"    if not checksum_algorithm:"},{"line_number":144,"context_line":"        return {}"},{"line_number":145,"context_line":"    headers \u003d {"},{"line_number":146,"context_line":"        checksum_header_from_algorithm(checksum_algorithm): checksum_value}"},{"line_number":147,"context_line":"    if include_type:"}],"source_content_type":"text/x-python","patch_set":16,"id":"1991ab6e_34b75f62","line":144,"in_reply_to":"00922417_39e6882b","updated":"2026-09-14 08:46:06.000000000","message":"MPU initiate is the one exception when we only persist algo and type, and it sets response headers using bespoke code rather than this ``checksum_sysmeta_to_response_headers`` helper, which is a shame.\n\nThere was a patchset where upload part did not persist type (because upload part responses do not return x-amz-checksum-type) but we eliminated that anomaly, so regular objects, parts uploads and completed MPU manifests all persist all three metadata items.\n\nI might try a refactor to move the condition out of the helper so that all paths can use the helper.","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"02cf7d2fd7cd3135e33d3b43d5e581786f0dab6b","unresolved":true,"context_lines":[{"line_number":141,"context_line":"    checksum_algorithm, checksum_value, checksum_type \u003d \\"},{"line_number":142,"context_line":"        checksum_sysmeta_values(sysmeta_headers)"},{"line_number":143,"context_line":"    if not checksum_algorithm:"},{"line_number":144,"context_line":"        return {}"},{"line_number":145,"context_line":"    headers \u003d {"},{"line_number":146,"context_line":"        checksum_header_from_algorithm(checksum_algorithm): checksum_value}"},{"line_number":147,"context_line":"    if include_type:"}],"source_content_type":"text/x-python","patch_set":16,"id":"9f8c5e35_1df35271","line":144,"in_reply_to":"1991ab6e_34b75f62","updated":"2026-09-15 16:49:32.000000000","message":"\u003e so regular objects, parts uploads and completed MPU manifests all persist all three metadata items\n\nIf we are ok with `include_type` we could also probably add `include_value` which would operate the same just on `x-amz-checksum-\u003calgorithm\u003e`.\n\nAnd then we could move the check of verifying the values out and just check if the caller wants `x-amz-checksum-crc32` for instance, which would be True for everyone else but False for CreateMultiPartUpload.","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"53633203c24107e2dfe1fb6c1b14d97f393cb8e9","unresolved":true,"context_lines":[{"line_number":141,"context_line":"    checksum_algorithm, checksum_value, checksum_type \u003d \\"},{"line_number":142,"context_line":"        checksum_sysmeta_values(sysmeta_headers)"},{"line_number":143,"context_line":"    if not checksum_algorithm:"},{"line_number":144,"context_line":"        return {}"},{"line_number":145,"context_line":"    headers \u003d {"},{"line_number":146,"context_line":"        checksum_header_from_algorithm(checksum_algorithm): checksum_value}"},{"line_number":147,"context_line":"    if include_type:"}],"source_content_type":"text/x-python","patch_set":16,"id":"ce943689_ce69bec2","line":144,"in_reply_to":"1991ab6e_34b75f62","updated":"2026-09-16 15:02:51.000000000","message":"second thoughts.. the MPU initiate case returns different headers (algo and type vs value and type)","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac362ed9f197712bb82dacef5d20aedf77076eae","unresolved":true,"context_lines":[{"line_number":141,"context_line":"    checksum_algorithm, checksum_value, checksum_type \u003d \\"},{"line_number":142,"context_line":"        checksum_sysmeta_values(sysmeta_headers)"},{"line_number":143,"context_line":"    if not checksum_algorithm:"},{"line_number":144,"context_line":"        return {}"},{"line_number":145,"context_line":"    headers \u003d {"},{"line_number":146,"context_line":"        checksum_header_from_algorithm(checksum_algorithm): checksum_value}"},{"line_number":147,"context_line":"    if include_type:"}],"source_content_type":"text/x-python","patch_set":16,"id":"fad04ab7_979c6f90","line":144,"in_reply_to":"9f8c5e35_1df35271","updated":"2026-09-15 17:28:13.000000000","message":"Though then we would need to update the helper to return `x-amz-checksum-algorithm: checksum-algo` too, my first instance would be a include_algorithm, but 3 kwargs does not seem like something we want...\n\nPerhaps instead (since controllers use `checksum_sysmeta_to_response_headers`) we could have the callers pass in the `result_elem_name` optionally, kinda like\n\n```\n    def append_copy_resp_body(self, result_elem_name, last_modified):\n```\n\nBut instead:\n```\ndef checksum_sysmeta_to_response_headers(sysmeta_headers, request_elem_name\u003d\"\"):\n    checksum_algorithm, checksum_value, checksum_type \u003d \\\n        checksum_sysmeta_values(sysmeta_headers)\n    if request_elem_name \u003d\u003d \"UploadPart\"\n    \t# x-amz-checksum-crc32\n    if request_elem_name \u003d\u003d \"CreateMultiPartUpload\n        # x-amz-checksum-algortihm AND x-amz-checksum-type\n    else:\n    \t# x-amz-checksum-crc32 AND x-amz-checksum-type\n```\n\nThen we know what headers to include for CreateMultiPartUpload and for UploadPart, and we would know since the caller wants the response headers for this type of request, then they should exist in the sysmeta values.","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"76d81b0960cf77e8e979fdcd9fbd1753357d00bd","unresolved":true,"context_lines":[{"line_number":141,"context_line":"    checksum_algorithm, checksum_value, checksum_type \u003d \\"},{"line_number":142,"context_line":"        checksum_sysmeta_values(sysmeta_headers)"},{"line_number":143,"context_line":"    if not checksum_algorithm:"},{"line_number":144,"context_line":"        return {}"},{"line_number":145,"context_line":"    headers \u003d {"},{"line_number":146,"context_line":"        checksum_header_from_algorithm(checksum_algorithm): checksum_value}"},{"line_number":147,"context_line":"    if include_type:"}],"source_content_type":"text/x-python","patch_set":16,"id":"00922417_39e6882b","line":144,"in_reply_to":"c2239c28_79b4a09d","updated":"2026-09-11 16:16:23.000000000","message":"Hmm... right... I think *maybe* it was something to do with MPU initiate calls needing algo and type, but not having value.","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"3e465e67bb192fdeda7a7e7eed866358a748503c","unresolved":true,"context_lines":[{"line_number":146,"context_line":"        checksum_header_from_algorithm(checksum_algorithm): checksum_value}"},{"line_number":147,"context_line":"    if include_type:"},{"line_number":148,"context_line":"        headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":149,"context_line":"    return headers"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"class ChecksummingInput(InputProxy):"}],"source_content_type":"text/x-python","patch_set":16,"id":"60e34b6f_7d74f8e2","line":149,"updated":"2026-09-10 22:53:54.000000000","message":"This seems like a sizable refactor -- why are we doing it here, in the middle of the chain, rather than in https://review.opendev.org/c/openstack/swift/+/991516 where it was introduced?\n\nIs it intentional that it changes behavior? We lost the `if all([...])` check...","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"bfcd87c3aed1f5824961ffa607890a204dba1973","unresolved":true,"context_lines":[{"line_number":146,"context_line":"        checksum_header_from_algorithm(checksum_algorithm): checksum_value}"},{"line_number":147,"context_line":"    if include_type:"},{"line_number":148,"context_line":"        headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":149,"context_line":"    return headers"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"class ChecksummingInput(InputProxy):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7e8f4052_2c413bfd","line":149,"in_reply_to":"2cfdc337_865afc51","updated":"2026-09-14 08:46:06.000000000","message":"@Nate - hi!\nsee above - we don\u0027t write down checksum-value for an MPU initiate","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8cd48c9d8460b43b711a901220ad6283bfa0612","unresolved":true,"context_lines":[{"line_number":146,"context_line":"        checksum_header_from_algorithm(checksum_algorithm): checksum_value}"},{"line_number":147,"context_line":"    if include_type:"},{"line_number":148,"context_line":"        headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":149,"context_line":"    return headers"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"class ChecksummingInput(InputProxy):"}],"source_content_type":"text/x-python","patch_set":16,"id":"c7791b55_10b1e63f","line":149,"in_reply_to":"2d617426_b634cf17","updated":"2026-09-11 15:18:11.000000000","message":"\u003eThis seems like a sizable refactor -- why are we doing it here, in the middle of the chain, rather than in https://review.opendev.org/c/openstack/swift/+/991516 where it was introduced?\n\nmoved forwards in chain","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"08604d4f17e31c114862e6e33b4c1d7b26be3d41","unresolved":true,"context_lines":[{"line_number":146,"context_line":"        checksum_header_from_algorithm(checksum_algorithm): checksum_value}"},{"line_number":147,"context_line":"    if include_type:"},{"line_number":148,"context_line":"        headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":149,"context_line":"    return headers"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"class ChecksummingInput(InputProxy):"}],"source_content_type":"text/x-python","patch_set":16,"id":"2d617426_b634cf17","line":149,"in_reply_to":"60e34b6f_7d74f8e2","updated":"2026-09-11 11:51:53.000000000","message":"I\u0027m also not convinced the loss of the ``all`` condition is intentional or necessary, will fix","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"1bb313ebcb076a2470519f8379f9d5269a15e836","unresolved":true,"context_lines":[{"line_number":146,"context_line":"        checksum_header_from_algorithm(checksum_algorithm): checksum_value}"},{"line_number":147,"context_line":"    if include_type:"},{"line_number":148,"context_line":"        headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":149,"context_line":"    return headers"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"class ChecksummingInput(InputProxy):"}],"source_content_type":"text/x-python","patch_set":16,"id":"2cfdc337_865afc51","line":149,"in_reply_to":"c7791b55_10b1e63f","updated":"2026-09-12 00:13:24.000000000","message":"My main reason for switching away from the all catch is because we always write all 3 pieces of checksum system, so if the algorithm exist, so too will the other headers. It might be doing some preventative checking, but I am not opposed at all to go back to checking all of them","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"53633203c24107e2dfe1fb6c1b14d97f393cb8e9","unresolved":true,"context_lines":[{"line_number":137,"context_line":"    )"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"def checksum_sysmeta_to_response_headers(sysmeta_headers, include_type\u003dTrue):"},{"line_number":141,"context_line":"    \"\"\""},{"line_number":142,"context_line":"    Translate checksum sysmeta into S3 response headers."},{"line_number":143,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"91e945dd_d2f375e9","line":140,"range":{"start_line":140,"start_character":58,"end_line":140,"end_character":75},"updated":"2026-09-16 15:02:51.000000000","message":"this arg seems unnecessary, and complicates the helper, vs the single call site popping the unwanted header","commit_id":"20daacd764af590e0c561042c2802401309c7dd3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"70ab7c08ec3e5c926525417239b31bc45fcf1555","unresolved":true,"context_lines":[{"line_number":141,"context_line":"    \"\"\"Translate complete checksum sysmeta into S3 response headers.\"\"\""},{"line_number":142,"context_line":"    checksum_algorithm, checksum_value, checksum_type \u003d \\"},{"line_number":143,"context_line":"        checksum_sysmeta_values(sysmeta_headers)"},{"line_number":144,"context_line":"    if all([checksum_algorithm, checksum_value, checksum_type]):"},{"line_number":145,"context_line":"        checksum_header \u003d checksum_header_from_algorithm(checksum_algorithm)"},{"line_number":146,"context_line":"        return {checksum_header: checksum_value,"},{"line_number":147,"context_line":"                \u0027x-amz-checksum-type\u0027: checksum_type}"}],"source_content_type":"text/x-python","patch_set":21,"id":"dc699fa8_6eb70fd4","line":144,"range":{"start_line":144,"start_character":0,"end_line":144,"end_character":2},"updated":"2026-09-16 16:14:34.000000000","message":"Just for my own keepsake, everytime we write down check sysmeta, the value, the algorithm, and the type will be written down.\nSo we can update how CreateMultiPartUpload adds its checksum response headers by using this function, then just removing the value header (because we know that is not supposed to be returned)","commit_id":"3898c45a365c20aae40e3880aa2c1dcaba27691f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"df97c7d08caccc6d8455ba55ea2cdc17176a84b5","unresolved":false,"context_lines":[{"line_number":93,"context_line":"    \"\"\""},{"line_number":94,"context_line":"    try:"},{"line_number":95,"context_line":"        return CHECKSUMS_BY_HEADER[header.lower()]()"},{"line_number":96,"context_line":"    except (KeyError, NotImplementedError):"},{"line_number":97,"context_line":"        # We don\u0027t want to import s3response in this module"},{"line_number":98,"context_line":"        # so we cannot raise S3NotImplemented here."},{"line_number":99,"context_line":"        raise NotImplementedError("}],"source_content_type":"text/x-python","patch_set":27,"id":"ebbe06d8_60df27eb","line":96,"updated":"2026-10-15 05:10:19.000000000","message":"no more ``NotImplementedError``","commit_id":"0d1f9cfc78766ff2db4213c2b3a339c12d6e8bde"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"fd1c81adf678df8de526c266dff297b9b173a6fe","unresolved":false,"context_lines":[{"line_number":175,"context_line":"        \"\"\"Return the S3 checksum algorithm.\"\"\""},{"line_number":176,"context_line":"        return checksum_algorithm_from_header(self.checksum_key)"},{"line_number":177,"context_line":""},{"line_number":178,"context_line":"    def chunk_update(self, chunk, eof, *args, **kwargs):"},{"line_number":179,"context_line":"        \"\"\"Update and finish the checksum as input chunks are consumed.\"\"\""},{"line_number":180,"context_line":"        # Note that \"chunk\" is just whatever was read from the input; this"},{"line_number":181,"context_line":"        # says nothing about whether the underlying stream uses aws-chunked."}],"source_content_type":"text/x-python","patch_set":30,"id":"4511e973_0af069fd","line":178,"updated":"2026-10-21 04:34:59.000000000","message":"Claude spotted this edge case: on a FULL_OBJECT MPU, an UploadPart with chunked transfer and no checksum fails with a 500 instead of a 200.\n\nbelow are sequence of how this issue get triggered:\n```\nThe client sends PUT ?partNumber\u003d1\u0026uploadId\u003dX with Transfer-Encoding: chunked, no Content-Length and no x-amz-checksum-* header.\n-\u003e The MPU marker has FULL_OBJECT sysmeta, so the controller calls the validator. swift/common/middleware/s3api/controllers/multi_upload.py:431\n-\u003e The validator installs a wrapper for a request with no checksum. swift/common/middleware/s3api/controllers/multi_upload.py:308\n-\u003e The wrapper gets self.content_length, which is None. swift/common/middleware/s3api/s3request.py:1575\n-\u003e The first read compares an int to None and raises TypeError. swift/common/middleware/s3api/s3checksum.py:183\n-\u003e The proxy logs the exception and returns 500. swift/proxy/controllers/obj.py:1195\n```\n\nA cluster with allow_store_checksums \u003d true. A client creates an MPU with x-amz-checksum-type: FULL_OBJECT (or x-amz-checksum-algorithm: CRC64NVME), then sends an UploadPart with Transfer-Encoding: chunked and no checksum header. Before this patch, only a chunked PUT that carried a checksum header reached the wrapper, and a chunked UploadPart with no checksum got a 200. Now every such UploadPart to a FULL_OBJECT MPU gets a 500 InternalError and a logged traceback.\n\nThe standard boto3/botocore and AWS CLI upload path can use HTTP chunking without Content-Length for both operations. however, they also send aws-chunked framing, a checksum trailer, and x-amz-decoded-content-length. Those requests have a known decoded length and avoid this defect. confirmed this with default settings in AWS CLI 2.36.29’s bundled client.\n\nso this defect can only occur with \"Low-level boto3 put_object() or upload_part() with a custom stream of unknown size\" which is very uncommon.\n\nFixed by adding this check: https://review.opendev.org/c/openstack/swift/+/1002405/30..31/swift/common/middleware/s3api/s3checksum.py","commit_id":"5fff338d269c57446034924bbf3d05714ce7356e"}],"swift/common/middleware/s3api/s3request.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":1041,"context_line":""},{"line_number":1042,"context_line":"    @property"},{"line_number":1043,"context_line":"    def checksum_sysmeta_footers(self):"},{"line_number":1044,"context_line":"        \"\"\"Return sysmeta-shaped footers for the validated request checksum.\"\"\""},{"line_number":1045,"context_line":"        if self._checksum_sysmeta_footers is not None:"},{"line_number":1046,"context_line":"            return self._checksum_sysmeta_footers"},{"line_number":1047,"context_line":"        # Even if we don\u0027t have any persisted sysmeta,"}],"source_content_type":"text/x-python","patch_set":6,"id":"3edda939_6736626c","line":1044,"range":{"start_line":1044,"start_character":25,"end_line":1044,"end_character":32},"updated":"2026-08-26 16:52:23.000000000","message":"nit: (or maybe not!) I\u0027m guessing this is LLM generated but I have a real dislike for things being \"shaped\". The method return sysmeta footers, end-of.","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"be3596e58080e312b104b801368b340a2e862ea0","unresolved":false,"context_lines":[{"line_number":1041,"context_line":""},{"line_number":1042,"context_line":"    @property"},{"line_number":1043,"context_line":"    def checksum_sysmeta_footers(self):"},{"line_number":1044,"context_line":"        \"\"\"Return sysmeta-shaped footers for the validated request checksum.\"\"\""},{"line_number":1045,"context_line":"        if self._checksum_sysmeta_footers is not None:"},{"line_number":1046,"context_line":"            return self._checksum_sysmeta_footers"},{"line_number":1047,"context_line":"        # Even if we don\u0027t have any persisted sysmeta,"}],"source_content_type":"text/x-python","patch_set":6,"id":"975a768c_20c764d9","line":1044,"range":{"start_line":1044,"start_character":25,"end_line":1044,"end_character":32},"in_reply_to":"054d720c_b3a297fc","updated":"2026-08-27 06:36:59.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":1041,"context_line":""},{"line_number":1042,"context_line":"    @property"},{"line_number":1043,"context_line":"    def checksum_sysmeta_footers(self):"},{"line_number":1044,"context_line":"        \"\"\"Return sysmeta-shaped footers for the validated request checksum.\"\"\""},{"line_number":1045,"context_line":"        if self._checksum_sysmeta_footers is not None:"},{"line_number":1046,"context_line":"            return self._checksum_sysmeta_footers"},{"line_number":1047,"context_line":"        # Even if we don\u0027t have any persisted sysmeta,"}],"source_content_type":"text/x-python","patch_set":6,"id":"054d720c_b3a297fc","line":1044,"range":{"start_line":1044,"start_character":25,"end_line":1044,"end_character":32},"in_reply_to":"3edda939_6736626c","updated":"2026-08-27 05:29:48.000000000","message":"Yea I think this is more straightforward...\nbut because of the UploadPart requests reutning attributes from `checksumming_input` as sysmeta headers.. maybe \n\n\"\"\"Return sysmeta headers for the request checksum\"\"\"","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":1044,"context_line":"        \"\"\"Return sysmeta-shaped footers for the validated request checksum.\"\"\""},{"line_number":1045,"context_line":"        if self._checksum_sysmeta_footers is not None:"},{"line_number":1046,"context_line":"            return self._checksum_sysmeta_footers"},{"line_number":1047,"context_line":"        # Even if we don\u0027t have any persisted sysmeta,"},{"line_number":1048,"context_line":"        # If we checksummed the object, then we should return the checksum"},{"line_number":1049,"context_line":"        # meta. A case for this is UploadPart when a client did not"},{"line_number":1050,"context_line":"        # specify a checksum on their MPU."}],"source_content_type":"text/x-python","patch_set":6,"id":"403b637d_dc752592","line":1047,"updated":"2026-08-26 16:52:23.000000000","message":"why don\u0027t we just always persist the checksum if we calculated it. If the MPU does not require it then we can just ignore it on the part, right? Keeps it simple.\n\nI\u0027d like to explore this before fixing up the method as per the comments below.","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":1044,"context_line":"        \"\"\"Return sysmeta-shaped footers for the validated request checksum.\"\"\""},{"line_number":1045,"context_line":"        if self._checksum_sysmeta_footers is not None:"},{"line_number":1046,"context_line":"            return self._checksum_sysmeta_footers"},{"line_number":1047,"context_line":"        # Even if we don\u0027t have any persisted sysmeta,"},{"line_number":1048,"context_line":"        # If we checksummed the object, then we should return the checksum"},{"line_number":1049,"context_line":"        # meta. A case for this is UploadPart when a client did not"},{"line_number":1050,"context_line":"        # specify a checksum on their MPU."}],"source_content_type":"text/x-python","patch_set":6,"id":"64836379_c60c14b1","line":1047,"in_reply_to":"403b637d_dc752592","updated":"2026-08-27 05:29:48.000000000","message":"\u003e Keeps it simple\n\nI think this approach could work","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"be3596e58080e312b104b801368b340a2e862ea0","unresolved":false,"context_lines":[{"line_number":1044,"context_line":"        \"\"\"Return sysmeta-shaped footers for the validated request checksum.\"\"\""},{"line_number":1045,"context_line":"        if self._checksum_sysmeta_footers is not None:"},{"line_number":1046,"context_line":"            return self._checksum_sysmeta_footers"},{"line_number":1047,"context_line":"        # Even if we don\u0027t have any persisted sysmeta,"},{"line_number":1048,"context_line":"        # If we checksummed the object, then we should return the checksum"},{"line_number":1049,"context_line":"        # meta. A case for this is UploadPart when a client did not"},{"line_number":1050,"context_line":"        # specify a checksum on their MPU."}],"source_content_type":"text/x-python","patch_set":6,"id":"ecaae3f2_6d3c1fa2","line":1047,"in_reply_to":"64836379_c60c14b1","updated":"2026-08-27 06:36:59.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":1047,"context_line":"        # Even if we don\u0027t have any persisted sysmeta,"},{"line_number":1048,"context_line":"        # If we checksummed the object, then we should return the checksum"},{"line_number":1049,"context_line":"        # meta. A case for this is UploadPart when a client did not"},{"line_number":1050,"context_line":"        # specify a checksum on their MPU."},{"line_number":1051,"context_line":"        if (self._checksumming_input is None or"},{"line_number":1052,"context_line":"                not self._checksumming_input.matching_checksum):"},{"line_number":1053,"context_line":"            return None"}],"source_content_type":"text/x-python","patch_set":6,"id":"54ec3d33_9a750fb7","line":1050,"updated":"2026-08-26 16:52:23.000000000","message":"I need help understanding this scenario: the client did NOT send a checksum value, Swift did calculate the checksum but Swift did not persist it? why was it calculated, was it purely to return a value in the response?\n\nAre we sure we need to do this, because...\n\"x-amz-checksum-crc32\nThe Base64 encoded, 32-bit CRC32 checksum of the part. This will only be present if the checksum was provided in the request. \" https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html\n\nis there a compat test that covers this?\n\nOh, maybe I get it: the upload part did have a checksum but the CreateMultipartUpload did not.\n\nIf we do need this code then can we invert the if so there are less negatives and beef up the comment:\n\n```\ndiff --git a/swift/common/middleware/s3api/s3checksum.py b/swift/common/middleware/s3api/s3checksum.py\nindex 106393e3f..cebba969c 100644\n--- a/swift/common/middleware/s3api/s3checksum.py\n+++ b/swift/common/middleware/s3api/s3checksum.py\n@@ -15,6 +15,7 @@\n \n from hashlib import sha1, sha256\n \n+from swift.common.header_key_dict import HeaderKeyDict\n from swift.common.middleware.s3api.exception import \\\n     S3InputChecksumMismatch, S3InputChecksumTrailerInvalid\n from swift.common.middleware.s3api.utils import s3api_sysmeta_header\ndiff --git a/swift/common/middleware/s3api/s3request.py b/swift/common/middleware/s3api/s3request.py\nindex 50fa224f0..5449dd96b 100644\n--- a/swift/common/middleware/s3api/s3request.py\n+++ b/swift/common/middleware/s3api/s3request.py\n@@ -1044,16 +1044,19 @@ class S3Request(swob.Request):\n         \"\"\"Return sysmeta-shaped footers for the validated request checksum.\"\"\"\n         if self._checksum_sysmeta_footers is not None:\n             return self._checksum_sysmeta_footers\n-        # Even if we don\u0027t have any persisted sysmeta,\n-        # If we checksummed the object, then we should return the checksum\n-        # meta. A case for this is UploadPart when a client did not\n-        # specify a checksum on their MPU.\n-        if (self._checksumming_input is None or\n-                not self._checksumming_input.matching_checksum):\n+        # Even if we don\u0027t have any *persisted* checksum sysmeta, we may have a\n+        # checksum value for the object which we should return in response\n+        # headers. For example, when a CreateMultipartUpload does not specify a\n+        # checksum algorithm but an UploadPart does, then we do not persist the\n+        # part checksum but we should return the checksum value in the\n+        # UploadPart response.\n+        if (self._checksumming_input and\n+                self._checksumming_input.matching_checksum):\n+            return checksum_sysmeta_headers(\n+                self._checksumming_input.algorithm,\n+                self._checksumming_input.matching_checksum)\n+        else:\n             return None\n-        return checksum_sysmeta_headers(\n-            self._checksumming_input.algorithm,\n-            self._checksumming_input.matching_checksum)\n \n     def __init__(self, env, app\u003dNone, conf\u003dNone):\n         # NOTE: app is not used by this class, need for compatibility of S3acl\n\n```","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":1047,"context_line":"        # Even if we don\u0027t have any persisted sysmeta,"},{"line_number":1048,"context_line":"        # If we checksummed the object, then we should return the checksum"},{"line_number":1049,"context_line":"        # meta. A case for this is UploadPart when a client did not"},{"line_number":1050,"context_line":"        # specify a checksum on their MPU."},{"line_number":1051,"context_line":"        if (self._checksumming_input is None or"},{"line_number":1052,"context_line":"                not self._checksumming_input.matching_checksum):"},{"line_number":1053,"context_line":"            return None"}],"source_content_type":"text/x-python","patch_set":6,"id":"ff456178_2a36862a","line":1050,"in_reply_to":"54ec3d33_9a750fb7","updated":"2026-08-27 05:29:48.000000000","message":"Yep this is the right approach!\nHere\u0027s some more context:\n\nWhen it comes to default checksums in the feature, AWS not only echos the checksum the client can send, but it always writes down the CRC64NVME for the part, so in that case it would write down 1 checksum (CRC64NVME) and return the client provided one (SHA1 for instance).\n\nI think this hunk is better too","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"08604d4f17e31c114862e6e33b4c1d7b26be3d41","unresolved":false,"context_lines":[{"line_number":1047,"context_line":"        # Even if we don\u0027t have any persisted sysmeta,"},{"line_number":1048,"context_line":"        # If we checksummed the object, then we should return the checksum"},{"line_number":1049,"context_line":"        # meta. A case for this is UploadPart when a client did not"},{"line_number":1050,"context_line":"        # specify a checksum on their MPU."},{"line_number":1051,"context_line":"        if (self._checksumming_input is None or"},{"line_number":1052,"context_line":"                not self._checksumming_input.matching_checksum):"},{"line_number":1053,"context_line":"            return None"}],"source_content_type":"text/x-python","patch_set":6,"id":"f75f0e78_574ee8f6","line":1050,"in_reply_to":"ff456178_2a36862a","updated":"2026-09-11 11:51:53.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":1053,"context_line":"            return None"},{"line_number":1054,"context_line":"        return checksum_sysmeta_headers("},{"line_number":1055,"context_line":"            self._checksumming_input.algorithm,"},{"line_number":1056,"context_line":"            self._checksumming_input.matching_checksum)"},{"line_number":1057,"context_line":""},{"line_number":1058,"context_line":"    def __init__(self, env, app\u003dNone, conf\u003dNone):"},{"line_number":1059,"context_line":"        # NOTE: app is not used by this class, need for compatibility of S3acl"}],"source_content_type":"text/x-python","patch_set":6,"id":"7b299025_a7041d4b","line":1056,"updated":"2026-08-26 16:52:23.000000000","message":"ok but this method is no longer returning ``checksum_sysmeta_footers``","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":1053,"context_line":"            return None"},{"line_number":1054,"context_line":"        return checksum_sysmeta_headers("},{"line_number":1055,"context_line":"            self._checksumming_input.algorithm,"},{"line_number":1056,"context_line":"            self._checksumming_input.matching_checksum)"},{"line_number":1057,"context_line":""},{"line_number":1058,"context_line":"    def __init__(self, env, app\u003dNone, conf\u003dNone):"},{"line_number":1059,"context_line":"        # NOTE: app is not used by this class, need for compatibility of S3acl"}],"source_content_type":"text/x-python","patch_set":6,"id":"ce532d14_272f8c76","line":1056,"in_reply_to":"7b299025_a7041d4b","updated":"2026-08-27 05:29:48.000000000","message":"Maybe we keep `self.checksum_sysmeta_footers` as is and\nmake `self.checksum_sysmeta` which can return the footers if we have them and if not, pull the checksum metadata from `checksumming_input` to handle \n\nI am not totally sold on it but my agents don\u0027t seem to have any other better options\n\nMaybe something better I will try is making a property for checksumming input instead...","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"64b4deac01530137d6a3984d8cf6720a185427eb","unresolved":false,"context_lines":[{"line_number":1053,"context_line":"            return None"},{"line_number":1054,"context_line":"        return checksum_sysmeta_headers("},{"line_number":1055,"context_line":"            self._checksumming_input.algorithm,"},{"line_number":1056,"context_line":"            self._checksumming_input.matching_checksum)"},{"line_number":1057,"context_line":""},{"line_number":1058,"context_line":"    def __init__(self, env, app\u003dNone, conf\u003dNone):"},{"line_number":1059,"context_line":"        # NOTE: app is not used by this class, need for compatibility of S3acl"}],"source_content_type":"text/x-python","patch_set":6,"id":"59fac61b_57525f7e","line":1056,"in_reply_to":"ce532d14_272f8c76","updated":"2026-09-19 13:33:14.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2529f712f5bd134ad4902bcd8fe2830037f0f9b2","unresolved":true,"context_lines":[{"line_number":1588,"context_line":"    def install_checksumming_input("},{"line_number":1589,"context_line":"            self, checksum_hasher, checksum_key, checksum_source):"},{"line_number":1590,"context_line":"        \"\"\""},{"line_number":1591,"context_line":"        Install an input wrapper that validates or calculates a checksum."},{"line_number":1592,"context_line":""},{"line_number":1593,"context_line":"        A checksum source enables validation against a client value. Passing"},{"line_number":1594,"context_line":"        None retains the calculated checksum for controller-owned behavior."}],"source_content_type":"text/x-python","patch_set":6,"id":"f2644cac_d4b3e49e","line":1591,"range":{"start_line":1591,"start_character":38,"end_line":1591,"end_character":61},"updated":"2026-08-26 16:52:23.000000000","message":"``calculates and optionally validates``","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"be3596e58080e312b104b801368b340a2e862ea0","unresolved":false,"context_lines":[{"line_number":1588,"context_line":"    def install_checksumming_input("},{"line_number":1589,"context_line":"            self, checksum_hasher, checksum_key, checksum_source):"},{"line_number":1590,"context_line":"        \"\"\""},{"line_number":1591,"context_line":"        Install an input wrapper that validates or calculates a checksum."},{"line_number":1592,"context_line":""},{"line_number":1593,"context_line":"        A checksum source enables validation against a client value. Passing"},{"line_number":1594,"context_line":"        None retains the calculated checksum for controller-owned behavior."}],"source_content_type":"text/x-python","patch_set":6,"id":"6404c052_0b27a6ee","line":1591,"range":{"start_line":1591,"start_character":38,"end_line":1591,"end_character":61},"in_reply_to":"99783cca_3079c4d9","updated":"2026-08-27 06:36:59.000000000","message":"Done","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"33ccd9b9646af2bd54a5ffcd9d579938f1154590","unresolved":true,"context_lines":[{"line_number":1588,"context_line":"    def install_checksumming_input("},{"line_number":1589,"context_line":"            self, checksum_hasher, checksum_key, checksum_source):"},{"line_number":1590,"context_line":"        \"\"\""},{"line_number":1591,"context_line":"        Install an input wrapper that validates or calculates a checksum."},{"line_number":1592,"context_line":""},{"line_number":1593,"context_line":"        A checksum source enables validation against a client value. Passing"},{"line_number":1594,"context_line":"        None retains the calculated checksum for controller-owned behavior."}],"source_content_type":"text/x-python","patch_set":6,"id":"99783cca_3079c4d9","line":1591,"range":{"start_line":1591,"start_character":38,"end_line":1591,"end_character":61},"in_reply_to":"f2644cac_d4b3e49e","updated":"2026-08-27 05:29:48.000000000","message":"This sounds better","commit_id":"660ad03fc6d576cff3d65d29a08a33ff9bc7ba7b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"08604d4f17e31c114862e6e33b4c1d7b26be3d41","unresolved":true,"context_lines":[{"line_number":1045,"context_line":"    @property"},{"line_number":1046,"context_line":"    def checksumming_input(self):"},{"line_number":1047,"context_line":"        \"\"\"Return the wrapper checksumming the request body, if any.\"\"\""},{"line_number":1048,"context_line":"        return self._checksumming_input"},{"line_number":1049,"context_line":""},{"line_number":1050,"context_line":"    def __init__(self, env, app\u003dNone, conf\u003dNone):"},{"line_number":1051,"context_line":"        # NOTE: app is not used by this class, need for compatibility of S3acl"}],"source_content_type":"text/x-python","patch_set":16,"id":"ee47adde_f8f19b5e","line":1048,"updated":"2026-09-11 11:51:53.000000000","message":"move this after the __init__, or even drop the property","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"64b4deac01530137d6a3984d8cf6720a185427eb","unresolved":false,"context_lines":[{"line_number":1045,"context_line":"    @property"},{"line_number":1046,"context_line":"    def checksumming_input(self):"},{"line_number":1047,"context_line":"        \"\"\"Return the wrapper checksumming the request body, if any.\"\"\""},{"line_number":1048,"context_line":"        return self._checksumming_input"},{"line_number":1049,"context_line":""},{"line_number":1050,"context_line":"    def __init__(self, env, app\u003dNone, conf\u003dNone):"},{"line_number":1051,"context_line":"        # NOTE: app is not used by this class, need for compatibility of S3acl"}],"source_content_type":"text/x-python","patch_set":16,"id":"0a3a957b_56d88efc","line":1048,"in_reply_to":"ee47adde_f8f19b5e","updated":"2026-09-19 13:33:14.000000000","message":"Done","commit_id":"bf756c5c9bac3ac5fc05245cd722a1580b62274b"}],"test/__init__.py":[{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"70ab7c08ec3e5c926525417239b31bc45fcf1555","unresolved":false,"context_lines":[{"line_number":129,"context_line":"            self.fail(\u0027Invalid NormalTimestamp (%r): %r\u0027 % (timestamp, e))"},{"line_number":130,"context_line":""},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"def requires_crc32_combine(func):"},{"line_number":133,"context_line":"    @functools.wraps(func)"},{"line_number":134,"context_line":"    def wrapper(*args, **kwargs):"},{"line_number":135,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":21,"id":"56faf67c_4a58ed32","line":132,"range":{"start_line":132,"start_character":0,"end_line":132,"end_character":2},"updated":"2026-09-16 16:14:34.000000000","message":"Yea this is a better place for them","commit_id":"3898c45a365c20aae40e3880aa2c1dcaba27691f"}],"test/s3api/test_object_checksums.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c55409b259eb52576dd83f50a9c43ca20478e24f","unresolved":true,"context_lines":[{"line_number":44,"context_line":"    def wrapper(*args, **kwargs):"},{"line_number":45,"context_line":"        if crc32().crc_combine_func is None:"},{"line_number":46,"context_line":"            raise SkipTest("},{"line_number":47,"context_line":"                \u0027Swift cannot calculate full-object MPU checksums \u0027"},{"line_number":48,"context_line":"                \u0027without crc_combine (install anycrc)\u0027)"},{"line_number":49,"context_line":"        return func(*args, **kwargs)"},{"line_number":50,"context_line":"    return wrapper"}],"source_content_type":"text/x-python","patch_set":18,"id":"43ee3d7d_50a4b031","line":47,"range":{"start_line":47,"start_character":17,"end_line":47,"end_character":39},"updated":"2026-09-16 16:00:30.000000000","message":"note: this was a little misleading because it is the *test suite* that requires crc combine, independently of the cluster being tested having it available","commit_id":"20daacd764af590e0c561042c2802401309c7dd3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"70ab7c08ec3e5c926525417239b31bc45fcf1555","unresolved":false,"context_lines":[{"line_number":44,"context_line":"    def wrapper(*args, **kwargs):"},{"line_number":45,"context_line":"        if crc32().crc_combine_func is None:"},{"line_number":46,"context_line":"            raise SkipTest("},{"line_number":47,"context_line":"                \u0027Swift cannot calculate full-object MPU checksums \u0027"},{"line_number":48,"context_line":"                \u0027without crc_combine (install anycrc)\u0027)"},{"line_number":49,"context_line":"        return func(*args, **kwargs)"},{"line_number":50,"context_line":"    return wrapper"}],"source_content_type":"text/x-python","patch_set":18,"id":"700e355d_d627fa02","line":47,"range":{"start_line":47,"start_character":17,"end_line":47,"end_character":39},"in_reply_to":"43ee3d7d_50a4b031","updated":"2026-09-16 16:14:34.000000000","message":"Acknowledged","commit_id":"20daacd764af590e0c561042c2802401309c7dd3"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"70ab7c08ec3e5c926525417239b31bc45fcf1555","unresolved":false,"context_lines":[{"line_number":1396,"context_line":"        obj_name \u003d self.create_name("},{"line_number":1397,"context_line":"            \u0027mpu-full-object-upload-part-checksum-optional\u0027)"},{"line_number":1398,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027FULL_OBJECT\u0027)"},{"line_number":1399,"context_line":"        with self.disable_client_checksum_calculation():"},{"line_number":1400,"context_line":"            body \u003d MPU_PART_BODIES[0]"},{"line_number":1401,"context_line":"            part_resp \u003d self.client.upload_part("},{"line_number":1402,"context_line":"                Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":21,"id":"ab127cf5_da6b93cb","line":1399,"range":{"start_line":1399,"start_character":0,"end_line":1399,"end_character":2},"updated":"2026-09-16 16:14:34.000000000","message":"Seems good","commit_id":"3898c45a365c20aae40e3880aa2c1dcaba27691f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"a0d8c422e645edec4c13d8dfd99221eab87e61a8","unresolved":true,"context_lines":[{"line_number":1352,"context_line":"                \u0027The COMPOSITE checksum type cannot be used with the \u0027"},{"line_number":1353,"context_line":"                \u0027crc64nvme checksum algorithm.\u0027))"},{"line_number":1354,"context_line":""},{"line_number":1355,"context_line":"    def test_upload_part_rejects_checksum_algorithm_mismatch(self):"},{"line_number":1356,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-upload-checksum-algorithm-mismatch\u0027)"},{"line_number":1357,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":1358,"context_line":""}],"source_content_type":"text/x-python","patch_set":22,"id":"18cc1d57_b5634d7c","line":1355,"updated":"2026-09-17 22:17:05.000000000","message":"need to add algorithm mismatch with FULL_OBJECT for this cross-compat test.","commit_id":"4a199298f77f6641819d9b7eeec001dc16d7db9f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"f326e1706dcb9ce0454dc3f63ed0767f5b0aa3e4","unresolved":false,"context_lines":[{"line_number":1352,"context_line":"                \u0027The COMPOSITE checksum type cannot be used with the \u0027"},{"line_number":1353,"context_line":"                \u0027crc64nvme checksum algorithm.\u0027))"},{"line_number":1354,"context_line":""},{"line_number":1355,"context_line":"    def test_upload_part_rejects_checksum_algorithm_mismatch(self):"},{"line_number":1356,"context_line":"        obj_name \u003d self.create_name(\u0027mpu-upload-checksum-algorithm-mismatch\u0027)"},{"line_number":1357,"context_line":"        upload_id \u003d self.create_mpu(obj_name, \u0027CRC32\u0027, \u0027COMPOSITE\u0027)"},{"line_number":1358,"context_line":""}],"source_content_type":"text/x-python","patch_set":22,"id":"aa2ab106_1b1878c7","line":1355,"in_reply_to":"18cc1d57_b5634d7c","updated":"2026-09-18 04:20:56.000000000","message":"Done","commit_id":"4a199298f77f6641819d9b7eeec001dc16d7db9f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":637,"context_line":"        }"},{"line_number":638,"context_line":"        with self.assertRaises(botocore.exceptions.ClientError) as caught:"},{"line_number":639,"context_line":"            self.client.put_object(**put_kwargs)"},{"line_number":640,"context_line":"        self.assert_error("},{"line_number":641,"context_line":"            resp\u003dcaught.exception.response,"},{"line_number":642,"context_line":"            err_code\u003d\u0027InvalidRequest\u0027,"},{"line_number":643,"context_line":"            err_msg\u003d\u0027Value for x-amz-checksum-crc32 header is invalid.\u0027,"}],"source_content_type":"text/x-python","patch_set":26,"id":"c7d84c00_a2db4547","line":640,"updated":"2026-10-14 23:38:20.000000000","message":"good refactoring, ``assert_error`` is much better than ``assert_invalid``. would it also be nice to combine this test with all 4 below? they all share the same setup and assertions.\n```\ntest_invalid_base64_too_short\ntest_invalid_base64_too_long\ntest_invalid_base64_all_invalid_chars\ntest_invalid_base64_includes_invalid_chars\n```","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":703,"context_line":"            err_msg\u003d\u0027Value for x-amz-checksum-crc32 header is invalid.\u0027,"},{"line_number":704,"context_line":"            obj_name\u003dput_kwargs[\u0027Key\u0027])"},{"line_number":705,"context_line":""},{"line_number":706,"context_line":"    def test_mpu_no_checksum_upload_part_invalid_checksum(self):"},{"line_number":707,"context_line":"        obj_name \u003d self.create_name(\u0027no-checksum-mpu\u0027)"},{"line_number":708,"context_line":"        create_mpu_resp \u003d self.client.create_multipart_upload("},{"line_number":709,"context_line":"            Bucket\u003dself.bucket_name, Key\u003dobj_name)"}],"source_content_type":"text/x-python","patch_set":26,"id":"e889d825_87806ada","line":706,"updated":"2026-10-14 23:38:20.000000000","message":"this existing test case is covered by the new added test ``test_mpu_upload_part_invalid_checksum`` which does more check and clean up mpu after test done, let\u0027s remove this one.","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":1048,"context_line":"                    self.assertIn(checksum_algorithm, supported_algorithms)"},{"line_number":1049,"context_line":""},{"line_number":1050,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":1051,"context_line":"    def test_create_rejects_unknown_checksum_type(self):"},{"line_number":1052,"context_line":"        with self.assertRaises(botocore.exceptions.ClientError) as caught:"},{"line_number":1053,"context_line":"            self.client.create_multipart_upload("},{"line_number":1054,"context_line":"                Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":26,"id":"dc4d49c1_9205dc1c","line":1051,"updated":"2026-10-14 23:38:20.000000000","message":"```\ntest_create_rejects_unknown_checksum_type\ntest_create_rejects_unknown_checksum_type_without_algorithm\ntest_create_rejects_empty_checksum_type\n```\nthose three tests can be merged into one using ``subTest``.","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"}],"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":"2bd7377e84358203b53ac6c16ba3466f636da3de","unresolved":true,"context_lines":[{"line_number":1410,"context_line":"                         put_call.footers)"},{"line_number":1411,"context_line":"        self.assertNotIn(s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027),"},{"line_number":1412,"context_line":"                         put_call.footers)"},{"line_number":1413,"context_line":"        put_headers \u003d self.swift.calls_with_headers[-1][2]"},{"line_number":1414,"context_line":"        self.assertNotIn("},{"line_number":1415,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027), put_headers)"},{"line_number":1416,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"9ca934db_b0eb1941","line":1413,"updated":"2026-08-27 15:16:04.000000000","message":"this is same as ``put_call.headers``, no need to get ``self.swift.calls_with_headers[-1][2]``","commit_id":"4b7238704985137bbff1b212f8872c094ab950ed"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"b61e9fb0f50f45febde6f178293d76ed19cf3857","unresolved":false,"context_lines":[{"line_number":1410,"context_line":"                         put_call.footers)"},{"line_number":1411,"context_line":"        self.assertNotIn(s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027),"},{"line_number":1412,"context_line":"                         put_call.footers)"},{"line_number":1413,"context_line":"        put_headers \u003d self.swift.calls_with_headers[-1][2]"},{"line_number":1414,"context_line":"        self.assertNotIn("},{"line_number":1415,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027), put_headers)"},{"line_number":1416,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"4921a790_40057b3c","line":1413,"in_reply_to":"9ca934db_b0eb1941","updated":"2026-08-27 22:06:56.000000000","message":"Acknowledged","commit_id":"4b7238704985137bbff1b212f8872c094ab950ed"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2bd7377e84358203b53ac6c16ba3466f636da3de","unresolved":true,"context_lines":[{"line_number":1467,"context_line":"                         put_call.footers)"},{"line_number":1468,"context_line":"        self.assertNotIn(s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027),"},{"line_number":1469,"context_line":"                         put_call.footers)"},{"line_number":1470,"context_line":"        put_headers \u003d self.swift.calls_with_headers[-1][2]"},{"line_number":1471,"context_line":"        self.assertNotIn("},{"line_number":1472,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027), put_headers)"},{"line_number":1473,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"d3b7d233_e294ac59","line":1470,"updated":"2026-08-27 15:16:04.000000000","message":"this is same as ``put_call.headers``, no need to get ``self.swift.calls_with_headers[-1][2]``","commit_id":"4b7238704985137bbff1b212f8872c094ab950ed"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"b61e9fb0f50f45febde6f178293d76ed19cf3857","unresolved":false,"context_lines":[{"line_number":1467,"context_line":"                         put_call.footers)"},{"line_number":1468,"context_line":"        self.assertNotIn(s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027),"},{"line_number":1469,"context_line":"                         put_call.footers)"},{"line_number":1470,"context_line":"        put_headers \u003d self.swift.calls_with_headers[-1][2]"},{"line_number":1471,"context_line":"        self.assertNotIn("},{"line_number":1472,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027), put_headers)"},{"line_number":1473,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"3e4d8cda_180d29d6","line":1470,"in_reply_to":"d3b7d233_e294ac59","updated":"2026-08-27 22:06:56.000000000","message":"Acknowledged","commit_id":"4b7238704985137bbff1b212f8872c094ab950ed"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2bd7377e84358203b53ac6c16ba3466f636da3de","unresolved":true,"context_lines":[{"line_number":1523,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027)])"},{"line_number":1524,"context_line":"        self.assertEqual(\u0027FULL_OBJECT\u0027, put_call.footers["},{"line_number":1525,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027)])"},{"line_number":1526,"context_line":"        put_headers \u003d self.swift.calls_with_headers[-1][2]"},{"line_number":1527,"context_line":"        self.assertEqual(\u0027X\u0027, put_headers.get("},{"line_number":1528,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027)))"},{"line_number":1529,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"894e2330_2944d832","line":1526,"updated":"2026-08-27 15:16:04.000000000","message":"this is same as ``put_call.headers``, no need to get ``self.swift.calls_with_headers[-1][2]``","commit_id":"4b7238704985137bbff1b212f8872c094ab950ed"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"b61e9fb0f50f45febde6f178293d76ed19cf3857","unresolved":false,"context_lines":[{"line_number":1523,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027)])"},{"line_number":1524,"context_line":"        self.assertEqual(\u0027FULL_OBJECT\u0027, put_call.footers["},{"line_number":1525,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027)])"},{"line_number":1526,"context_line":"        put_headers \u003d self.swift.calls_with_headers[-1][2]"},{"line_number":1527,"context_line":"        self.assertEqual(\u0027X\u0027, put_headers.get("},{"line_number":1528,"context_line":"            s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-upload-id\u0027)))"},{"line_number":1529,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"d8498a35_66746c8b","line":1526,"in_reply_to":"894e2330_2944d832","updated":"2026-08-27 22:06:56.000000000","message":"Acknowledged","commit_id":"4b7238704985137bbff1b212f8872c094ab950ed"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        self.assertFalse(attrs.is_full_object)"},{"line_number":116,"context_line":"        self.assertFalse(attrs.is_composite)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"    def test_full_object_properties(self):"},{"line_number":119,"context_line":"        attrs \u003d MPUChecksumAttrs("},{"line_number":120,"context_line":"            \u0027X-Amz-Checksum-Crc32\u0027, checksum_type\u003d\u0027full_object\u0027)"},{"line_number":121,"context_line":""}],"source_content_type":"text/x-python","patch_set":26,"id":"83d2f36d_379eade1","line":118,"updated":"2026-10-14 23:38:20.000000000","message":"can share one test case with ``test_composite_properties``","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":162,"context_line":"        self.assertEqual(\u0027FULL_OBJECT\u0027, attrs.type)"},{"line_number":163,"context_line":"        self.assertTrue(attrs.is_mpu_in_progress)"},{"line_number":164,"context_line":""},{"line_number":165,"context_line":"    def test_from_complete_request_with_checksum_value(self):"},{"line_number":166,"context_line":"        req \u003d Request.blank("},{"line_number":167,"context_line":"            \u0027/bucket/object?uploadId\u003dX\u0027, method\u003d\u0027POST\u0027, headers\u003d{"},{"line_number":168,"context_line":"                \u0027X-Amz-Checksum-Crc32\u0027: \u0027AAAAAA\u003d\u003d\u0027,"}],"source_content_type":"text/x-python","patch_set":26,"id":"67b84d98_774d9bca","line":165,"updated":"2026-10-14 23:38:20.000000000","message":"can share one test case with ``test_from_upload_part_request_with_checksum_header`` and ``test_from_upload_part_request_with_checksum_trailer``","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":176,"context_line":"        self.assertEqual(\u0027COMPOSITE\u0027, attrs.type)"},{"line_number":177,"context_line":"        self.assertTrue(attrs.is_mpu_in_progress)"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":"    def test_from_complete_request_ignores_algorithm_header(self):"},{"line_number":180,"context_line":"        req \u003d Request.blank("},{"line_number":181,"context_line":"            \u0027/bucket/object?uploadId\u003dX\u0027, method\u003d\u0027POST\u0027,"},{"line_number":182,"context_line":"            headers\u003d{\u0027X-Amz-Checksum-Algorithm\u0027: \u0027CRC32\u0027})"}],"source_content_type":"text/x-python","patch_set":26,"id":"0576466c_ab7448a1","line":179,"updated":"2026-10-14 23:38:20.000000000","message":"this one can share one test with ``test_from_upload_part_request_ignores_algorithm_header``","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":1275,"context_line":""},{"line_number":1276,"context_line":"class TestS3ApiMultiUpload(BaseS3ApiMultiUpload, S3ApiTestCase):"},{"line_number":1277,"context_line":""},{"line_number":1278,"context_line":"    def test_checksum_hasher_unavailable(self):"},{"line_number":1279,"context_line":"        fake_memcache \u003d FakeMemcache()"},{"line_number":1280,"context_line":"        fake_memcache.store[get_cache_key("},{"line_number":1281,"context_line":"            \u0027AUTH_test\u0027, \u0027bucket\u0027)] \u003d {\u0027status\u0027: 204}"}],"source_content_type":"text/x-python","patch_set":26,"id":"64d57d98_9fddede1","line":1278,"updated":"2026-10-14 23:38:20.000000000","message":"can merged into one test with ``test_composite_checksum_hasher_unavailable``","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":1556,"context_line":"        self.assertNotIn(\u0027x-object-sysmeta-s3api-checksum-type\u0027,"},{"line_number":1557,"context_line":"                         put_call.footers)"},{"line_number":1558,"context_line":""},{"line_number":1559,"context_line":"    def test_object_upload_part_composite_checksum_value(self):"},{"line_number":1560,"context_line":"        self._register_checksum_upload_marker()"},{"line_number":1561,"context_line":"        body \u003d b\u0027part object\u0027"},{"line_number":1562,"context_line":"        part_checksum \u003d base64.b64encode("}],"source_content_type":"text/x-python","patch_set":26,"id":"c0b51384_fc23d349","line":1559,"updated":"2026-10-14 23:38:20.000000000","message":"this shares the same setup as next one ``test_object_upload_part_composite_sdk_checksum_algorithm``","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":1791,"context_line":"        self.assertNotIn(\u0027swift.callback.update_footers\u0027, put_call.env)"},{"line_number":1792,"context_line":"        self.assertFalse(put_call.footers)"},{"line_number":1793,"context_line":""},{"line_number":1794,"context_line":"    def test_object_upload_part_composite_checksum_wrong_algorithm(self):"},{"line_number":1795,"context_line":"        self._register_checksum_upload_marker()"},{"line_number":1796,"context_line":"        body \u003d b\u0027part object\u0027"},{"line_number":1797,"context_line":"        part_checksum \u003d base64.b64encode("}],"source_content_type":"text/x-python","patch_set":26,"id":"8e66e95e_0ea40def","line":1794,"updated":"2026-10-14 23:38:20.000000000","message":"share same setup as next one ``test_object_upload_part_full_object_checksum_wrong_algorithm``","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":2069,"context_line":"        self._test_object_multipart_upload_initiate("},{"line_number":2070,"context_line":"            {\u0027X-Amz-Checksum-Algorithm\u0027: \u0027CRC32\u0027,"},{"line_number":2071,"context_line":"             \u0027X-Amz-Checksum-Type\u0027: \u0027COMPOSITE\u0027}, fake_memcache,"},{"line_number":2072,"context_line":"            expected_checksum_algorithm\u003d\u0027CRC32\u0027,"},{"line_number":2073,"context_line":"            expected_checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":2074,"context_line":""},{"line_number":2075,"context_line":"    def test_initiate_checksum_persistence_disabled_without_crc_combine(self):"}],"source_content_type":"text/x-python","patch_set":26,"id":"7b8bfa09_0dd0abda","line":2072,"updated":"2026-10-14 23:38:20.000000000","message":"this is confusing, let\u0027s remove them.","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":2072,"context_line":"            expected_checksum_algorithm\u003d\u0027CRC32\u0027,"},{"line_number":2073,"context_line":"            expected_checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":2074,"context_line":""},{"line_number":2075,"context_line":"    def test_initiate_checksum_persistence_disabled_without_crc_combine(self):"},{"line_number":2076,"context_line":"        self.s3api.conf.allow_store_checksums \u003d False"},{"line_number":2077,"context_line":"        fake_memcache \u003d FakeMemcache()"},{"line_number":2078,"context_line":"        fake_memcache.store[get_cache_key("}],"source_content_type":"text/x-python","patch_set":26,"id":"a97c9dc0_857aec14","line":2075,"updated":"2026-10-14 23:38:20.000000000","message":"not needed since anycrc is hard requirement on master now.","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":2104,"context_line":"            expected_checksum_algorithm\u003d\u0027CRC32\u0027,"},{"line_number":2105,"context_line":"            expected_checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":2106,"context_line":""},{"line_number":2107,"context_line":"    def test_object_multipart_upload_initiate_crc32_full_object_checksum_type("},{"line_number":2108,"context_line":"            self):"},{"line_number":2109,"context_line":"        fake_memcache \u003d FakeMemcache()"},{"line_number":2110,"context_line":"        fake_memcache.store[get_cache_key("}],"source_content_type":"text/x-python","patch_set":26,"id":"7306a232_1847744f","line":2107,"updated":"2026-10-14 23:38:20.000000000","message":"combine with ``test_object_multipart_upload_initiate_normalizes_crc32_full_object``","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":2118,"context_line":"                expected_checksum_algorithm\u003d\u0027CRC32\u0027,"},{"line_number":2119,"context_line":"                expected_checksum_type\u003d\u0027FULL_OBJECT\u0027)"},{"line_number":2120,"context_line":""},{"line_number":2121,"context_line":"    def test_object_multipart_upload_initiate_sha1_composite_checksum_type("},{"line_number":2122,"context_line":"            self):"},{"line_number":2123,"context_line":"        fake_memcache \u003d FakeMemcache()"},{"line_number":2124,"context_line":"        fake_memcache.store[get_cache_key("}],"source_content_type":"text/x-python","patch_set":26,"id":"6710c0ca_b1d88282","line":2121,"updated":"2026-10-14 23:38:20.000000000","message":"combine with test_object_multipart_upload_initiate_normalizes_sha1_composite","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":2158,"context_line":"            expected_checksum_algorithm\u003d\u0027SHA1\u0027,"},{"line_number":2159,"context_line":"            expected_checksum_type\u003d\u0027COMPOSITE\u0027)"},{"line_number":2160,"context_line":""},{"line_number":2161,"context_line":"    def test_object_multipart_upload_initiate_crc32_default_checksum_type("},{"line_number":2162,"context_line":"            self):"},{"line_number":2163,"context_line":"        fake_memcache \u003d FakeMemcache()"},{"line_number":2164,"context_line":"        fake_memcache.store[get_cache_key("}],"source_content_type":"text/x-python","patch_set":26,"id":"3e111a5c_38294486","line":2161,"updated":"2026-10-14 23:38:20.000000000","message":"should combine with test_object_multipart_upload_initiate_crc32c_default_checksum_type, test_object_multipart_upload_initiate_sha1_default_checksum_type and test_object_multipart_upload_initiate_sha256_default_checksum_type","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":2242,"context_line":"            \u0027x-amz-checksum-algorithm header.\u0027)"},{"line_number":2243,"context_line":"        self.assertEqual([], self.swift.calls)"},{"line_number":2244,"context_line":""},{"line_number":2245,"context_line":"    def test_object_multipart_upload_initiate_rejects_unsupported_algorithm("},{"line_number":2246,"context_line":"            self):"},{"line_number":2247,"context_line":"        fake_memcache \u003d FakeMemcache()"},{"line_number":2248,"context_line":"        fake_memcache.store[get_cache_key("}],"source_content_type":"text/x-python","patch_set":26,"id":"97779f5e_891ad75b","line":2245,"updated":"2026-10-14 23:38:20.000000000","message":"can combine with test_object_multipart_upload_initiate_rejects_hyphenated_algorithm","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":2296,"context_line":"                    self._get_error_message(body))"},{"line_number":2297,"context_line":"                self.assertEqual([], self.swift.calls)"},{"line_number":2298,"context_line":""},{"line_number":2299,"context_line":"    def test_object_multipart_upload_initiate_rejects_unknown_checksum_type("},{"line_number":2300,"context_line":"            self):"},{"line_number":2301,"context_line":"        fake_memcache \u003d FakeMemcache()"},{"line_number":2302,"context_line":"        fake_memcache.store[get_cache_key("}],"source_content_type":"text/x-python","patch_set":26,"id":"2f18d1a5_67ae9e7a","line":2299,"updated":"2026-10-14 23:38:20.000000000","message":"can combine with test_object_multipart_upload_initiate_unknown_checksum_type_no_algo, test_object_multipart_upload_initiate_rejects_invalid_checksum_type, test_object_multipart_upload_initiate_empty_checksum_type and","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":2387,"context_line":"            self._get_error_message(body))"},{"line_number":2388,"context_line":"        self.assertEqual([], self.swift.calls)"},{"line_number":2389,"context_line":""},{"line_number":2390,"context_line":"    def test_object_multipart_upload_initiate_full_object_needs_crc_combine("},{"line_number":2391,"context_line":"            self):"},{"line_number":2392,"context_line":"        fake_memcache \u003d FakeMemcache()"},{"line_number":2393,"context_line":"        fake_memcache.store[get_cache_key("}],"source_content_type":"text/x-python","patch_set":26,"id":"889a8fad_534fa8d6","line":2390,"updated":"2026-10-14 23:38:20.000000000","message":"to be deleted after anycrc becomes hard requirement.","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":2412,"context_line":"            \u0027calculate them.\u0027, self._get_error_message(body))"},{"line_number":2413,"context_line":"        self.assertEqual([], self.swift.calls)"},{"line_number":2414,"context_line":""},{"line_number":2415,"context_line":"    def test_object_multipart_upload_initiate_full_object_rejects_sha1(self):"},{"line_number":2416,"context_line":"        fake_memcache \u003d FakeMemcache()"},{"line_number":2417,"context_line":"        fake_memcache.store[get_cache_key("},{"line_number":2418,"context_line":"            \u0027AUTH_test\u0027, \u0027bucket\u0027)] \u003d {\u0027status\u0027: 204}"}],"source_content_type":"text/x-python","patch_set":26,"id":"be812ca7_d0328088","line":2415,"updated":"2026-10-14 23:38:20.000000000","message":"can combine with test_object_multipart_upload_initiate_full_object_rejects_sha256 and test_object_multipart_upload_initiate_composite_rejects_crc64nvme","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"}],"test/unit/common/middleware/s3api/test_obj.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"3e465e67bb192fdeda7a7e7eed866358a748503c","unresolved":true,"context_lines":[{"line_number":524,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"},{"line_number":525,"context_line":"        self.assertEqual(self.object_body, body)"},{"line_number":526,"context_line":""},{"line_number":527,"context_line":"    def test_object_GET_checksum_mode_requires_checksum_algorithm(self):"},{"line_number":528,"context_line":"        swift_headers \u003d dict(self.response_headers)"},{"line_number":529,"context_line":"        swift_headers.update({"},{"line_number":530,"context_line":"            # No algorithm, means we should not return the checksum"}],"source_content_type":"text/x-python","patch_set":16,"id":"6a42fd77_d8e10e1f","side":"PARENT","line":527,"updated":"2026-09-10 22:53:54.000000000","message":"Why are we dropping these tests? Seems unrelated to this change. FWIW, happened between PS 6 and 7.","commit_id":"82de2ba34e17ef3c276f8fe5b372101887e46845"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"08604d4f17e31c114862e6e33b4c1d7b26be3d41","unresolved":true,"context_lines":[{"line_number":599,"context_line":"        self.assertEqual(status.split()[0], \u0027200\u0027)"},{"line_number":600,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, headers)"},{"line_number":601,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"},{"line_number":602,"context_line":"        self.assertEqual(self.object_body, body)"},{"line_number":603,"context_line":""},{"line_number":604,"context_line":"    def test_object_HEAD_checksum_mode_enabled_without_checksum_sysmeta(self):"},{"line_number":605,"context_line":"        self.swift.register("}],"source_content_type":"text/x-python","patch_set":16,"id":"ce0edcb0_b0eef254","side":"PARENT","line":602,"updated":"2026-09-11 11:51:53.000000000","message":"I\u0027m not sure why these tests were removed. What changed with MPU support that means it\u0027s ok to have only partial checksum sysmeta?","commit_id":"82de2ba34e17ef3c276f8fe5b372101887e46845"}],"test/unit/common/middleware/s3api/test_s3request.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"27e2377ba14eb59ad82e26bacac42b89c69f3ca6","unresolved":false,"context_lines":[{"line_number":1589,"context_line":"            sigv4_req.environ.get(\u0027swift.callback.update_footers\u0027))"},{"line_number":1590,"context_line":"        self.assertFalse(sigv4_req.checksum_sysmeta_footers)"},{"line_number":1591,"context_line":""},{"line_number":1592,"context_line":"    def test_installs_checksumming_input(self):"},{"line_number":1593,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1594,"context_line":"        crc \u003d base64.b64encode(checksum.crc32(body).digest())"},{"line_number":1595,"context_line":"        sigv4_req \u003d self._test_sig_v4_unsigned_payload("}],"source_content_type":"text/x-python","patch_set":26,"id":"086f285b_eb23ac70","line":1592,"updated":"2026-10-14 23:38:20.000000000","message":"can be merged into ``test_crc32_ok``","commit_id":"afc4fe120cfc7fe888c09a13193ce5c27a5cb6e7"}]}
