)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"061631f210daab007691365994c38d8221b1f4de","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"d9976149_28145a4d","updated":"2026-08-14 15:04:32.000000000","message":"LGTM except for the module name clash, I\u0027d prefer a different name for clarity","commit_id":"c35f73a79a48646b3b1b9126f44fc201a2281173"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"63c3aa56f8da8a698c86a8d562789864a44b10d4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"3a297df1_a041ee18","updated":"2026-08-11 18:12:09.000000000","message":"This patch is mainly just to save our butts in the feature from\nthe despair of circular imports and we do have a lot of checksum code to add, good to put it all in one place","commit_id":"c35f73a79a48646b3b1b9126f44fc201a2281173"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"e2ca6dba2499b8e04313b4e11f9964553c661da8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"ce760d79_804b8ac3","updated":"2026-08-18 15:21:41.000000000","message":"Please see my inline comment","commit_id":"d183b92560e1771cb88f16bb9414e43e89813913"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9aba46ebea6db3c252b882a1d0df8bdf2c2dc78e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"fc50f5ac_0097d0cc","updated":"2026-08-19 14:42:31.000000000","message":"I\u0027m not convinced (yet) by the change to ChecksummingInput, and regardless it shouldn\u0027t be a drive-by fix in what is otherwise a refactor.","commit_id":"dbf87c6022b4fbe020f61b271bf2e91841c2e550"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"09f4e0cedb327f198aa0cec77535bc64e45681bf","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"25aee278_c60fc1a9","updated":"2026-08-19 16:20:37.000000000","message":"Reverted this to patchset 3, which was good before, will defer behavior changes to 999457: s3api: Recompute Checksums for CopyObject and UploadPartCopy | https://review.opendev.org/c/openstack/swift/+/999457","commit_id":"67ae15cd881767429046eb62e6b29f3149975c96"}],"swift/common/middleware/s3api/checksum.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"061631f210daab007691365994c38d8221b1f4de","unresolved":true,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from swift.common.middleware.s3api.exception import \\"},{"line_number":19,"context_line":"    S3InputChecksumMismatch, S3InputChecksumTrailerInvalid"},{"line_number":20,"context_line":"from swift.common.utils import checksum, InputProxy, strict_b64decode"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"CHECKSUMS_BY_HEADER \u003d {"}],"source_content_type":"text/x-python","patch_set":1,"id":"b429c62b_a8bb0ce8","line":20,"range":{"start_line":20,"start_character":31,"end_line":20,"end_character":39},"updated":"2026-08-14 15:04:32.000000000","message":"we already have a ``checksum.py``, could we name this new module ``s3checksum.py``","commit_id":"c35f73a79a48646b3b1b9126f44fc201a2281173"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"15bd9b99cab3ef5e74901b9831890df3574d109e","unresolved":false,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from swift.common.middleware.s3api.exception import \\"},{"line_number":19,"context_line":"    S3InputChecksumMismatch, S3InputChecksumTrailerInvalid"},{"line_number":20,"context_line":"from swift.common.utils import checksum, InputProxy, strict_b64decode"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"CHECKSUMS_BY_HEADER \u003d {"}],"source_content_type":"text/x-python","patch_set":1,"id":"16054324_c83f7a41","line":20,"range":{"start_line":20,"start_character":31,"end_line":20,"end_character":39},"in_reply_to":"a36941aa_a4ea487d","updated":"2026-08-19 23:43:00.000000000","message":"Done","commit_id":"c35f73a79a48646b3b1b9126f44fc201a2281173"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"099116c670c17ecdad0bc7e8de860ef470af29d5","unresolved":true,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from swift.common.middleware.s3api.exception import \\"},{"line_number":19,"context_line":"    S3InputChecksumMismatch, S3InputChecksumTrailerInvalid"},{"line_number":20,"context_line":"from swift.common.utils import checksum, InputProxy, strict_b64decode"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"CHECKSUMS_BY_HEADER \u003d {"}],"source_content_type":"text/x-python","patch_set":1,"id":"a36941aa_a4ea487d","line":20,"range":{"start_line":20,"start_character":31,"end_line":20,"end_character":39},"in_reply_to":"b429c62b_a8bb0ce8","updated":"2026-08-14 23:59:10.000000000","message":"Yea I think this a good idea","commit_id":"c35f73a79a48646b3b1b9126f44fc201a2281173"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"061631f210daab007691365994c38d8221b1f4de","unresolved":true,"context_lines":[{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"def get_checksum_hasher(header):"},{"line_number":33,"context_line":"    \"\"\"Return a checksum hasher for an x-amz-checksum-* header.\"\"\""},{"line_number":34,"context_line":"    try:"},{"line_number":35,"context_line":"        return CHECKSUMS_BY_HEADER[header]()"},{"line_number":36,"context_line":"    except (KeyError, NotImplementedError):"}],"source_content_type":"text/x-python","patch_set":1,"id":"00442a57_12da0c13","line":33,"updated":"2026-08-14 15:04:32.000000000","message":"nit: add a ``:raises:`` file in docstring","commit_id":"c35f73a79a48646b3b1b9126f44fc201a2281173"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"099116c670c17ecdad0bc7e8de860ef470af29d5","unresolved":false,"context_lines":[{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"def get_checksum_hasher(header):"},{"line_number":33,"context_line":"    \"\"\"Return a checksum hasher for an x-amz-checksum-* header.\"\"\""},{"line_number":34,"context_line":"    try:"},{"line_number":35,"context_line":"        return CHECKSUMS_BY_HEADER[header]()"},{"line_number":36,"context_line":"    except (KeyError, NotImplementedError):"}],"source_content_type":"text/x-python","patch_set":1,"id":"f9b51e25_57ebfe2d","line":33,"in_reply_to":"00442a57_12da0c13","updated":"2026-08-14 23:59:10.000000000","message":"Done","commit_id":"c35f73a79a48646b3b1b9126f44fc201a2281173"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"061631f210daab007691365994c38d8221b1f4de","unresolved":true,"context_lines":[{"line_number":47,"context_line":"    )"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"class ChecksummingInput(InputProxy):"},{"line_number":51,"context_line":"    \"\"\""},{"line_number":52,"context_line":"    Calculate and validate the X-Amz-Checksum-* of an input as it is read."},{"line_number":53,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"9d0be74a_2db4b903","line":50,"updated":"2026-08-14 15:04:32.000000000","message":"I think moving this out of s3request is probably justified because later we\u0027ll want to use it for an object copy hook, correct? Plus, it\u0027s to do with checksums","commit_id":"c35f73a79a48646b3b1b9126f44fc201a2281173"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"099116c670c17ecdad0bc7e8de860ef470af29d5","unresolved":true,"context_lines":[{"line_number":47,"context_line":"    )"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"class ChecksummingInput(InputProxy):"},{"line_number":51,"context_line":"    \"\"\""},{"line_number":52,"context_line":"    Calculate and validate the X-Amz-Checksum-* of an input as it is read."},{"line_number":53,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"739ebcd6_2700ab54","line":50,"in_reply_to":"9d0be74a_2db4b903","updated":"2026-08-14 23:59:10.000000000","message":"Yes in the future, we will end up wrapping this class over a generic Swift `Request` class to handle the copying. It wouldn\u0027t feel right to like expose `ChecksummingInput` from `S3Request` and use it on a request that is NOT a `S3Request`... so I think this is the best approach","commit_id":"c35f73a79a48646b3b1b9126f44fc201a2281173"}],"swift/common/middleware/s3api/s3checksum.py":[{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"e2ca6dba2499b8e04313b4e11f9964553c661da8","unresolved":true,"context_lines":[{"line_number":82,"context_line":"        if self.bytes_received \u003c self._expected_length:"},{"line_number":83,"context_line":"            # Wrapped input is likely to have timed out before this clause is"},{"line_number":84,"context_line":"            # reached with eof\u003dTrue, but just in case."},{"line_number":85,"context_line":"            error \u003d eof"},{"line_number":86,"context_line":"        elif self.bytes_received \u003d\u003d self._expected_length:"},{"line_number":87,"context_line":"            # Lazy fetch checksum value because it may have come in trailers."},{"line_number":88,"context_line":"            b64digest \u003d self._checksum_source.get(self._checksum_key)"}],"source_content_type":"text/x-python","patch_set":3,"id":"7307d502_0aaf4610","line":85,"updated":"2026-08-18 15:21:41.000000000","message":"This needs to be: `error \u003d eof and not chunk`\n\nA copy can fail with 400 BadDigest even though the client sent no checksum. ChecksummingInput stops at the first short read, but the copy source returns one chunk per read, so the checksum only covers part of the body. \n\nNoticed the issue later in the patch series when testing on a SAIO; the bug can\u0027t be reproduced on a SAIO here (only later - on 999457), but it makes sense to fix it here.\n\nShorter reproducer, fails without the fix - might be a good candidate for another test:\n\n```\nfrom swift.common.utils import FileLikeIter\nfrom swift.common.middleware.s3api.s3checksum import ChecksummingInput, get_checksum_hasher\nH \u003d \u0027x-amz-checksum-crc32\u0027\nsrc \u003d FileLikeIter(iter([b\u0027a\u0027 * 100, b\u0027b\u0027 * 100]))\ninp \u003d ChecksummingInput(src, 200, get_checksum_hasher(H), H, None)\nwhile inp.read(150):\n    pass\n  \n```","commit_id":"d183b92560e1771cb88f16bb9414e43e89813913"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"71db19afd9d0494929e71ae9611fee80dcad1220","unresolved":true,"context_lines":[{"line_number":82,"context_line":"        if self.bytes_received \u003c self._expected_length:"},{"line_number":83,"context_line":"            # Wrapped input is likely to have timed out before this clause is"},{"line_number":84,"context_line":"            # reached with eof\u003dTrue, but just in case."},{"line_number":85,"context_line":"            error \u003d eof"},{"line_number":86,"context_line":"        elif self.bytes_received \u003d\u003d self._expected_length:"},{"line_number":87,"context_line":"            # Lazy fetch checksum value because it may have come in trailers."},{"line_number":88,"context_line":"            b64digest \u003d self._checksum_source.get(self._checksum_key)"}],"source_content_type":"text/x-python","patch_set":3,"id":"f75063e9_184c0bd9","line":85,"in_reply_to":"7307d502_0aaf4610","updated":"2026-08-18 18:53:15.000000000","message":"Yes I think this is needed earlier, I can write up a unit test to address this along with the fix, thanks!\n\nI think it will be useful to write a test case in 999457 to showcase this aswell","commit_id":"d183b92560e1771cb88f16bb9414e43e89813913"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"15bd9b99cab3ef5e74901b9831890df3574d109e","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        if self.bytes_received \u003c self._expected_length:"},{"line_number":83,"context_line":"            # Wrapped input is likely to have timed out before this clause is"},{"line_number":84,"context_line":"            # reached with eof\u003dTrue, but just in case."},{"line_number":85,"context_line":"            error \u003d eof"},{"line_number":86,"context_line":"        elif self.bytes_received \u003d\u003d self._expected_length:"},{"line_number":87,"context_line":"            # Lazy fetch checksum value because it may have come in trailers."},{"line_number":88,"context_line":"            b64digest \u003d self._checksum_source.get(self._checksum_key)"}],"source_content_type":"text/x-python","patch_set":3,"id":"4668e3b4_c8d72c90","line":85,"in_reply_to":"f75063e9_184c0bd9","updated":"2026-08-19 23:43:00.000000000","message":"Done https://review.opendev.org/c/openstack/swift/+/999457/26/swift/common/middleware/s3api/s3checksum.py#197","commit_id":"d183b92560e1771cb88f16bb9414e43e89813913"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9aba46ebea6db3c252b882a1d0df8bdf2c2dc78e","unresolved":true,"context_lines":[{"line_number":82,"context_line":"        if self.bytes_received \u003c self._expected_length:"},{"line_number":83,"context_line":"            # A non-empty short read may be one chunk from an iterable-backed"},{"line_number":84,"context_line":"            # input rather than the end of the input."},{"line_number":85,"context_line":"            error \u003d eof and not chunk"},{"line_number":86,"context_line":"        elif self.bytes_received \u003d\u003d self._expected_length:"},{"line_number":87,"context_line":"            # Lazy fetch checksum value because it may have come in trailers."},{"line_number":88,"context_line":"            b64digest \u003d self._checksum_source.get(self._checksum_key)"}],"source_content_type":"text/x-python","patch_set":5,"id":"89e6e0c7_260f13e2","line":85,"range":{"start_line":85,"start_character":12,"end_line":85,"end_character":37},"updated":"2026-08-19 14:42:31.000000000","message":"wait, this is a behavioral change sneaked into what is ostensibly a refactor. Where does InputProxy wrap an iterable? It\u0027s docstring says it is to be used with file like objects. If a read cannot satisfy the requested bytes then we should be at eof.\n\nIf we do have a bug then please address it separately from moving the class to this module.","commit_id":"dbf87c6022b4fbe020f61b271bf2e91841c2e550"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"d66b6a5fa51c4b1a70fa8da7e2c7bdad2572a0b0","unresolved":true,"context_lines":[{"line_number":82,"context_line":"        if self.bytes_received \u003c self._expected_length:"},{"line_number":83,"context_line":"            # A non-empty short read may be one chunk from an iterable-backed"},{"line_number":84,"context_line":"            # input rather than the end of the input."},{"line_number":85,"context_line":"            error \u003d eof and not chunk"},{"line_number":86,"context_line":"        elif self.bytes_received \u003d\u003d self._expected_length:"},{"line_number":87,"context_line":"            # Lazy fetch checksum value because it may have come in trailers."},{"line_number":88,"context_line":"            b64digest \u003d self._checksum_source.get(self._checksum_key)"}],"source_content_type":"text/x-python","patch_set":5,"id":"7a4b4f1f_401dd42c","line":85,"range":{"start_line":85,"start_character":12,"end_line":85,"end_character":37},"in_reply_to":"10bb5cc5_16808802","updated":"2026-08-19 16:12:52.000000000","message":"\u003e There is no bug today AFAICT. It becomes a bug in in 999457\n\nYes\n\nI can move this out into the Copy patch!","commit_id":"dbf87c6022b4fbe020f61b271bf2e91841c2e550"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"15bd9b99cab3ef5e74901b9831890df3574d109e","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        if self.bytes_received \u003c self._expected_length:"},{"line_number":83,"context_line":"            # A non-empty short read may be one chunk from an iterable-backed"},{"line_number":84,"context_line":"            # input rather than the end of the input."},{"line_number":85,"context_line":"            error \u003d eof and not chunk"},{"line_number":86,"context_line":"        elif self.bytes_received \u003d\u003d self._expected_length:"},{"line_number":87,"context_line":"            # Lazy fetch checksum value because it may have come in trailers."},{"line_number":88,"context_line":"            b64digest \u003d self._checksum_source.get(self._checksum_key)"}],"source_content_type":"text/x-python","patch_set":5,"id":"184d8a4f_65fa78cf","line":85,"range":{"start_line":85,"start_character":12,"end_line":85,"end_character":37},"in_reply_to":"7a4b4f1f_401dd42c","updated":"2026-08-19 23:43:00.000000000","message":"Done","commit_id":"dbf87c6022b4fbe020f61b271bf2e91841c2e550"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"ed748296acbbe8ff96eb24d7e20464ce46a61872","unresolved":true,"context_lines":[{"line_number":82,"context_line":"        if self.bytes_received \u003c self._expected_length:"},{"line_number":83,"context_line":"            # A non-empty short read may be one chunk from an iterable-backed"},{"line_number":84,"context_line":"            # input rather than the end of the input."},{"line_number":85,"context_line":"            error \u003d eof and not chunk"},{"line_number":86,"context_line":"        elif self.bytes_received \u003d\u003d self._expected_length:"},{"line_number":87,"context_line":"            # Lazy fetch checksum value because it may have come in trailers."},{"line_number":88,"context_line":"            b64digest \u003d self._checksum_source.get(self._checksum_key)"}],"source_content_type":"text/x-python","patch_set":5,"id":"10bb5cc5_16808802","line":85,"range":{"start_line":85,"start_character":12,"end_line":85,"end_character":37},"in_reply_to":"89e6e0c7_260f13e2","updated":"2026-08-19 15:00:34.000000000","message":"@alistairncoles@gmail.com: Sorry, this on is on me - I asked Nate to change this in my earlier comment.\n\nThere is no bug today AFAICT. It becomes a bug in in 999457. I recommended to fix it here, but you\u0027re right that this is the wrong location because this is mostly moving code.\n\nIn swift/common/middleware/copy.py:476 we use `wsgi.input \u003d FileLikeIter(source_resp.app_iter)`. FileLikeIter.read(size) returns one chunk of the iterable, but it does not fill up to size, and InputProxy.read() calls that eof.","commit_id":"dbf87c6022b4fbe020f61b271bf2e91841c2e550"}],"swift/common/middleware/s3api/s3request.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"061631f210daab007691365994c38d8221b1f4de","unresolved":true,"context_lines":[{"line_number":116,"context_line":"))"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"def _validate_checksum_header_cardinality(num_checksum_headers,"},{"line_number":120,"context_line":"                                          headers_and_trailer\u003dFalse):"},{"line_number":121,"context_line":"    if num_checksum_headers \u003e 1:"},{"line_number":122,"context_line":"        # inconsistent messaging for AWS compatibility..."}],"source_content_type":"text/x-python","patch_set":1,"id":"eaddc924_8d19ecc9","line":119,"updated":"2026-08-14 15:04:32.000000000","message":"good call, leave this where it is","commit_id":"c35f73a79a48646b3b1b9126f44fc201a2281173"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"099116c670c17ecdad0bc7e8de860ef470af29d5","unresolved":false,"context_lines":[{"line_number":116,"context_line":"))"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"def _validate_checksum_header_cardinality(num_checksum_headers,"},{"line_number":120,"context_line":"                                          headers_and_trailer\u003dFalse):"},{"line_number":121,"context_line":"    if num_checksum_headers \u003e 1:"},{"line_number":122,"context_line":"        # inconsistent messaging for AWS compatibility..."}],"source_content_type":"text/x-python","patch_set":1,"id":"9478c55c_83ee1d27","line":119,"in_reply_to":"eaddc924_8d19ecc9","updated":"2026-08-14 23:59:10.000000000","message":"Acknowledged","commit_id":"c35f73a79a48646b3b1b9126f44fc201a2281173"}],"test/unit/common/middleware/s3api/test_s3checksum.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9aba46ebea6db3c252b882a1d0df8bdf2c2dc78e","unresolved":true,"context_lines":[{"line_number":53,"context_line":"            FileLikeIter(iter(body_chunks)), len(body), checksum.crc32(),"},{"line_number":54,"context_line":"            \u0027x-amz-checksum-crc32\u0027, checksum_source)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"        self.assertEqual(body_chunks[0], wrapped.read(150))"},{"line_number":57,"context_line":"        self.assertEqual(body_chunks[1], wrapped.read(150))"},{"line_number":58,"context_line":"        self.assertEqual(b\u0027\u0027, wrapped.read(150))"},{"line_number":59,"context_line":"        self.assertFalse(wrapped.wsgi_input.closed)"}],"source_content_type":"text/x-python","patch_set":5,"id":"23eb6142_2f47822f","line":56,"updated":"2026-08-19 14:42:31.000000000","message":"this is asserting that it is ok for the stream to return only 100 bytes when asked for 150, and yet the stream has 200 bytes. That seems wrong for a file like stream.","commit_id":"dbf87c6022b4fbe020f61b271bf2e91841c2e550"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"15bd9b99cab3ef5e74901b9831890df3574d109e","unresolved":false,"context_lines":[{"line_number":53,"context_line":"            FileLikeIter(iter(body_chunks)), len(body), checksum.crc32(),"},{"line_number":54,"context_line":"            \u0027x-amz-checksum-crc32\u0027, checksum_source)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"        self.assertEqual(body_chunks[0], wrapped.read(150))"},{"line_number":57,"context_line":"        self.assertEqual(body_chunks[1], wrapped.read(150))"},{"line_number":58,"context_line":"        self.assertEqual(b\u0027\u0027, wrapped.read(150))"},{"line_number":59,"context_line":"        self.assertFalse(wrapped.wsgi_input.closed)"}],"source_content_type":"text/x-python","patch_set":5,"id":"bfe155fe_6412e174","line":56,"in_reply_to":"23eb6142_2f47822f","updated":"2026-08-19 23:43:00.000000000","message":"Pushed in https://review.opendev.org/c/openstack/swift/+/999457/25..26/test/unit/common/middleware/s3api/test_s3checksum.py#51","commit_id":"dbf87c6022b4fbe020f61b271bf2e91841c2e550"}]}
