)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"673cf2a26468af3af6b9f63d6c60a63bd1e956fb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"17e010c6_5a0dbb18","updated":"2025-11-25 11:51:53.000000000","message":"Could you drop the unnecessary `noqa` comment in a follow-up?","commit_id":"490d049557ace0b657c143795cfb6c413ca40572"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"e67cd0016d5493230a36eaaf24d09f74edeac105","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"23c6184f_4e77d7dd","updated":"2025-11-25 17:53:19.000000000","message":"This should unblock CI: https://review.opendev.org/c/openstack/openstacksdk/+/968353","commit_id":"490d049557ace0b657c143795cfb6c413ca40572"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"836aad1faebef4b573c64851746e943f5fb07f47","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"ec86eb13_c35140b6","updated":"2025-11-25 21:24:34.000000000","message":"Some nits but once again not going to hold on those (assuming pep8 is happy this time)","commit_id":"cbd7677a97003d4decddf67ba90b83b1f7fa9e66"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"c8f07c4a5a46e58c6bb02f93ca2bffbefc838b8b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"b1b0fc6f_bb36f8e1","updated":"2025-11-25 20:45:20.000000000","message":"recheck - pep8 should be fixed now.","commit_id":"cbd7677a97003d4decddf67ba90b83b1f7fa9e66"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"4f40a3b8fd33a80817f0b68c683f4066998dd733","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":4,"id":"60a8e999_d6441b2d","updated":"2025-12-22 14:41:11.000000000","message":"What do we need for a +W here?","commit_id":"263dd48a1774354580d97121da2528f46117b8f7"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"64e1b71d07f73a252fd85eb33f53265c2a6e6650","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"092bfcac_117511c8","updated":"2025-12-01 14:58:55.000000000","message":"recheck","commit_id":"263dd48a1774354580d97121da2528f46117b8f7"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"e8847ac332cb818e5583338400a077243a5b7538","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"86e98a2f_c993e3e8","updated":"2025-11-27 10:33:54.000000000","message":"recheck - POST_FAILURE","commit_id":"263dd48a1774354580d97121da2528f46117b8f7"},{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"e8c48aee687d845031f4880068bba80363e2bac1","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":4,"id":"c6f2e7b3_cf2cf907","in_reply_to":"60a8e999_d6441b2d","updated":"2025-12-22 14:49:38.000000000","message":"less distraction on every other front ;-)","commit_id":"263dd48a1774354580d97121da2528f46117b8f7"}],"openstack/image/_download.py":[{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"acdb800b48eeca73ca33272a55d0d2f02cb01a5b","unresolved":true,"context_lines":[{"line_number":108,"context_line":"                hasher \u003d hashlib.new(str(meta_hash_algo))"},{"line_number":109,"context_line":"                expected_hash \u003d meta_hash_value"},{"line_number":110,"context_line":"                hash_algo \u003d meta_hash_algo"},{"line_number":111,"context_line":"                use_secure_hash \u003d True"},{"line_number":112,"context_line":"            except ValueError as ve:"},{"line_number":113,"context_line":"                if ("},{"line_number":114,"context_line":"                    str(ve).startswith(\u0027unsupported hash type\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"a0da905d_02f08432","line":111,"updated":"2025-11-07 12:03:00.000000000","message":"nit: from what I understand remote can use md5 or sha1 if provider decides so. None are really \"secure\", so maybe use the different variable name.","commit_id":"66beefe7d3159e32f5f226dcc63f02edd51e52fe"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"b9e8ae85e3b6370b9a0dcd31028ff9bb70eb4469","unresolved":false,"context_lines":[{"line_number":108,"context_line":"                hasher \u003d hashlib.new(str(meta_hash_algo))"},{"line_number":109,"context_line":"                expected_hash \u003d meta_hash_value"},{"line_number":110,"context_line":"                hash_algo \u003d meta_hash_algo"},{"line_number":111,"context_line":"                use_secure_hash \u003d True"},{"line_number":112,"context_line":"            except ValueError as ve:"},{"line_number":113,"context_line":"                if ("},{"line_number":114,"context_line":"                    str(ve).startswith(\u0027unsupported hash type\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"d4739036_ff5df193","line":111,"in_reply_to":"a0da905d_02f08432","updated":"2025-11-10 08:23:46.000000000","message":"Acknowledged","commit_id":"66beefe7d3159e32f5f226dcc63f02edd51e52fe"},{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"acdb800b48eeca73ca33272a55d0d2f02cb01a5b","unresolved":true,"context_lines":[{"line_number":118,"context_line":"                else:"},{"line_number":119,"context_line":"                    raise exceptions.SDKException("},{"line_number":120,"context_line":"                        f\"Unsupported hash algorithm \u0027{meta_hash_algo}\u0027: {ve}\""},{"line_number":121,"context_line":"                    )"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"        if not use_secure_hash and meta_checksum is not None:"},{"line_number":124,"context_line":"            hasher \u003d hashlib.md5(usedforsecurity\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":1,"id":"66d40a9c_73cd2f56","line":121,"updated":"2025-11-07 12:03:00.000000000","message":"what about restructuring those if, if - elif, if statements to: \n```\nif meta_hash_algo and meta_hash_value: \n    try:\n        hasher \u003d hashlib ....  \n        expected_hash \u003d meta_hash_value\n    except:\n        ...\n# if metadata hashing is not usable fallback to header metadata \nif not hasher or not expected_hash:\n    hasher \u003d hashlib.md5...\n    expected_hash \u003d header_checksum\n...\n```","commit_id":"66beefe7d3159e32f5f226dcc63f02edd51e52fe"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"b9e8ae85e3b6370b9a0dcd31028ff9bb70eb4469","unresolved":true,"context_lines":[{"line_number":118,"context_line":"                else:"},{"line_number":119,"context_line":"                    raise exceptions.SDKException("},{"line_number":120,"context_line":"                        f\"Unsupported hash algorithm \u0027{meta_hash_algo}\u0027: {ve}\""},{"line_number":121,"context_line":"                    )"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"        if not use_secure_hash and meta_checksum is not None:"},{"line_number":124,"context_line":"            hasher \u003d hashlib.md5(usedforsecurity\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":1,"id":"7f5cfaa0_1256489d","line":121,"in_reply_to":"66d40a9c_73cd2f56","updated":"2025-11-10 08:23:46.000000000","message":"That actually makes more sense, tks!","commit_id":"66beefe7d3159e32f5f226dcc63f02edd51e52fe"},{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"fc05bc63cf11c53f1b6c473d8d0082085e420114","unresolved":false,"context_lines":[{"line_number":118,"context_line":"                else:"},{"line_number":119,"context_line":"                    raise exceptions.SDKException("},{"line_number":120,"context_line":"                        f\"Unsupported hash algorithm \u0027{meta_hash_algo}\u0027: {ve}\""},{"line_number":121,"context_line":"                    )"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"        if not use_secure_hash and meta_checksum is not None:"},{"line_number":124,"context_line":"            hasher \u003d hashlib.md5(usedforsecurity\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":1,"id":"7b8c7453_5527e2d9","line":121,"in_reply_to":"7f5cfaa0_1256489d","updated":"2025-11-14 14:27:56.000000000","message":"Done","commit_id":"66beefe7d3159e32f5f226dcc63f02edd51e52fe"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"673cf2a26468af3af6b9f63d6c60a63bd1e956fb","unresolved":true,"context_lines":[{"line_number":17,"context_line":"from openstack import utils"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"def _verify_checksum(hasher, expected_hash, hash_algo\u003dNone):"},{"line_number":21,"context_line":"    \"\"\"Verify checksum using the provided hasher."},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    :param hasher: A hashlib hash object"}],"source_content_type":"text/x-python","patch_set":2,"id":"d24d2b64_77b37fe0","line":20,"updated":"2025-11-25 11:51:53.000000000","message":"nit: it would be fantastic to get hints here and below for the new util code","commit_id":"490d049557ace0b657c143795cfb6c413ca40572"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"f0fa3fdfd75cc515e17dcc704c7dcc795346ef01","unresolved":false,"context_lines":[{"line_number":17,"context_line":"from openstack import utils"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"def _verify_checksum(hasher, expected_hash, hash_algo\u003dNone):"},{"line_number":21,"context_line":"    \"\"\"Verify checksum using the provided hasher."},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    :param hasher: A hashlib hash object"}],"source_content_type":"text/x-python","patch_set":2,"id":"e5f1e63a_1e490ade","line":20,"in_reply_to":"d24d2b64_77b37fe0","updated":"2025-11-25 18:12:25.000000000","message":"Acknowledged","commit_id":"490d049557ace0b657c143795cfb6c413ca40572"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"e9a1d85e6f6f91f352e5c3871480ca3409748c5a","unresolved":true,"context_lines":[{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"def _integrity_iter("},{"line_number":43,"context_line":"    iterable: ty.Iterable[bytes],"},{"line_number":44,"context_line":"    hasher: ty.Any,"},{"line_number":45,"context_line":"    expected_hash: str | None,"},{"line_number":46,"context_line":"    hash_algo: str | None,"}],"source_content_type":"text/x-python","patch_set":3,"id":"fb2c242a_5fda7330","line":43,"updated":"2025-11-25 21:23:55.000000000","message":"These are deprecated aliases now as the types from `collections.abc` are subscriptable since Python 3.10 (I think):\n\n```suggestion\n    iterable: collections.abc.Iterable[bytes],\n```","commit_id":"cbd7677a97003d4decddf67ba90b83b1f7fa9e66"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"e8847ac332cb818e5583338400a077243a5b7538","unresolved":false,"context_lines":[{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"def _integrity_iter("},{"line_number":43,"context_line":"    iterable: ty.Iterable[bytes],"},{"line_number":44,"context_line":"    hasher: ty.Any,"},{"line_number":45,"context_line":"    expected_hash: str | None,"},{"line_number":46,"context_line":"    hash_algo: str | None,"}],"source_content_type":"text/x-python","patch_set":3,"id":"6b472ebc_2bb60259","line":43,"in_reply_to":"fb2c242a_5fda7330","updated":"2025-11-27 10:33:54.000000000","message":"Acknowledged","commit_id":"cbd7677a97003d4decddf67ba90b83b1f7fa9e66"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"e9a1d85e6f6f91f352e5c3871480ca3409748c5a","unresolved":true,"context_lines":[{"line_number":44,"context_line":"    hasher: ty.Any,"},{"line_number":45,"context_line":"    expected_hash: str | None,"},{"line_number":46,"context_line":"    hash_algo: str | None,"},{"line_number":47,"context_line":") -\u003e ty.Iterator[bytes]:"},{"line_number":48,"context_line":"    \"\"\"Check image data integrity"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    :param iterable: Iterable containing the image data chunks"}],"source_content_type":"text/x-python","patch_set":3,"id":"4308632a_820debc3","line":47,"updated":"2025-11-25 21:23:55.000000000","message":"```suggestion\n) -\u003e collections.abc.Iterator[bytes]:\n```","commit_id":"cbd7677a97003d4decddf67ba90b83b1f7fa9e66"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"e8847ac332cb818e5583338400a077243a5b7538","unresolved":false,"context_lines":[{"line_number":44,"context_line":"    hasher: ty.Any,"},{"line_number":45,"context_line":"    expected_hash: str | None,"},{"line_number":46,"context_line":"    hash_algo: str | None,"},{"line_number":47,"context_line":") -\u003e ty.Iterator[bytes]:"},{"line_number":48,"context_line":"    \"\"\"Check image data integrity"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"    :param iterable: Iterable containing the image data chunks"}],"source_content_type":"text/x-python","patch_set":3,"id":"e3843465_86d207fa","line":47,"in_reply_to":"4308632a_820debc3","updated":"2025-11-27 10:33:54.000000000","message":"Acknowledged","commit_id":"cbd7677a97003d4decddf67ba90b83b1f7fa9e66"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"e9a1d85e6f6f91f352e5c3871480ca3409748c5a","unresolved":true,"context_lines":[{"line_number":60,"context_line":"    _verify_checksum(hasher, expected_hash, hash_algo)"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"def _write_chunks(fd: io.IOBase, chunks: ty.Iterable[bytes]) -\u003e None:"},{"line_number":64,"context_line":"    \"\"\"Write chunks to file descriptor.\"\"\""},{"line_number":65,"context_line":"    for chunk in chunks:"},{"line_number":66,"context_line":"        fd.write(chunk)"}],"source_content_type":"text/x-python","patch_set":3,"id":"b28eec3c_a9b64130","line":63,"updated":"2025-11-25 21:23:55.000000000","message":"```suggestion\ndef _write_chunks(\n    fd: io.IOBase, chunks: collections.abc.Iterable[bytes]\n) -\u003e None:\n```","commit_id":"cbd7677a97003d4decddf67ba90b83b1f7fa9e66"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"e8847ac332cb818e5583338400a077243a5b7538","unresolved":false,"context_lines":[{"line_number":60,"context_line":"    _verify_checksum(hasher, expected_hash, hash_algo)"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"def _write_chunks(fd: io.IOBase, chunks: ty.Iterable[bytes]) -\u003e None:"},{"line_number":64,"context_line":"    \"\"\"Write chunks to file descriptor.\"\"\""},{"line_number":65,"context_line":"    for chunk in chunks:"},{"line_number":66,"context_line":"        fd.write(chunk)"}],"source_content_type":"text/x-python","patch_set":3,"id":"ec74a04e_42d5c482","line":63,"in_reply_to":"b28eec3c_a9b64130","updated":"2025-11-27 10:33:54.000000000","message":"Acknowledged","commit_id":"cbd7677a97003d4decddf67ba90b83b1f7fa9e66"}],"openstack/tests/unit/cloud/test_image.py":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"673cf2a26468af3af6b9f63d6c60a63bd1e956fb","unresolved":true,"context_lines":[{"line_number":126,"context_line":"                ),"},{"line_number":127,"context_line":"                dict("},{"line_number":128,"context_line":"                    method\u003d\u0027GET\u0027,"},{"line_number":129,"context_line":"                    uri\u003df\u0027https://image.example.com/v2/images/{self.image_id}\u0027,  # noqa: E501"},{"line_number":130,"context_line":"                    json\u003dself.fake_image_dict,"},{"line_number":131,"context_line":"                ),"},{"line_number":132,"context_line":"                dict("}],"source_content_type":"text/x-python","patch_set":2,"id":"5f2f6d8b_8f1166d2","line":129,"updated":"2025-11-25 11:51:53.000000000","message":"You don\u0027t need this\n\n```suggestion\n                    uri\u003df\u0027https://image.example.com/v2/images/{self.image_id}\u0027,\n```","commit_id":"490d049557ace0b657c143795cfb6c413ca40572"},{"author":{"_account_id":36770,"name":"cid","display_name":"cid","email":"cid@gr-oss.io","username":"cidelight","status":"@gr-oss upstream: Doing good IRONIC things..."},"change_message_id":"f0fa3fdfd75cc515e17dcc704c7dcc795346ef01","unresolved":false,"context_lines":[{"line_number":126,"context_line":"                ),"},{"line_number":127,"context_line":"                dict("},{"line_number":128,"context_line":"                    method\u003d\u0027GET\u0027,"},{"line_number":129,"context_line":"                    uri\u003df\u0027https://image.example.com/v2/images/{self.image_id}\u0027,  # noqa: E501"},{"line_number":130,"context_line":"                    json\u003dself.fake_image_dict,"},{"line_number":131,"context_line":"                ),"},{"line_number":132,"context_line":"                dict("}],"source_content_type":"text/x-python","patch_set":2,"id":"ed07d673_e5da821e","line":129,"in_reply_to":"5f2f6d8b_8f1166d2","updated":"2025-11-25 18:12:25.000000000","message":"Acknowledged","commit_id":"490d049557ace0b657c143795cfb6c413ca40572"}],"openstack/tests/unit/image/v2/test_image.py":[{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"acdb800b48eeca73ca33272a55d0d2f02cb01a5b","unresolved":true,"context_lines":[{"line_number":410,"context_line":""},{"line_number":411,"context_line":"        self.assertEqual(rv, resp2)"},{"line_number":412,"context_line":""},{"line_number":413,"context_line":"    def test_download_checksum_mismatch(self):"},{"line_number":414,"context_line":"        example_with_wrong_hash \u003d EXAMPLE.copy()"},{"line_number":415,"context_line":"        example_with_wrong_hash[\u0027os_hash_value\u0027] \u003d \"wrong_hash_value\""},{"line_number":416,"context_line":"        sot \u003d image.Image(**example_with_wrong_hash)"}],"source_content_type":"text/x-python","patch_set":1,"id":"fc4b5969_4a83a1fa","line":413,"updated":"2025-11-07 12:03:00.000000000","message":"lets please have another test verifying the os_hash_algo is not supported by hashlib (maybe it is a very very old image and python don\u0027t support this algo today)","commit_id":"66beefe7d3159e32f5f226dcc63f02edd51e52fe"},{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"fc05bc63cf11c53f1b6c473d8d0082085e420114","unresolved":false,"context_lines":[{"line_number":410,"context_line":""},{"line_number":411,"context_line":"        self.assertEqual(rv, resp2)"},{"line_number":412,"context_line":""},{"line_number":413,"context_line":"    def test_download_checksum_mismatch(self):"},{"line_number":414,"context_line":"        example_with_wrong_hash \u003d EXAMPLE.copy()"},{"line_number":415,"context_line":"        example_with_wrong_hash[\u0027os_hash_value\u0027] \u003d \"wrong_hash_value\""},{"line_number":416,"context_line":"        sot \u003d image.Image(**example_with_wrong_hash)"}],"source_content_type":"text/x-python","patch_set":1,"id":"ecdd7515_2cf8b09e","line":413,"in_reply_to":"fc4b5969_4a83a1fa","updated":"2025-11-14 14:27:56.000000000","message":"Done","commit_id":"66beefe7d3159e32f5f226dcc63f02edd51e52fe"}]}
