)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"5618876098b2ccaeab251d92137a1943dc744a59","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"e80a4c36_15e2a425","updated":"2026-03-18 17:32:53.000000000","message":"Failures are from parent. I have one suggestion inline but I think this is good otherwise.","commit_id":"e63513cda89648f802a972e8793fd377a11dbdb0"}],"oslo_utils/imageutils/cli.py":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"f585a0680845a0161113a97e7c75d0235659472e","unresolved":true,"context_lines":[{"line_number":89,"context_line":"    args \u003d parser.parse_args()"},{"line_number":90,"context_line":"    image \u003d args.image"},{"line_number":91,"context_line":"    verbose \u003d args.verbose"},{"line_number":92,"context_line":"    data \u003d {k: v for k, v in [arg.split(\u0027\u003d\u0027) for arg in args.data]}"},{"line_number":93,"context_line":"    if args.debug:"},{"line_number":94,"context_line":"        logging.getLogger().setLevel(logging.DEBUG)"},{"line_number":95,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"c1781859_db1ab340","line":92,"updated":"2026-02-26 21:20:19.000000000","message":"nit:\n\n```suggestion\n    data \u003d {k: v for k, v in [arg.split(\u0027\u003d\u0027, 1) for arg in args.data]}\n```\n\nIn case someone passes e.g. `x\u003dy\u003dz`.\n\nosc-lib has [`KeyValueAction`](https://github.com/openstack/osc-lib/blob/adeeb7214bf5abb9b5f72a1c7c82ea9eb8e0b25f/osc_lib/cli/parseractions.py#L27-L58) that could be worth copying here, though this is a developer tool so 🤷","commit_id":"a11f03b22367c9aae1cf4e82315716956e8f3f6b"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"0eb10bb1a59343a1fb902747445c20832bcd8bd6","unresolved":false,"context_lines":[{"line_number":89,"context_line":"    args \u003d parser.parse_args()"},{"line_number":90,"context_line":"    image \u003d args.image"},{"line_number":91,"context_line":"    verbose \u003d args.verbose"},{"line_number":92,"context_line":"    data \u003d {k: v for k, v in [arg.split(\u0027\u003d\u0027) for arg in args.data]}"},{"line_number":93,"context_line":"    if args.debug:"},{"line_number":94,"context_line":"        logging.getLogger().setLevel(logging.DEBUG)"},{"line_number":95,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"7aec3f39_297c62cb","line":92,"in_reply_to":"c1781859_db1ab340","updated":"2026-02-26 21:43:43.000000000","message":"Acknowledged","commit_id":"a11f03b22367c9aae1cf4e82315716956e8f3f6b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"5618876098b2ccaeab251d92137a1943dc744a59","unresolved":false,"context_lines":[{"line_number":89,"context_line":"    args \u003d parser.parse_args()"},{"line_number":90,"context_line":"    image \u003d args.image"},{"line_number":91,"context_line":"    verbose \u003d args.verbose"},{"line_number":92,"context_line":"    params \u003d {k: v for k, v in [arg.split(\u0027\u003d\u0027, 1) for arg in args.param]}"},{"line_number":93,"context_line":"    if args.debug:"},{"line_number":94,"context_line":"        logging.getLogger().setLevel(logging.DEBUG)"},{"line_number":95,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"9b81c414_e1df233b","line":92,"updated":"2026-03-18 17:32:53.000000000","message":"Note this will silently pass if the user forgets the value `\u003d`\n\n```\n\u003e\u003e\u003e \u0027test\u0027.split(\u0027\u003d\u0027, 1)\n[\u0027test\u0027]\n\u003e\u003e\u003e \u0027test\u0027.split(\u0027\u003d\u0027, 2)\n[\u0027test\u0027]\n```\n\nI think that\u0027s okay but jfyi","commit_id":"e63513cda89648f802a972e8793fd377a11dbdb0"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"378a379ae56cc098c97381fed35473fe2d44ab77","unresolved":false,"context_lines":[{"line_number":89,"context_line":"    args \u003d parser.parse_args()"},{"line_number":90,"context_line":"    image \u003d args.image"},{"line_number":91,"context_line":"    verbose \u003d args.verbose"},{"line_number":92,"context_line":"    params \u003d {k: v for k, v in [arg.split(\u0027\u003d\u0027, 1) for arg in args.param]}"},{"line_number":93,"context_line":"    if args.debug:"},{"line_number":94,"context_line":"        logging.getLogger().setLevel(logging.DEBUG)"},{"line_number":95,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"f76f14f3_f1d7e12e","line":92,"in_reply_to":"9b81c414_e1df233b","updated":"2026-03-18 20:31:20.000000000","message":"Yep.","commit_id":"e63513cda89648f802a972e8793fd377a11dbdb0"}],"oslo_utils/imageutils/format_inspector.py":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"8bdc15f1db8db57a0bfd32337a25a616db0a1917","unresolved":true,"context_lines":[{"line_number":249,"context_line":"    NAME \u003d \u0027\u0027"},{"line_number":250,"context_line":""},{"line_number":251,"context_line":"    def __init__("},{"line_number":252,"context_line":"        self, tracing: bool \u003d False, data: dict[str, str] | None \u003d None"},{"line_number":253,"context_line":"    ) -\u003e None:"},{"line_number":254,"context_line":"        self._total_count \u003d 0"},{"line_number":255,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"25a1e4b2_32605fdc","line":252,"range":{"start_line":252,"start_character":37,"end_line":252,"end_character":42},"updated":"2026-02-26 16:07:01.000000000","message":"I don\u0027t love the name here, so please, someone make some better suggestions.","commit_id":"a11f03b22367c9aae1cf4e82315716956e8f3f6b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"f585a0680845a0161113a97e7c75d0235659472e","unresolved":true,"context_lines":[{"line_number":249,"context_line":"    NAME \u003d \u0027\u0027"},{"line_number":250,"context_line":""},{"line_number":251,"context_line":"    def __init__("},{"line_number":252,"context_line":"        self, tracing: bool \u003d False, data: dict[str, str] | None \u003d None"},{"line_number":253,"context_line":"    ) -\u003e None:"},{"line_number":254,"context_line":"        self._total_count \u003d 0"},{"line_number":255,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"43627de3_c60a4056","line":252,"range":{"start_line":252,"start_character":37,"end_line":252,"end_character":42},"in_reply_to":"25a1e4b2_32605fdc","updated":"2026-02-26 21:20:19.000000000","message":"The only thing I see us storing/using in the next patch is `luks_passphrase`, and I don\u0027t think the inspector is pluggable meaning the list of other possible options is finite? Assuming so, any reason we couldn\u0027t just enumerate the parameters here (as kwarg-only parameters with format-relevant prefixes like `vhdx_*`, `qcow2_*`, `luks_*`) that get passed through the relevant inspector?\n\nIt would make building `self._inspectors` below slightly more challenging, but not excessively so (assuming we even need to keep the current loop as I only count 10 inspectors)","commit_id":"a11f03b22367c9aae1cf4e82315716956e8f3f6b"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"0eb10bb1a59343a1fb902747445c20832bcd8bd6","unresolved":true,"context_lines":[{"line_number":249,"context_line":"    NAME \u003d \u0027\u0027"},{"line_number":250,"context_line":""},{"line_number":251,"context_line":"    def __init__("},{"line_number":252,"context_line":"        self, tracing: bool \u003d False, data: dict[str, str] | None \u003d None"},{"line_number":253,"context_line":"    ) -\u003e None:"},{"line_number":254,"context_line":"        self._total_count \u003d 0"},{"line_number":255,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"d0aa154a_09a7cbee","line":252,"range":{"start_line":252,"start_character":37,"end_line":252,"end_character":42},"in_reply_to":"43627de3_c60a4056","updated":"2026-02-26 21:43:43.000000000","message":"I think this needs to be extensible because we may need to pass cipher stuff, key slot things, LUKSv2 may bring more fun, etc. It also needs to be reasonably generic I think so it can pass through the generic interfaces (detect and InspectWrapper). And, even though I\u0027m not doing it yet, probably needs to pass to the inner wrapper for things like LUKS does, in case there were qcow2/gpt things that need to be passed to the second-level inspector. And, nova had an inspector implementation subclassed from the base here that wasn\u0027t in oslo for a time. Even though it\u0027s not a loadable pluggable interface, I don\u0027t think I want to make doing that any harder.","commit_id":"a11f03b22367c9aae1cf4e82315716956e8f3f6b"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"14221d9ae8f0ec1b1fc5f7e3d084265a52b1714d","unresolved":false,"context_lines":[{"line_number":249,"context_line":"    NAME \u003d \u0027\u0027"},{"line_number":250,"context_line":""},{"line_number":251,"context_line":"    def __init__("},{"line_number":252,"context_line":"        self, tracing: bool \u003d False, data: dict[str, str] | None \u003d None"},{"line_number":253,"context_line":"    ) -\u003e None:"},{"line_number":254,"context_line":"        self._total_count \u003d 0"},{"line_number":255,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"196a341b_3ad432cc","line":252,"range":{"start_line":252,"start_character":37,"end_line":252,"end_character":42},"in_reply_to":"79c759cf_51b9a812","updated":"2026-03-18 14:50:03.000000000","message":"Done","commit_id":"a11f03b22367c9aae1cf4e82315716956e8f3f6b"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"695113b5a41fb45aa961d506dde8f55f3703c04b","unresolved":true,"context_lines":[{"line_number":249,"context_line":"    NAME \u003d \u0027\u0027"},{"line_number":250,"context_line":""},{"line_number":251,"context_line":"    def __init__("},{"line_number":252,"context_line":"        self, tracing: bool \u003d False, data: dict[str, str] | None \u003d None"},{"line_number":253,"context_line":"    ) -\u003e None:"},{"line_number":254,"context_line":"        self._total_count \u003d 0"},{"line_number":255,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"79c759cf_51b9a812","line":252,"range":{"start_line":252,"start_character":37,"end_line":252,"end_character":42},"in_reply_to":"8dd2d85c_4e3c416b","updated":"2026-03-10 15:42:58.000000000","message":"params or options sounds better.\n\nFor command line argument probably it could be named with inspector_ prefix but for this specific interface of Inspector class I find the prefix redundant. (So I prefer params to inspector_params)","commit_id":"a11f03b22367c9aae1cf4e82315716956e8f3f6b"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"653dac976b52ec3140ae172530f5d4f5613d4414","unresolved":true,"context_lines":[{"line_number":249,"context_line":"    NAME \u003d \u0027\u0027"},{"line_number":250,"context_line":""},{"line_number":251,"context_line":"    def __init__("},{"line_number":252,"context_line":"        self, tracing: bool \u003d False, data: dict[str, str] | None \u003d None"},{"line_number":253,"context_line":"    ) -\u003e None:"},{"line_number":254,"context_line":"        self._total_count \u003d 0"},{"line_number":255,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"8dd2d85c_4e3c416b","line":252,"range":{"start_line":252,"start_character":37,"end_line":252,"end_character":42},"in_reply_to":"d0aa154a_09a7cbee","updated":"2026-03-10 13:47:53.000000000","message":"We discussed this more on IRC. Nova also provides its own inspectors so this is in fact vaguely pluggable. This being the case, a dict is probably as good as we can get.\n\nwrt naming, maybe `inspector_params`? Or just `params`? We could also consider typing this as a `TypedDict`:\n\n```\nclass InspectorParams(TypedDict, total\u003dFalse):\n    luks_passphrase: str\n```\n\nWhich we could use like so:\n\n```suggestion\n        self,\n        tracing: bool \u003d False,\n        inspector_params: InspectorParams | None \u003d None,\n```\n\nThis would require `type: ignore[typeddict-unknown-key]` if we wanted to pass custom parameters for \"extensions\". idk if that\u0027s likely to happen or not. [PEP-728](https://peps.python.org/pep-0728/) adds an `additional_items` parameter to typed dict but mypy doesn\u0027t seem to support this yet and we\u0027d need to import from `typing_extensions` instead of `typing`.","commit_id":"a11f03b22367c9aae1cf4e82315716956e8f3f6b"}],"oslo_utils/tests/imageutils/test_format_inspector.py":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"5618876098b2ccaeab251d92137a1943dc744a59","unresolved":true,"context_lines":[{"line_number":1041,"context_line":"        self.assertIsNotNone(inspector)"},{"line_number":1042,"context_line":"        # This makes sure we passed the \"data\" through detect, InspectWrapper,"},{"line_number":1043,"context_line":"        # and to the actual inspector objects themselves."},{"line_number":1044,"context_line":"        if inspector is not None:"},{"line_number":1045,"context_line":"            # Thanks mypy *eyeroll*"},{"line_number":1046,"context_line":"            self.assertEqual(\u0027bar\u0027, inspector._params[\u0027foo\u0027])"},{"line_number":1047,"context_line":""},{"line_number":1048,"context_line":""},{"line_number":1049,"context_line":"class TestFormatInspectorInfra(test_base.BaseTestCase):"}],"source_content_type":"text/x-python","patch_set":2,"id":"f8aa182e_37b48e84","line":1046,"range":{"start_line":1044,"start_character":0,"end_line":1046,"end_character":61},"updated":"2026-03-18 17:32:53.000000000","message":"Yeah, it\u0027s dumb 😞 Type checkers currently special case `isinstance` and both [`TypeGuard` or `TypeIs`](https://mypy.readthedocs.io/en/latest/type_narrowing.html#typeis-vs-typeguard) narrow via return value, not a strict assertion. I usually just stick a duplicate `assert` in here\n\n```suggestion\n        assert inspector is not None\n        self.assertEqual(\u0027bar\u0027, inspector._params[\u0027foo\u0027])\n```","commit_id":"e63513cda89648f802a972e8793fd377a11dbdb0"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"57a25e4ee940a6b82e8bf6e8c8c746d8cf24f688","unresolved":false,"context_lines":[{"line_number":1041,"context_line":"        self.assertIsNotNone(inspector)"},{"line_number":1042,"context_line":"        # This makes sure we passed the \"data\" through detect, InspectWrapper,"},{"line_number":1043,"context_line":"        # and to the actual inspector objects themselves."},{"line_number":1044,"context_line":"        if inspector is not None:"},{"line_number":1045,"context_line":"            # Thanks mypy *eyeroll*"},{"line_number":1046,"context_line":"            self.assertEqual(\u0027bar\u0027, inspector._params[\u0027foo\u0027])"},{"line_number":1047,"context_line":""},{"line_number":1048,"context_line":""},{"line_number":1049,"context_line":"class TestFormatInspectorInfra(test_base.BaseTestCase):"}],"source_content_type":"text/x-python","patch_set":2,"id":"98e30f41_eb87abd6","line":1046,"range":{"start_line":1044,"start_character":0,"end_line":1046,"end_character":61},"in_reply_to":"5213a0b1_52113a54","updated":"2026-03-19 10:55:19.000000000","message":"The main advantage I see if that you don\u0027t branch so it\u0027s a slightly easier flow to follow. The `if` conditional suggests an implicit else that in practice will/can never be reached. Much of muchness though, yeah.","commit_id":"e63513cda89648f802a972e8793fd377a11dbdb0"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"378a379ae56cc098c97381fed35473fe2d44ab77","unresolved":false,"context_lines":[{"line_number":1041,"context_line":"        self.assertIsNotNone(inspector)"},{"line_number":1042,"context_line":"        # This makes sure we passed the \"data\" through detect, InspectWrapper,"},{"line_number":1043,"context_line":"        # and to the actual inspector objects themselves."},{"line_number":1044,"context_line":"        if inspector is not None:"},{"line_number":1045,"context_line":"            # Thanks mypy *eyeroll*"},{"line_number":1046,"context_line":"            self.assertEqual(\u0027bar\u0027, inspector._params[\u0027foo\u0027])"},{"line_number":1047,"context_line":""},{"line_number":1048,"context_line":""},{"line_number":1049,"context_line":"class TestFormatInspectorInfra(test_base.BaseTestCase):"}],"source_content_type":"text/x-python","patch_set":2,"id":"5213a0b1_52113a54","line":1046,"range":{"start_line":1044,"start_character":0,"end_line":1046,"end_character":61},"in_reply_to":"f8aa182e_37b48e84","updated":"2026-03-18 20:31:20.000000000","message":"Okay, I\u0027m not sure it\u0027s much different, but if that\u0027s the pattern used elsewhere here then fine.","commit_id":"e63513cda89648f802a972e8793fd377a11dbdb0"}]}
