)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"9e42c2c30404e2f37fd1a62d8971a720a13506e1","unresolved":true,"context_lines":[{"line_number":7,"context_line":"Handle ISO+GPT hybrid images in image conversion plugin"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Hybrid ISO images (ISO+GPT) can trigger multiple format detection errors, even though they are valid for UEFI boot. Align with existing logic by resolving {iso, gpt} to ISO on error, while keeping other multi-format cases unchanged. (e.g., {iso, qcow2})."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Closes-Bug: #2140767"},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"Change-Id: I8ecc165a779aa9812a00c6626e338b49512fd0a8"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"3196d3f4_d0c79149","line":10,"updated":"2026-04-06 13:42:46.000000000","message":"Can you wrap this please?\n\nAlso, the way this is written it sounds like ISO+GPT is an error (due to the \"on error\" phrase) and ISO+qcow2 is not. I know that\u0027s not what you mean (obviously) but it\u0027s not super clear so I think it\u0027d be worth making it a little more specific.","commit_id":"168cb9a44a115e71374b525726a0552a7f460f70"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"2b08d66f4a3aa35e6e19d05826ca4fe0dfde345f","unresolved":false,"context_lines":[{"line_number":7,"context_line":"Handle ISO+GPT hybrid images in image conversion plugin"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Hybrid ISO images (ISO+GPT) can trigger multiple format detection errors, even though they are valid for UEFI boot. Align with existing logic by resolving {iso, gpt} to ISO on error, while keeping other multi-format cases unchanged. (e.g., {iso, qcow2})."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Closes-Bug: #2140767"},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"Change-Id: I8ecc165a779aa9812a00c6626e338b49512fd0a8"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"aef7b29e_049697a5","line":10,"in_reply_to":"3196d3f4_d0c79149","updated":"2026-04-08 07:05:08.000000000","message":"Done","commit_id":"168cb9a44a115e71374b525726a0552a7f460f70"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"709f9e7c164f46aa1c60bc892a93d40c7b0785a1","unresolved":true,"context_lines":[{"line_number":16,"context_line":"combinations (e.g. {\u0027iso\u0027, \u0027qcow2\u0027}) with ImageFormatError."},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"Closes-Bug: #2140767"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"Change-Id: I8ecc165a779aa9812a00c6626e338b49512fd0a8"},{"line_number":21,"context_line":"Signed-off-by: sakumbha \u003csakumbha@redhat.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"3b69ce1d_b960d749","line":19,"updated":"2026-04-14 12:45:58.000000000","message":"if you have used cursor or any other AI agent for coding then you need to add tag\nAssisted-By: Cursor or Agent name","commit_id":"504dd158bccddd4cdcd7baa2fddad9ff605fa618"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"6b1048ceccd415747e6989fa1165858913e74a7b","unresolved":false,"context_lines":[{"line_number":16,"context_line":"combinations (e.g. {\u0027iso\u0027, \u0027qcow2\u0027}) with ImageFormatError."},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"Closes-Bug: #2140767"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"Change-Id: I8ecc165a779aa9812a00c6626e338b49512fd0a8"},{"line_number":21,"context_line":"Signed-off-by: sakumbha \u003csakumbha@redhat.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"5ac6c4fb_d03c7aa5","line":19,"in_reply_to":"3b69ce1d_b960d749","updated":"2026-05-08 07:19:12.000000000","message":"Acknowledged","commit_id":"504dd158bccddd4cdcd7baa2fddad9ff605fa618"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"2e24544ecf6e27eedaef5bee6a1be68e586e7e27","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"945081cf_c266bff8","updated":"2026-04-14 12:37:16.000000000","message":"recheck","commit_id":"504dd158bccddd4cdcd7baa2fddad9ff605fa618"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"493db00ffacf9494052bd7ba126c4fca397e07a7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"9645ee77_d05aaf3b","updated":"2026-05-08 10:08:17.000000000","message":"recheck","commit_id":"6656b1831b379abfb17f9cf0745db56e1fb95f56"}],"glance/async_/flows/plugins/image_conversion.py":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"9e42c2c30404e2f37fd1a62d8971a720a13506e1","unresolved":true,"context_lines":[{"line_number":133,"context_line":"                inspector.safety_check()"},{"line_number":134,"context_line":"            else:"},{"line_number":135,"context_line":"                LOG.error(\u0027Image failed format inspection: %s\u0027, e)"},{"line_number":136,"context_line":"                raise RuntimeError(\u0027Image format detection failed\u0027)"},{"line_number":137,"context_line":"        except Exception as e:"},{"line_number":138,"context_line":"            LOG.exception(\u0027Unknown error inspecting image format: %s\u0027, e)"},{"line_number":139,"context_line":"            raise RuntimeError(\u0027Unable to inspect image\u0027)"}],"source_content_type":"text/x-python","patch_set":2,"id":"b075e894_abe9beb8","line":136,"updated":"2026-04-06 13:42:46.000000000","message":"This approach will re-inspect every detection failure just to get access to the inspector, which seems un-ideal to me.\n\nI have been meaning to add a multi-format-capable file detection routine to oslo.utils to handle this. But, if we want/need to fix it sooner, I think we should model this after the support in the upload path:\n\nhttps://review.opendev.org/c/openstack/glance/+/963868\n\nand just replace our use of `detect_file_format()` with a single run-through. What you have here will also not handle SafetyCheckFailed properly, and doesn\u0027t run all the inspectors to completion, which may mean you don\u0027t catch triple matches or matches that require more than 4k of the image to be confirmed. Using `InspectWrapper.formats()` should give us the multi-format match once we\u0027re sure we\u0027ve read enough to make the decision.","commit_id":"168cb9a44a115e71374b525726a0552a7f460f70"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"2b08d66f4a3aa35e6e19d05826ca4fe0dfde345f","unresolved":false,"context_lines":[{"line_number":133,"context_line":"                inspector.safety_check()"},{"line_number":134,"context_line":"            else:"},{"line_number":135,"context_line":"                LOG.error(\u0027Image failed format inspection: %s\u0027, e)"},{"line_number":136,"context_line":"                raise RuntimeError(\u0027Image format detection failed\u0027)"},{"line_number":137,"context_line":"        except Exception as e:"},{"line_number":138,"context_line":"            LOG.exception(\u0027Unknown error inspecting image format: %s\u0027, e)"},{"line_number":139,"context_line":"            raise RuntimeError(\u0027Unable to inspect image\u0027)"}],"source_content_type":"text/x-python","patch_set":2,"id":"e4f907cf_41b7497c","line":136,"in_reply_to":"b075e894_abe9beb8","updated":"2026-04-08 07:05:08.000000000","message":"Thanks, this was helpful.\nI’ve updated the implementation to use a single-pass inspection with InspectWrapper, reading until EOF so all inspectors run to completion. Detection now uses wrapper.formats() to handle multi-format cases properly, including triple matches.\nAlso added explicit handling for {\u0027iso\u0027, \u0027gpt\u0027} and ensured SafetyCheckFailed is handled correctly.\nPlease let me know if this looks good.","commit_id":"168cb9a44a115e71374b525726a0552a7f460f70"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"2e24544ecf6e27eedaef5bee6a1be68e586e7e27","unresolved":false,"context_lines":[{"line_number":133,"context_line":"                inspector.safety_check()"},{"line_number":134,"context_line":"            else:"},{"line_number":135,"context_line":"                LOG.error(\u0027Image failed format inspection: %s\u0027, e)"},{"line_number":136,"context_line":"                raise RuntimeError(\u0027Image format detection failed\u0027)"},{"line_number":137,"context_line":"        except Exception as e:"},{"line_number":138,"context_line":"            LOG.exception(\u0027Unknown error inspecting image format: %s\u0027, e)"},{"line_number":139,"context_line":"            raise RuntimeError(\u0027Unable to inspect image\u0027)"}],"source_content_type":"text/x-python","patch_set":2,"id":"6568e9b3_707499d9","line":136,"in_reply_to":"e2d17f9e_57abb54a","updated":"2026-04-14 12:37:16.000000000","message":"No, I used it to structure my implementation.","commit_id":"168cb9a44a115e71374b525726a0552a7f460f70"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"55ab56d2acb13dcda5adb9c57b28fe84a66e2477","unresolved":false,"context_lines":[{"line_number":133,"context_line":"                inspector.safety_check()"},{"line_number":134,"context_line":"            else:"},{"line_number":135,"context_line":"                LOG.error(\u0027Image failed format inspection: %s\u0027, e)"},{"line_number":136,"context_line":"                raise RuntimeError(\u0027Image format detection failed\u0027)"},{"line_number":137,"context_line":"        except Exception as e:"},{"line_number":138,"context_line":"            LOG.exception(\u0027Unknown error inspecting image format: %s\u0027, e)"},{"line_number":139,"context_line":"            raise RuntimeError(\u0027Unable to inspect image\u0027)"}],"source_content_type":"text/x-python","patch_set":2,"id":"e2d17f9e_57abb54a","line":136,"in_reply_to":"e4f907cf_41b7497c","updated":"2026-04-08 14:21:49.000000000","message":"This almost sounds like a Claude work summary. I hope you\u0027re not just feeding my comments into Claude and pasting the result here :)","commit_id":"168cb9a44a115e71374b525726a0552a7f460f70"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"55ab56d2acb13dcda5adb9c57b28fe84a66e2477","unresolved":true,"context_lines":[{"line_number":108,"context_line":"                    # chunk to every active inspector until EOF."},{"line_number":109,"context_line":"                    while True:"},{"line_number":110,"context_line":"                        chunk \u003d wrapper.read(_IMAGE_INSPECTION_READ_SIZE)"},{"line_number":111,"context_line":"                        if not chunk:"},{"line_number":112,"context_line":"                            break"},{"line_number":113,"context_line":"                finally:"},{"line_number":114,"context_line":"                    # Run ``finish()`` on all inspectors so ``.formats`` is"}],"source_content_type":"text/x-python","patch_set":3,"id":"f21f3deb_fab0cdd4","line":111,"updated":"2026-04-08 14:21:49.000000000","message":"This will now read to completion, which could be 8TB of data, even if we only need the first 1KB. In the upload data pipeline that\u0027s fine because we have to read the whole thing anyway. Here, it does not.\n\nPlease use `wrapper.formats` to control ending the loop. It will return None until a definitive decision has been made, after which time it will return the relevant formats.","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"2e24544ecf6e27eedaef5bee6a1be68e586e7e27","unresolved":false,"context_lines":[{"line_number":108,"context_line":"                    # chunk to every active inspector until EOF."},{"line_number":109,"context_line":"                    while True:"},{"line_number":110,"context_line":"                        chunk \u003d wrapper.read(_IMAGE_INSPECTION_READ_SIZE)"},{"line_number":111,"context_line":"                        if not chunk:"},{"line_number":112,"context_line":"                            break"},{"line_number":113,"context_line":"                finally:"},{"line_number":114,"context_line":"                    # Run ``finish()`` on all inspectors so ``.formats`` is"}],"source_content_type":"text/x-python","patch_set":3,"id":"7cd22755_5334fa23","line":111,"in_reply_to":"f21f3deb_fab0cdd4","updated":"2026-04-14 12:37:16.000000000","message":"Done, used wrapper.formats to control ending loop till a definitive decision is made.","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"55ab56d2acb13dcda5adb9c57b28fe84a66e2477","unresolved":true,"context_lines":[{"line_number":116,"context_line":"                    wrapper.close()"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"            matches \u003d wrapper.formats"},{"line_number":119,"context_line":"            if matches is None:"},{"line_number":120,"context_line":"                raise format_inspector.ImageFormatError("},{"line_number":121,"context_line":"                    \u0027No format detected\u0027)"},{"line_number":122,"context_line":"            # Same keying as location.py upload path (str(inspector) is stable"}],"source_content_type":"text/x-python","patch_set":3,"id":"a5617dbb_159f17bf","line":119,"updated":"2026-04-08 14:21:49.000000000","message":"When will this happen? If you don\u0027t constrain the allowed formats (and you\u0027re not), we should only ever get RawInspector here, right?","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"2e24544ecf6e27eedaef5bee6a1be68e586e7e27","unresolved":false,"context_lines":[{"line_number":116,"context_line":"                    wrapper.close()"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"            matches \u003d wrapper.formats"},{"line_number":119,"context_line":"            if matches is None:"},{"line_number":120,"context_line":"                raise format_inspector.ImageFormatError("},{"line_number":121,"context_line":"                    \u0027No format detected\u0027)"},{"line_number":122,"context_line":"            # Same keying as location.py upload path (str(inspector) is stable"}],"source_content_type":"text/x-python","patch_set":3,"id":"5dbc28d6_91397327","line":119,"in_reply_to":"a5617dbb_159f17bf","updated":"2026-04-14 12:37:16.000000000","message":"Done","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"55ab56d2acb13dcda5adb9c57b28fe84a66e2477","unresolved":true,"context_lines":[{"line_number":142,"context_line":"                if inspector is not None:"},{"line_number":143,"context_line":"                    LOG.error(\u0027%s %s\u0027, str(inspector), e)"},{"line_number":144,"context_line":"                else:"},{"line_number":145,"context_line":"                    LOG.error(\u0027Image safety check failed: %s\u0027, e)"},{"line_number":146,"context_line":"                raise RuntimeError(\u0027Image has disallowed configuration\u0027)"},{"line_number":147,"context_line":"        except format_inspector.ImageFormatError as e:"},{"line_number":148,"context_line":"            LOG.error(\u0027Image failed format inspection: %s\u0027, e)"}],"source_content_type":"text/x-python","patch_set":3,"id":"c5fea091_0e26a48a","line":145,"updated":"2026-04-08 14:21:49.000000000","message":"I think that this (now) nested try..except block is really complicated and hard to read. Can you change this up now to make it more easy to grok? I think that having the top-level try..except around the whole thing doesn\u0027t make sense anymore (it used to wrap one statement) and needing to handle `if inspector is None` everywhere makes it pretty messy. Perhaps a helper function to split this up would get it back closer to what it looked like before?","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"2e24544ecf6e27eedaef5bee6a1be68e586e7e27","unresolved":false,"context_lines":[{"line_number":142,"context_line":"                if inspector is not None:"},{"line_number":143,"context_line":"                    LOG.error(\u0027%s %s\u0027, str(inspector), e)"},{"line_number":144,"context_line":"                else:"},{"line_number":145,"context_line":"                    LOG.error(\u0027Image safety check failed: %s\u0027, e)"},{"line_number":146,"context_line":"                raise RuntimeError(\u0027Image has disallowed configuration\u0027)"},{"line_number":147,"context_line":"        except format_inspector.ImageFormatError as e:"},{"line_number":148,"context_line":"            LOG.error(\u0027Image failed format inspection: %s\u0027, e)"}],"source_content_type":"text/x-python","patch_set":3,"id":"b3a09dd4_087be79f","line":145,"in_reply_to":"c5fea091_0e26a48a","updated":"2026-04-14 12:37:16.000000000","message":"Done, added helper function _inspect_path to make it more easy.","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"}],"glance/tests/unit/async_/flows/plugins/test_image_conversion.py":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"55ab56d2acb13dcda5adb9c57b28fe84a66e2477","unresolved":true,"context_lines":[{"line_number":98,"context_line":""},{"line_number":99,"context_line":"        self._inspector \u003d mock.MagicMock()"},{"line_number":100,"context_line":"        self._inspector.NAME \u003d \u0027qcow2\u0027"},{"line_number":101,"context_line":"        self._inspector.__str__.return_value \u003d \u0027qcow2\u0027"},{"line_number":102,"context_line":"        self._wrapper \u003d mock.MagicMock()"},{"line_number":103,"context_line":"        self._wrapper.read.return_value \u003d b\u0027\u0027"},{"line_number":104,"context_line":"        self._wrapper.formats \u003d [self._inspector]"}],"source_content_type":"text/x-python","patch_set":3,"id":"cb2c5352_7a99ef8e","line":101,"updated":"2026-04-08 14:21:49.000000000","message":"If you make this a function that runs `str(self._inspector.NAME)` then you won\u0027t need to adjust the mock everywhere below. But, given you reproduce this same build-a-mocked-inspector pattern several places below, perhaps you could just write a helper function to do this generically and then re-use it here and below?","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"2e24544ecf6e27eedaef5bee6a1be68e586e7e27","unresolved":false,"context_lines":[{"line_number":98,"context_line":""},{"line_number":99,"context_line":"        self._inspector \u003d mock.MagicMock()"},{"line_number":100,"context_line":"        self._inspector.NAME \u003d \u0027qcow2\u0027"},{"line_number":101,"context_line":"        self._inspector.__str__.return_value \u003d \u0027qcow2\u0027"},{"line_number":102,"context_line":"        self._wrapper \u003d mock.MagicMock()"},{"line_number":103,"context_line":"        self._wrapper.read.return_value \u003d b\u0027\u0027"},{"line_number":104,"context_line":"        self._wrapper.formats \u003d [self._inspector]"}],"source_content_type":"text/x-python","patch_set":3,"id":"cf512e96_320cef9e","line":101,"in_reply_to":"cb2c5352_7a99ef8e","updated":"2026-04-14 12:37:16.000000000","message":"Done","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"55ab56d2acb13dcda5adb9c57b28fe84a66e2477","unresolved":true,"context_lines":[{"line_number":272,"context_line":"            RuntimeError,"},{"line_number":273,"context_line":"            image_convert.execute, \u0027file:///test/path.iso\u0027)"},{"line_number":274,"context_line":"        self.assertEqual(\u0027Image format detection failed\u0027, str(e))"},{"line_number":275,"context_line":""},{"line_number":276,"context_line":"    def _setup_image_convert_info_fail(self, disk_format\u003d\u0027qcow2\u0027):"},{"line_number":277,"context_line":"        image_convert \u003d image_conversion._ConvertImage(self.context,"},{"line_number":278,"context_line":"                                                       self.task.task_id,"}],"source_content_type":"text/x-python","patch_set":3,"id":"4b44dcbd_33c13c95","line":275,"updated":"2026-04-08 14:21:49.000000000","message":"Seems like these tests are basically identical except for the two formats they return. An opportunity for DRYing up I think.","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"2e24544ecf6e27eedaef5bee6a1be68e586e7e27","unresolved":false,"context_lines":[{"line_number":272,"context_line":"            RuntimeError,"},{"line_number":273,"context_line":"            image_convert.execute, \u0027file:///test/path.iso\u0027)"},{"line_number":274,"context_line":"        self.assertEqual(\u0027Image format detection failed\u0027, str(e))"},{"line_number":275,"context_line":""},{"line_number":276,"context_line":"    def _setup_image_convert_info_fail(self, disk_format\u003d\u0027qcow2\u0027):"},{"line_number":277,"context_line":"        image_convert \u003d image_conversion._ConvertImage(self.context,"},{"line_number":278,"context_line":"                                                       self.task.task_id,"}],"source_content_type":"text/x-python","patch_set":3,"id":"7163bad6_974e8d7a","line":275,"in_reply_to":"4b44dcbd_33c13c95","updated":"2026-04-14 12:37:16.000000000","message":"Done, made changes according","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"55ab56d2acb13dcda5adb9c57b28fe84a66e2477","unresolved":true,"context_lines":[{"line_number":373,"context_line":"    def test_image_convert_fails_inspection_format_check(self):"},{"line_number":374,"context_line":"        convert \u003d self._setup_image_convert_info_fail()"},{"line_number":375,"context_line":"        # No decision until stream finished; None after close \u003d\u003e no format."},{"line_number":376,"context_line":"        self._wrapper.formats \u003d None"},{"line_number":377,"context_line":"        self.assertRaisesRegex(RuntimeError,"},{"line_number":378,"context_line":"                               \u0027Image format detection failed\u0027,"},{"line_number":379,"context_line":"                               convert.execute, \u0027file:///test/path.qcow\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"0176a80b_baed9184","line":376,"updated":"2026-04-08 14:21:49.000000000","message":"This test was for the case where we encounter a fatal error inspecting a file, but you\u0027ve changed it to (what I believe to be) an impossible scenario where formats is None.\n\nMaybe I\u0027m missing something?","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"2e24544ecf6e27eedaef5bee6a1be68e586e7e27","unresolved":false,"context_lines":[{"line_number":373,"context_line":"    def test_image_convert_fails_inspection_format_check(self):"},{"line_number":374,"context_line":"        convert \u003d self._setup_image_convert_info_fail()"},{"line_number":375,"context_line":"        # No decision until stream finished; None after close \u003d\u003e no format."},{"line_number":376,"context_line":"        self._wrapper.formats \u003d None"},{"line_number":377,"context_line":"        self.assertRaisesRegex(RuntimeError,"},{"line_number":378,"context_line":"                               \u0027Image format detection failed\u0027,"},{"line_number":379,"context_line":"                               convert.execute, \u0027file:///test/path.qcow\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"082c76fa_1906d9e5","line":376,"in_reply_to":"0176a80b_baed9184","updated":"2026-04-14 12:37:16.000000000","message":"Done","commit_id":"a66c71ee775954f003d3c60b4d2747bc7d948162"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"53d57688eaf9a8458135b5624a50fc72ce2f93e8","unresolved":true,"context_lines":[{"line_number":253,"context_line":"        iso_inspector \u003d self._make_inspector(\u0027iso\u0027)"},{"line_number":254,"context_line":"        qcow2_inspector \u003d self._make_inspector(\u0027qcow2\u0027)"},{"line_number":255,"context_line":"        self._wrapper.formats \u003d [iso_inspector, qcow2_inspector]"},{"line_number":256,"context_line":"        type(self._wrapper).format \u003d mock.PropertyMock("},{"line_number":257,"context_line":"            side_effect\u003dformat_inspector.ImageFormatError("},{"line_number":258,"context_line":"                \u0027Multiple formats detected\u0027))"},{"line_number":259,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"8ce2a989_e32d6601","line":256,"updated":"2026-05-05 18:45:08.000000000","message":"Isn\u0027t this modifying the class of the inspector? This should not be done as it could have side effects on further tests, among other things. Just mock the wrapper object.","commit_id":"3c0b9b980d71382b39f84890a3d791672444fdca"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"5212a8e7bceaa4cfedf18cb85edecaaee2a24ebe","unresolved":true,"context_lines":[{"line_number":253,"context_line":"        iso_inspector \u003d self._make_inspector(\u0027iso\u0027)"},{"line_number":254,"context_line":"        qcow2_inspector \u003d self._make_inspector(\u0027qcow2\u0027)"},{"line_number":255,"context_line":"        self._wrapper.formats \u003d [iso_inspector, qcow2_inspector]"},{"line_number":256,"context_line":"        type(self._wrapper).format \u003d mock.PropertyMock("},{"line_number":257,"context_line":"            side_effect\u003dformat_inspector.ImageFormatError("},{"line_number":258,"context_line":"                \u0027Multiple formats detected\u0027))"},{"line_number":259,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"fff70fb2_b4aa155d","line":256,"in_reply_to":"8ce2a989_e32d6601","updated":"2026-05-08 07:26:34.000000000","message":"Replaced the mock with a small FakeInspector class defined inside the helper a plain object.","commit_id":"3c0b9b980d71382b39f84890a3d791672444fdca"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"90c285337999b61e4efab453d9ca6a5e0f6efe5c","unresolved":false,"context_lines":[{"line_number":253,"context_line":"        iso_inspector \u003d self._make_inspector(\u0027iso\u0027)"},{"line_number":254,"context_line":"        qcow2_inspector \u003d self._make_inspector(\u0027qcow2\u0027)"},{"line_number":255,"context_line":"        self._wrapper.formats \u003d [iso_inspector, qcow2_inspector]"},{"line_number":256,"context_line":"        type(self._wrapper).format \u003d mock.PropertyMock("},{"line_number":257,"context_line":"            side_effect\u003dformat_inspector.ImageFormatError("},{"line_number":258,"context_line":"                \u0027Multiple formats detected\u0027))"},{"line_number":259,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3fbf802a_37294414","line":256,"in_reply_to":"fff70fb2_b4aa155d","updated":"2026-05-08 07:29:59.000000000","message":"now no type() mutation, no PropertyMock","commit_id":"3c0b9b980d71382b39f84890a3d791672444fdca"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"53d57688eaf9a8458135b5624a50fc72ce2f93e8","unresolved":true,"context_lines":[{"line_number":260,"context_line":"        e \u003d self.assertRaises("},{"line_number":261,"context_line":"            RuntimeError,"},{"line_number":262,"context_line":"            image_convert.execute, \u0027file:///test/path.iso\u0027)"},{"line_number":263,"context_line":"        self.assertEqual(\u0027Image format detection failed\u0027, str(e))"},{"line_number":264,"context_line":""},{"line_number":265,"context_line":"    def _setup_image_convert_info_fail(self, disk_format\u003d\u0027qcow2\u0027):"},{"line_number":266,"context_line":"        image_convert \u003d image_conversion._ConvertImage(self.context,"}],"source_content_type":"text/x-python","patch_set":5,"id":"f257e265_b141bfe3","line":263,"updated":"2026-05-05 18:45:08.000000000","message":"As noted in PS3, this still feels like it\u0027s adding two identical tests with different assertions. Would be better to add one setup thing and do the assertions in each test case, especially because it will make it clear what the differences are (iso+gpt and iso+qcow2).","commit_id":"3c0b9b980d71382b39f84890a3d791672444fdca"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"5212a8e7bceaa4cfedf18cb85edecaaee2a24ebe","unresolved":false,"context_lines":[{"line_number":260,"context_line":"        e \u003d self.assertRaises("},{"line_number":261,"context_line":"            RuntimeError,"},{"line_number":262,"context_line":"            image_convert.execute, \u0027file:///test/path.iso\u0027)"},{"line_number":263,"context_line":"        self.assertEqual(\u0027Image format detection failed\u0027, str(e))"},{"line_number":264,"context_line":""},{"line_number":265,"context_line":"    def _setup_image_convert_info_fail(self, disk_format\u003d\u0027qcow2\u0027):"},{"line_number":266,"context_line":"        image_convert \u003d image_conversion._ConvertImage(self.context,"}],"source_content_type":"text/x-python","patch_set":5,"id":"0430903e_4922b0de","line":263,"in_reply_to":"f257e265_b141bfe3","updated":"2026-05-08 07:26:34.000000000","message":"Done. Added the common setup  into _setup)iso_gpt_hybrid_test(formats) now ech test only specifies the format list and its own assertions.","commit_id":"3c0b9b980d71382b39f84890a3d791672444fdca"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"2231e84e59fe0630c4d580405a7270c67bd32be1","unresolved":true,"context_lines":[{"line_number":100,"context_line":"        self._wrapper \u003d mock.MagicMock()"},{"line_number":101,"context_line":"        self._wrapper.read.return_value \u003d b\u0027\u0027"},{"line_number":102,"context_line":"        self._wrapper.formats \u003d [self._inspector]"},{"line_number":103,"context_line":"        type(self._wrapper).format \u003d mock.PropertyMock("},{"line_number":104,"context_line":"            return_value\u003dself._inspector)"},{"line_number":105,"context_line":"        self._iw_patch \u003d self.useFixture(fixtures.MockPatch("},{"line_number":106,"context_line":"            \u0027glance.async_.flows.plugins.image_conversion.\u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"4ca5b589_f8218a19","line":103,"updated":"2026-05-08 16:50:17.000000000","message":"I must be missing something about why you think you need to do this `type()` thing to modify the class. Looks like you fixed some of the cases below but not this one. Why are you doing this?","commit_id":"6656b1831b379abfb17f9cf0745db56e1fb95f56"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"e81378add0b1de7bb324e52e2d327ed246bbca9b","unresolved":true,"context_lines":[{"line_number":100,"context_line":"        self._wrapper \u003d mock.MagicMock()"},{"line_number":101,"context_line":"        self._wrapper.read.return_value \u003d b\u0027\u0027"},{"line_number":102,"context_line":"        self._wrapper.formats \u003d [self._inspector]"},{"line_number":103,"context_line":"        type(self._wrapper).format \u003d mock.PropertyMock("},{"line_number":104,"context_line":"            return_value\u003dself._inspector)"},{"line_number":105,"context_line":"        self._iw_patch \u003d self.useFixture(fixtures.MockPatch("},{"line_number":106,"context_line":"            \u0027glance.async_.flows.plugins.image_conversion.\u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"b044cef0_772a8a2b","line":103,"in_reply_to":"4ca5b589_f8218a19","updated":"2026-05-11 09:35:34.000000000","message":"Yes I missed it. I used the `type()` approach becoz `format` is a `@property` on the real `InspectWrapper`, i tried setting it on the instance does not work correctly. I have now replaced those cases with a `_make_wrapper()` helper using a small fake class with a real `@property format`, which is much cleaner and easier to read.","commit_id":"6656b1831b379abfb17f9cf0745db56e1fb95f56"},{"author":{"_account_id":38762,"name":"Sahil Kumbhar","display_name":"sakumbha","email":"sakumbha@redhat.com","username":"sakumbha"},"change_message_id":"72fee27771fd32757c804f24febb094985235843","unresolved":false,"context_lines":[{"line_number":100,"context_line":"        self._wrapper \u003d mock.MagicMock()"},{"line_number":101,"context_line":"        self._wrapper.read.return_value \u003d b\u0027\u0027"},{"line_number":102,"context_line":"        self._wrapper.formats \u003d [self._inspector]"},{"line_number":103,"context_line":"        type(self._wrapper).format \u003d mock.PropertyMock("},{"line_number":104,"context_line":"            return_value\u003dself._inspector)"},{"line_number":105,"context_line":"        self._iw_patch \u003d self.useFixture(fixtures.MockPatch("},{"line_number":106,"context_line":"            \u0027glance.async_.flows.plugins.image_conversion.\u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"c109e924_7ae91919","line":103,"in_reply_to":"b044cef0_772a8a2b","updated":"2026-05-11 09:38:38.000000000","message":"Use FakeInspectorWrapper class to resolve type()","commit_id":"6656b1831b379abfb17f9cf0745db56e1fb95f56"}]}
