)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"a62f6fd785b494eacae47c3d2685dc8c38363dcf","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"86b3243b_1837edbe","updated":"2025-09-09 21:29:14.000000000","message":"This one needs a good deal more work, I\u0027m afraid. It\u0027s a lot more complicated than I feel it needs to be","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"7a22b297d1071a507648da6e240bca06cb6510c0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"2fef2a8b_a6c8efcf","updated":"2025-11-12 12:08:52.000000000","message":"Also, when you address a comment, can you please mark it as \"Done\" or resolved?","commit_id":"10aeceaf1e04666061682e171303146d5c5e6dcd"}],"openstackclient/tests/functional/image/v2/test_image.py":[{"author":{"_account_id":35119,"name":"jihyun huh","email":"huhji.elha@gmail.com","username":"jhhuh"},"change_message_id":"8dfb83f75882a7cc85f198e44ec61ae1f1f61eda","unresolved":true,"context_lines":[{"line_number":272,"context_line":"        #     )"},{"line_number":273,"context_line":""},{"line_number":274,"context_line":"    # functional test for \u0027openstack image stores info\u0027"},{"line_number":275,"context_line":"    def test_image_stores_info(self):"},{"line_number":276,"context_line":"        def _multistore_disabled(msg: str) -\u003e bool:"},{"line_number":277,"context_line":"            markers \u003d ["},{"line_number":278,"context_line":"                \u0027Multi Backend support not enabled\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"c8d6e976_a31c64e1","line":275,"updated":"2025-08-30 07:25:40.000000000","message":"You need to separate the functional test file as `openstack/tests/functional/image/v2/test_service_info.py`.\nEvery feature has its own file, and you can compare the same feature with the following paths.\n- `openstack/image/v2/service_info.py`\n- `openstack/tests/unit/image/v2/test_service_info.py`","commit_id":"893dde6038d603ca9b8c099eabb09687bb3819be"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"a62f6fd785b494eacae47c3d2685dc8c38363dcf","unresolved":false,"context_lines":[{"line_number":272,"context_line":"        #     )"},{"line_number":273,"context_line":""},{"line_number":274,"context_line":"    # functional test for \u0027openstack image stores info\u0027"},{"line_number":275,"context_line":"    def test_image_stores_info(self):"},{"line_number":276,"context_line":"        def _multistore_disabled(msg: str) -\u003e bool:"},{"line_number":277,"context_line":"            markers \u003d ["},{"line_number":278,"context_line":"                \u0027Multi Backend support not enabled\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"d7f01ffc_ccba566a","line":275,"in_reply_to":"c8d6e976_a31c64e1","updated":"2025-09-09 21:29:14.000000000","message":"Done","commit_id":"893dde6038d603ca9b8c099eabb09687bb3819be"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"a62f6fd785b494eacae47c3d2685dc8c38363dcf","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":5,"id":"5d0e2634_fbc9ebcc","line":271,"range":{"start_line":257,"start_character":0,"end_line":271,"end_character":1},"updated":"2025-09-09 21:29:14.000000000","message":"Can you remove this rather than leaving it here commented out","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"9c46b46d4fbc1fe3cc3bd3a09a840b10b9a94774","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":5,"id":"9112b724_f65d9f95","line":271,"range":{"start_line":257,"start_character":0,"end_line":271,"end_character":1},"in_reply_to":"5d0e2634_fbc9ebcc","updated":"2025-09-25 10:34:57.000000000","message":"Comment still applies.","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"efa7f5f854887bb948ff3226d07848923722bb91","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":5,"id":"abafe0a8_412bd643","line":271,"range":{"start_line":257,"start_character":0,"end_line":271,"end_character":1},"in_reply_to":"9112b724_f65d9f95","updated":"2025-11-12 12:08:27.000000000","message":"...and it still applies 😅","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"}],"openstackclient/tests/functional/image/v2/test_service_info.py":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"a62f6fd785b494eacae47c3d2685dc8c38363dcf","unresolved":true,"context_lines":[{"line_number":17,"context_line":"class ImageServiceInfoTests(base.BaseImageTests):"},{"line_number":18,"context_line":"    \"\"\"Functional tests for image service info commands\"\"\""},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"    # functional test for \u0027openstack image stores info\u0027"},{"line_number":21,"context_line":"    def test_image_stores_info(self):"},{"line_number":22,"context_line":"        \"\"\"Test \u0027image stores info\u0027 with fallback and skip logic.\"\"\""},{"line_number":23,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"0dbbb86e_dbb35046","line":20,"updated":"2025-09-09 21:29:14.000000000","message":"Can you remove  these comments: they don\u0027t tell us anything the function name doesn\u0027t already say.","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"9c46b46d4fbc1fe3cc3bd3a09a840b10b9a94774","unresolved":false,"context_lines":[{"line_number":17,"context_line":"class ImageServiceInfoTests(base.BaseImageTests):"},{"line_number":18,"context_line":"    \"\"\"Functional tests for image service info commands\"\"\""},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"    # functional test for \u0027openstack image stores info\u0027"},{"line_number":21,"context_line":"    def test_image_stores_info(self):"},{"line_number":22,"context_line":"        \"\"\"Test \u0027image stores info\u0027 with fallback and skip logic.\"\"\""},{"line_number":23,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"97ff6170_f02a1172","line":20,"in_reply_to":"0dbbb86e_dbb35046","updated":"2025-09-25 10:34:57.000000000","message":"Done","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"a62f6fd785b494eacae47c3d2685dc8c38363dcf","unresolved":true,"context_lines":[{"line_number":24,"context_line":"        def _multistore_disabled(msg: str) -\u003e bool:"},{"line_number":25,"context_line":"            markers \u003d ["},{"line_number":26,"context_line":"                \u0027Multi Backend support not enabled\u0027,"},{"line_number":27,"context_line":"                \u0027Multi store is not enabled\u0027,"},{"line_number":28,"context_line":"                \u0027Unknown command\u0027,"},{"line_number":29,"context_line":"                \u0027No such command \"stores\"\u0027,"},{"line_number":30,"context_line":"                \u0027404\u0027,"},{"line_number":31,"context_line":"            ]"},{"line_number":32,"context_line":"            return any(m in (msg or \u0027\u0027) for m in markers)"}],"source_content_type":"text/x-python","patch_set":5,"id":"61ec30f1_e9efcfc6","line":29,"range":{"start_line":27,"start_character":45,"end_line":29,"end_character":43},"updated":"2025-09-09 21:29:14.000000000","message":"I don\u0027t believe either of these should happen when the functional tests are running against the code in-tree (which they always will). Can you remove them?","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"9c46b46d4fbc1fe3cc3bd3a09a840b10b9a94774","unresolved":false,"context_lines":[{"line_number":24,"context_line":"        def _multistore_disabled(msg: str) -\u003e bool:"},{"line_number":25,"context_line":"            markers \u003d ["},{"line_number":26,"context_line":"                \u0027Multi Backend support not enabled\u0027,"},{"line_number":27,"context_line":"                \u0027Multi store is not enabled\u0027,"},{"line_number":28,"context_line":"                \u0027Unknown command\u0027,"},{"line_number":29,"context_line":"                \u0027No such command \"stores\"\u0027,"},{"line_number":30,"context_line":"                \u0027404\u0027,"},{"line_number":31,"context_line":"            ]"},{"line_number":32,"context_line":"            return any(m in (msg or \u0027\u0027) for m in markers)"}],"source_content_type":"text/x-python","patch_set":5,"id":"1c528b26_97bbee90","line":29,"range":{"start_line":27,"start_character":45,"end_line":29,"end_character":43},"in_reply_to":"61ec30f1_e9efcfc6","updated":"2025-09-25 10:34:57.000000000","message":"Done","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"a62f6fd785b494eacae47c3d2685dc8c38363dcf","unresolved":true,"context_lines":[{"line_number":43,"context_line":"                )"},{"line_number":44,"context_line":"            out \u003d None"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"        rows \u003d None"},{"line_number":47,"context_line":"        if isinstance(out, list):"},{"line_number":48,"context_line":"            rows \u003d out"},{"line_number":49,"context_line":"        elif isinstance(out, dict) and \u0027stores\u0027 in out:"},{"line_number":50,"context_line":"            rows \u003d out[\u0027stores\u0027]"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        if rows is None:"},{"line_number":53,"context_line":"            try:"},{"line_number":54,"context_line":"                out \u003d self.openstack("}],"source_content_type":"text/x-python","patch_set":5,"id":"e954e7b1_5a914c39","line":51,"range":{"start_line":46,"start_character":0,"end_line":51,"end_character":1},"updated":"2025-09-09 21:29:14.000000000","message":"This shouldn\u0027t be necessary. Can you explain why it is?","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"9c46b46d4fbc1fe3cc3bd3a09a840b10b9a94774","unresolved":false,"context_lines":[{"line_number":43,"context_line":"                )"},{"line_number":44,"context_line":"            out \u003d None"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"        rows \u003d None"},{"line_number":47,"context_line":"        if isinstance(out, list):"},{"line_number":48,"context_line":"            rows \u003d out"},{"line_number":49,"context_line":"        elif isinstance(out, dict) and \u0027stores\u0027 in out:"},{"line_number":50,"context_line":"            rows \u003d out[\u0027stores\u0027]"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        if rows is None:"},{"line_number":53,"context_line":"            try:"},{"line_number":54,"context_line":"                out \u003d self.openstack("}],"source_content_type":"text/x-python","patch_set":5,"id":"81fda487_54a978c2","line":51,"range":{"start_line":46,"start_character":0,"end_line":51,"end_character":1},"in_reply_to":"e954e7b1_5a914c39","updated":"2025-09-25 10:34:57.000000000","message":"Done","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"a62f6fd785b494eacae47c3d2685dc8c38363dcf","unresolved":true,"context_lines":[{"line_number":79,"context_line":"    # functional test for \u0027openstack image import info\u0027"},{"line_number":80,"context_line":"    def test_image_import_info(self):"},{"line_number":81,"context_line":"        \"\"\"Test \u0027image import info\u0027 with multiple format handlers.\"\"\""},{"line_number":82,"context_line":"        try:"},{"line_number":83,"context_line":"            out \u003d self.openstack("},{"line_number":84,"context_line":"                \u0027image import info -f json\u0027, parse_output\u003dTrue"},{"line_number":85,"context_line":"            )"},{"line_number":86,"context_line":"        except exceptions.CommandFailed:"},{"line_number":87,"context_line":"            txt \u003d self.openstack(\u0027image import info\u0027)"},{"line_number":88,"context_line":"            self.assertTrue("},{"line_number":89,"context_line":"                any("}],"source_content_type":"text/x-python","patch_set":5,"id":"1b742f4f_e347c8a6","line":86,"range":{"start_line":82,"start_character":12,"end_line":86,"end_character":40},"updated":"2025-09-09 21:29:14.000000000","message":"Why will this fail, and why is it okay to try again without `-f json`? If you see a problem here on `master`, you\u0027ve likely hit a bug.","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"9c46b46d4fbc1fe3cc3bd3a09a840b10b9a94774","unresolved":false,"context_lines":[{"line_number":79,"context_line":"    # functional test for \u0027openstack image import info\u0027"},{"line_number":80,"context_line":"    def test_image_import_info(self):"},{"line_number":81,"context_line":"        \"\"\"Test \u0027image import info\u0027 with multiple format handlers.\"\"\""},{"line_number":82,"context_line":"        try:"},{"line_number":83,"context_line":"            out \u003d self.openstack("},{"line_number":84,"context_line":"                \u0027image import info -f json\u0027, parse_output\u003dTrue"},{"line_number":85,"context_line":"            )"},{"line_number":86,"context_line":"        except exceptions.CommandFailed:"},{"line_number":87,"context_line":"            txt \u003d self.openstack(\u0027image import info\u0027)"},{"line_number":88,"context_line":"            self.assertTrue("},{"line_number":89,"context_line":"                any("}],"source_content_type":"text/x-python","patch_set":5,"id":"68b0fc72_df6f6559","line":86,"range":{"start_line":82,"start_character":12,"end_line":86,"end_character":40},"in_reply_to":"1b742f4f_e347c8a6","updated":"2025-09-25 10:34:57.000000000","message":"Done","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"a62f6fd785b494eacae47c3d2685dc8c38363dcf","unresolved":true,"context_lines":[{"line_number":94,"context_line":"            )"},{"line_number":95,"context_line":"            return"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"        methods \u003d None"},{"line_number":98,"context_line":"        if isinstance(out, dict) and \u0027import-methods\u0027 in out:"},{"line_number":99,"context_line":"            payload \u003d out[\u0027import-methods\u0027]"},{"line_number":100,"context_line":"            if isinstance(payload, dict):"},{"line_number":101,"context_line":"                methods \u003d ("},{"line_number":102,"context_line":"                    payload.get(\u0027value\u0027)"},{"line_number":103,"context_line":"                    or payload.get(\u0027values\u0027)"},{"line_number":104,"context_line":"                    or payload.get(\u0027methods\u0027)"},{"line_number":105,"context_line":"                    or payload.get(\u0027supported\u0027)"},{"line_number":106,"context_line":"                )"},{"line_number":107,"context_line":"            elif isinstance(payload, list | tuple | set):"},{"line_number":108,"context_line":"                methods \u003d payload"},{"line_number":109,"context_line":"        elif isinstance(out, list | tuple | set):"},{"line_number":110,"context_line":"            methods \u003d out"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"        self.assertIsNotNone("},{"line_number":113,"context_line":"            methods, f\"Couldn\u0027t find methods in output: {out}\""}],"source_content_type":"text/x-python","patch_set":5,"id":"18881680_c036607d","line":110,"range":{"start_line":97,"start_character":22,"end_line":110,"end_character":25},"updated":"2025-09-09 21:29:14.000000000","message":"Same comment as above: under what circumstances is this complicated logic needed? It should never be needed.","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"9c46b46d4fbc1fe3cc3bd3a09a840b10b9a94774","unresolved":false,"context_lines":[{"line_number":94,"context_line":"            )"},{"line_number":95,"context_line":"            return"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"        methods \u003d None"},{"line_number":98,"context_line":"        if isinstance(out, dict) and \u0027import-methods\u0027 in out:"},{"line_number":99,"context_line":"            payload \u003d out[\u0027import-methods\u0027]"},{"line_number":100,"context_line":"            if isinstance(payload, dict):"},{"line_number":101,"context_line":"                methods \u003d ("},{"line_number":102,"context_line":"                    payload.get(\u0027value\u0027)"},{"line_number":103,"context_line":"                    or payload.get(\u0027values\u0027)"},{"line_number":104,"context_line":"                    or payload.get(\u0027methods\u0027)"},{"line_number":105,"context_line":"                    or payload.get(\u0027supported\u0027)"},{"line_number":106,"context_line":"                )"},{"line_number":107,"context_line":"            elif isinstance(payload, list | tuple | set):"},{"line_number":108,"context_line":"                methods \u003d payload"},{"line_number":109,"context_line":"        elif isinstance(out, list | tuple | set):"},{"line_number":110,"context_line":"            methods \u003d out"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"        self.assertIsNotNone("},{"line_number":113,"context_line":"            methods, f\"Couldn\u0027t find methods in output: {out}\""}],"source_content_type":"text/x-python","patch_set":5,"id":"79d80ffd_ce97a234","line":110,"range":{"start_line":97,"start_character":22,"end_line":110,"end_character":25},"in_reply_to":"18881680_c036607d","updated":"2025-09-25 10:34:57.000000000","message":"Done","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"a62f6fd785b494eacae47c3d2685dc8c38363dcf","unresolved":true,"context_lines":[{"line_number":111,"context_line":""},{"line_number":112,"context_line":"        self.assertIsNotNone("},{"line_number":113,"context_line":"            methods, f\"Couldn\u0027t find methods in output: {out}\""},{"line_number":114,"context_line":"        )"},{"line_number":115,"context_line":"        if isinstance(methods, list | tuple | set):"},{"line_number":116,"context_line":"            self.assertGreater(len(methods), 0, \u0027No import methods reported\u0027)"},{"line_number":117,"context_line":"        else:"},{"line_number":118,"context_line":"            self.assertTrue(str(methods).strip(), \u0027Empty import methods\u0027)"}],"source_content_type":"text/x-python","patch_set":5,"id":"a93c751c_c6e0b353","line":115,"range":{"start_line":114,"start_character":9,"end_line":115,"end_character":51},"updated":"2025-09-09 21:29:14.000000000","message":"We should be able to know the return type of this. Can you settle on one of these?","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"9c46b46d4fbc1fe3cc3bd3a09a840b10b9a94774","unresolved":false,"context_lines":[{"line_number":111,"context_line":""},{"line_number":112,"context_line":"        self.assertIsNotNone("},{"line_number":113,"context_line":"            methods, f\"Couldn\u0027t find methods in output: {out}\""},{"line_number":114,"context_line":"        )"},{"line_number":115,"context_line":"        if isinstance(methods, list | tuple | set):"},{"line_number":116,"context_line":"            self.assertGreater(len(methods), 0, \u0027No import methods reported\u0027)"},{"line_number":117,"context_line":"        else:"},{"line_number":118,"context_line":"            self.assertTrue(str(methods).strip(), \u0027Empty import methods\u0027)"}],"source_content_type":"text/x-python","patch_set":5,"id":"5f42defb_6cb6c339","line":115,"range":{"start_line":114,"start_character":9,"end_line":115,"end_character":51},"in_reply_to":"a93c751c_c6e0b353","updated":"2025-09-25 10:34:57.000000000","message":"Done","commit_id":"9e1b2108d15a4172ec106bbcfee36a5f9630c1da"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"9c46b46d4fbc1fe3cc3bd3a09a840b10b9a94774","unresolved":true,"context_lines":[{"line_number":28,"context_line":"            ]"},{"line_number":29,"context_line":"            return any(m in (msg or \u0027\u0027) for m in markers)"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"        try:"},{"line_number":32,"context_line":"            out \u003d self.openstack("},{"line_number":33,"context_line":"                \u0027image stores info -f json\u0027, parse_output\u003dTrue"},{"line_number":34,"context_line":"            )"},{"line_number":35,"context_line":"        except exceptions.CommandFailed as e:"},{"line_number":36,"context_line":"            err \u003d str(e.stderr or \u0027\u0027)"},{"line_number":37,"context_line":"            if _multistore_disabled(err):"}],"source_content_type":"text/x-python","patch_set":10,"id":"178bee88_54778210","line":34,"range":{"start_line":31,"start_character":12,"end_line":34,"end_character":13},"updated":"2025-09-25 10:34:57.000000000","message":"The `-f json` is redundant since it is automatically appended when you set `parse_output\u003dTrue`\n\n```suggestion\n        try:\n            out \u003d self.openstack(\u0027image stores info\u0027, parse_output\u003dTrue)\n```","commit_id":"ca4a8c6a76a5afacd6403341f9f4420983c5ff52"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"efa7f5f854887bb948ff3226d07848923722bb91","unresolved":false,"context_lines":[{"line_number":28,"context_line":"            ]"},{"line_number":29,"context_line":"            return any(m in (msg or \u0027\u0027) for m in markers)"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"        try:"},{"line_number":32,"context_line":"            out \u003d self.openstack("},{"line_number":33,"context_line":"                \u0027image stores info -f json\u0027, parse_output\u003dTrue"},{"line_number":34,"context_line":"            )"},{"line_number":35,"context_line":"        except exceptions.CommandFailed as e:"},{"line_number":36,"context_line":"            err \u003d str(e.stderr or \u0027\u0027)"},{"line_number":37,"context_line":"            if _multistore_disabled(err):"}],"source_content_type":"text/x-python","patch_set":10,"id":"a1712981_2ba8b2b8","line":34,"range":{"start_line":31,"start_character":12,"end_line":34,"end_character":13},"in_reply_to":"178bee88_54778210","updated":"2025-11-12 12:08:27.000000000","message":"Done","commit_id":"ca4a8c6a76a5afacd6403341f9f4420983c5ff52"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"9c46b46d4fbc1fe3cc3bd3a09a840b10b9a94774","unresolved":true,"context_lines":[{"line_number":38,"context_line":"                self.skipTest("},{"line_number":39,"context_line":"                    \u0027Glance multi-store not enabled in this environment\u0027"},{"line_number":40,"context_line":"                )"},{"line_number":41,"context_line":"            out \u003d None"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"        rows \u003d out.get(\u0027stores\u0027) if out else None"},{"line_number":44,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"258a0981_f27ca1c1","line":41,"updated":"2025-09-25 10:34:57.000000000","message":"What other reasons might this fail? Shouldn\u0027t we raise here instead? If we did, we could maybe simplify other calls below?","commit_id":"ca4a8c6a76a5afacd6403341f9f4420983c5ff52"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"efa7f5f854887bb948ff3226d07848923722bb91","unresolved":false,"context_lines":[{"line_number":38,"context_line":"                self.skipTest("},{"line_number":39,"context_line":"                    \u0027Glance multi-store not enabled in this environment\u0027"},{"line_number":40,"context_line":"                )"},{"line_number":41,"context_line":"            out \u003d None"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"        rows \u003d out.get(\u0027stores\u0027) if out else None"},{"line_number":44,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"b77b6b7e_f9041afc","line":41,"in_reply_to":"258a0981_f27ca1c1","updated":"2025-11-12 12:08:27.000000000","message":"Done","commit_id":"ca4a8c6a76a5afacd6403341f9f4420983c5ff52"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"9c46b46d4fbc1fe3cc3bd3a09a840b10b9a94774","unresolved":true,"context_lines":[{"line_number":49,"context_line":"                )"},{"line_number":50,"context_line":"                rows \u003d out if isinstance(out, list) else out.get(\u0027stores\u0027)"},{"line_number":51,"context_line":"            except exceptions.CommandFailed as e:"},{"line_number":52,"context_line":"                err \u003d str(e.stderr or \u0027\u0027)"},{"line_number":53,"context_line":"                if _multistore_disabled(err):"},{"line_number":54,"context_line":"                    self.skipTest("},{"line_number":55,"context_line":"                        \u0027Glance multi-store not enabled in this environment\u0027"},{"line_number":56,"context_line":"                    )"},{"line_number":57,"context_line":"                raise"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"        self.assertIsInstance(rows, list)"}],"source_content_type":"text/x-python","patch_set":10,"id":"b4e8d8a3_27919096","line":56,"range":{"start_line":52,"start_character":41,"end_line":56,"end_character":21},"updated":"2025-09-25 10:34:57.000000000","message":"You already checked this above. Is it necessary to check again?","commit_id":"ca4a8c6a76a5afacd6403341f9f4420983c5ff52"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"efa7f5f854887bb948ff3226d07848923722bb91","unresolved":false,"context_lines":[{"line_number":49,"context_line":"                )"},{"line_number":50,"context_line":"                rows \u003d out if isinstance(out, list) else out.get(\u0027stores\u0027)"},{"line_number":51,"context_line":"            except exceptions.CommandFailed as e:"},{"line_number":52,"context_line":"                err \u003d str(e.stderr or \u0027\u0027)"},{"line_number":53,"context_line":"                if _multistore_disabled(err):"},{"line_number":54,"context_line":"                    self.skipTest("},{"line_number":55,"context_line":"                        \u0027Glance multi-store not enabled in this environment\u0027"},{"line_number":56,"context_line":"                    )"},{"line_number":57,"context_line":"                raise"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"        self.assertIsInstance(rows, list)"}],"source_content_type":"text/x-python","patch_set":10,"id":"0976f52d_d188a611","line":56,"range":{"start_line":52,"start_character":41,"end_line":56,"end_character":21},"in_reply_to":"b4e8d8a3_27919096","updated":"2025-11-12 12:08:27.000000000","message":"Done","commit_id":"ca4a8c6a76a5afacd6403341f9f4420983c5ff52"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"efa7f5f854887bb948ff3226d07848923722bb91","unresolved":true,"context_lines":[{"line_number":27,"context_line":"            )"},{"line_number":28,"context_line":"        except exceptions.CommandFailed as e:"},{"line_number":29,"context_line":"            err \u003d str(e.stderr or \u0027\u0027)"},{"line_number":30,"context_line":"            out_err \u003d str(e.stdout or \u0027\u0027)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"            if \"is not an openstack command\" in out_err:"},{"line_number":33,"context_line":"                self.skipTest("},{"line_number":34,"context_line":"                    \"image stores info command is not available in this OSC version\""},{"line_number":35,"context_line":"                )"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"            # If the command fails because Glance doesn\u0027t support the feature,"},{"line_number":38,"context_line":"            # we skip the test. Otherwise, we let it raise to signal a true failure."}],"source_content_type":"text/x-python","patch_set":14,"id":"f1f7be1f_eb6faa28","line":35,"range":{"start_line":30,"start_character":41,"end_line":35,"end_character":17},"updated":"2025-11-12 12:08:27.000000000","message":"This will never happen: the functional tests run against the current version of OSC, and the current version of OSC has this command. You can drop this.","commit_id":"10aeceaf1e04666061682e171303146d5c5e6dcd"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"efa7f5f854887bb948ff3226d07848923722bb91","unresolved":true,"context_lines":[{"line_number":36,"context_line":""},{"line_number":37,"context_line":"            # If the command fails because Glance doesn\u0027t support the feature,"},{"line_number":38,"context_line":"            # we skip the test. Otherwise, we let it raise to signal a true failure."},{"line_number":39,"context_line":"            markers \u003d ("},{"line_number":40,"context_line":"                \"The server could not comply with the request since it is \""},{"line_number":41,"context_line":"                \"not able to service it\","},{"line_number":42,"context_line":"                \"Internal Server Error: The server has either erred or is \""},{"line_number":43,"context_line":"                \"incapable of performing the requested operation\","},{"line_number":44,"context_line":"            )"},{"line_number":45,"context_line":"            if any(m in err for m in markers):"},{"line_number":46,"context_line":"                self.skipTest("}],"source_content_type":"text/x-python","patch_set":14,"id":"0364e515_cec85d93","line":43,"range":{"start_line":39,"start_character":23,"end_line":43,"end_character":66},"updated":"2025-11-12 12:08:27.000000000","message":"Where do these strings come from? Are you able to reproduce this in a local environment? If so, I think you could make this better by modifying the command to catch the `BadRequest` error directly and looking for the string.","commit_id":"10aeceaf1e04666061682e171303146d5c5e6dcd"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"efa7f5f854887bb948ff3226d07848923722bb91","unresolved":true,"context_lines":[{"line_number":51,"context_line":"                raise"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"        # When multi-store is enabled, the output is a list of store dictionaries,"},{"line_number":54,"context_line":"        # otherwise it is a single dictionary."},{"line_number":55,"context_line":"        required_keys \u003d [\u0027id\u0027, \u0027description\u0027, \u0027default\u0027]"},{"line_number":56,"context_line":"        if isinstance(out, list):"},{"line_number":57,"context_line":"            self.assertTrue(len(out) \u003e 0)"}],"source_content_type":"text/x-python","patch_set":14,"id":"c441cacc_2df2368e","line":54,"updated":"2025-11-12 12:08:27.000000000","message":"I don\u0027t believe this to be true. The code [always returns a generator](https://opendev.org/openstack/python-openstackclient/src/commit/7505186a41417fc2130f88d52a980e0b2575b3c6/openstackclient/image/v2/image.py#L1920-L1930) which would result in a list. Are you sure? Where does this assumption come from?","commit_id":"10aeceaf1e04666061682e171303146d5c5e6dcd"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0f35741c32d8c1ed6806d3d522c3f1227caea7b6","unresolved":false,"context_lines":[{"line_number":51,"context_line":"                raise"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"        # When multi-store is enabled, the output is a list of store dictionaries,"},{"line_number":54,"context_line":"        # otherwise it is a single dictionary."},{"line_number":55,"context_line":"        required_keys \u003d [\u0027id\u0027, \u0027description\u0027, \u0027default\u0027]"},{"line_number":56,"context_line":"        if isinstance(out, list):"},{"line_number":57,"context_line":"            self.assertTrue(len(out) \u003e 0)"}],"source_content_type":"text/x-python","patch_set":14,"id":"6fe21a80_88f559de","line":54,"in_reply_to":"c441cacc_2df2368e","updated":"2026-01-21 12:45:32.000000000","message":"Done","commit_id":"10aeceaf1e04666061682e171303146d5c5e6dcd"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"efa7f5f854887bb948ff3226d07848923722bb91","unresolved":true,"context_lines":[{"line_number":54,"context_line":"        # otherwise it is a single dictionary."},{"line_number":55,"context_line":"        required_keys \u003d [\u0027id\u0027, \u0027description\u0027, \u0027default\u0027]"},{"line_number":56,"context_line":"        if isinstance(out, list):"},{"line_number":57,"context_line":"            self.assertTrue(len(out) \u003e 0)"},{"line_number":58,"context_line":"            # Check for required keys in the first store"},{"line_number":59,"context_line":"            for key in required_keys:"},{"line_number":60,"context_line":"                self.assertIn(key, out[0])"}],"source_content_type":"text/x-python","patch_set":14,"id":"736b3ac5_97fab90a","line":57,"updated":"2025-11-12 12:08:27.000000000","message":"```suggestion\n            self.assertGreater(len(out), 0)\n```","commit_id":"10aeceaf1e04666061682e171303146d5c5e6dcd"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0f35741c32d8c1ed6806d3d522c3f1227caea7b6","unresolved":false,"context_lines":[{"line_number":54,"context_line":"        # otherwise it is a single dictionary."},{"line_number":55,"context_line":"        required_keys \u003d [\u0027id\u0027, \u0027description\u0027, \u0027default\u0027]"},{"line_number":56,"context_line":"        if isinstance(out, list):"},{"line_number":57,"context_line":"            self.assertTrue(len(out) \u003e 0)"},{"line_number":58,"context_line":"            # Check for required keys in the first store"},{"line_number":59,"context_line":"            for key in required_keys:"},{"line_number":60,"context_line":"                self.assertIn(key, out[0])"}],"source_content_type":"text/x-python","patch_set":14,"id":"af8347e0_c9e7d74f","line":57,"in_reply_to":"736b3ac5_97fab90a","updated":"2026-01-21 12:45:32.000000000","message":"Done","commit_id":"10aeceaf1e04666061682e171303146d5c5e6dcd"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0f35741c32d8c1ed6806d3d522c3f1227caea7b6","unresolved":true,"context_lines":[{"line_number":29,"context_line":"            # Combine stdout and stderr to catch all error messages"},{"line_number":30,"context_line":"            msg \u003d str(e.stdout or \u0027\u0027) + str(e.stderr or \u0027\u0027)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"            # Check if the command itself is missing (CLI error)"},{"line_number":33,"context_line":"            if \"is not an openstack command\" in msg:"},{"line_number":34,"context_line":"                self.skipTest("},{"line_number":35,"context_line":"                    \"image stores info command is not available in this client\""},{"line_number":36,"context_line":"                )"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"            # Check if the API request failed (Server error)"},{"line_number":39,"context_line":"            # Bad Request (400) or Not Found (404) means feature disabled"}],"source_content_type":"text/x-python","patch_set":19,"id":"0a9beac5_2b7e8a5c","line":36,"range":{"start_line":32,"start_character":0,"end_line":36,"end_character":17},"updated":"2026-01-21 12:45:32.000000000","message":"This needs to be removed. Please see my earlier comment.\n\nhttps://review.opendev.org/c/openstack/python-openstackclient/+/958908/comment/f1f7be1f_eb6faa28/","commit_id":"da2b913ae062e4ccd5eaa23cf51d67da62f9c428"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0f35741c32d8c1ed6806d3d522c3f1227caea7b6","unresolved":true,"context_lines":[{"line_number":34,"context_line":"                self.skipTest("},{"line_number":35,"context_line":"                    \"image stores info command is not available in this client\""},{"line_number":36,"context_line":"                )"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"            # Check if the API request failed (Server error)"},{"line_number":39,"context_line":"            # Bad Request (400) or Not Found (404) means feature disabled"},{"line_number":40,"context_line":"            # or old API"},{"line_number":41,"context_line":"            if ("},{"line_number":42,"context_line":"                \"Bad Request\" in msg"},{"line_number":43,"context_line":"                or \"400\" in msg"},{"line_number":44,"context_line":"                or \"Not Found\" in msg"},{"line_number":45,"context_line":"                or \"404\" in msg"},{"line_number":46,"context_line":"            ):"},{"line_number":47,"context_line":"                self.skipTest("},{"line_number":48,"context_line":"                    \"Glance multi-store not enabled or API not supported\""},{"line_number":49,"context_line":"                )"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"            # If neither, raise the actual error"},{"line_number":52,"context_line":"            raise"}],"source_content_type":"text/x-python","patch_set":19,"id":"2d905f57_c532d799","line":49,"range":{"start_line":37,"start_character":1,"end_line":49,"end_character":17},"updated":"2026-01-21 12:45:32.000000000","message":"I also think this still needs to be reworked https://review.opendev.org/c/openstack/python-openstackclient/+/958908/comment/0364e515_cec85d93/","commit_id":"da2b913ae062e4ccd5eaa23cf51d67da62f9c428"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0f35741c32d8c1ed6806d3d522c3f1227caea7b6","unresolved":true,"context_lines":[{"line_number":74,"context_line":"                \u0027image import info\u0027,"},{"line_number":75,"context_line":"                parse_output\u003dTrue,"},{"line_number":76,"context_line":"            )"},{"line_number":77,"context_line":"        except exceptions.CommandFailed as e:"},{"line_number":78,"context_line":"            msg \u003d str(e.stdout or \u0027\u0027) + str(e.stderr or \u0027\u0027)"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"            # Check if the command itself is missing"},{"line_number":81,"context_line":"            if \"is not an openstack command\" in msg:"},{"line_number":82,"context_line":"                self.skipTest("},{"line_number":83,"context_line":"                    \"image import info command is not available in this client\""},{"line_number":84,"context_line":"                )"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"            # Check if the API request failed"},{"line_number":87,"context_line":"            if ("},{"line_number":88,"context_line":"                \"Bad Request\" in msg"},{"line_number":89,"context_line":"                or \"400\" in msg"},{"line_number":90,"context_line":"                or \"Not Found\" in msg"},{"line_number":91,"context_line":"                or \"404\" in msg"},{"line_number":92,"context_line":"            ):"},{"line_number":93,"context_line":"                self.skipTest("},{"line_number":94,"context_line":"                    \"Import API is not supported by the image service\""},{"line_number":95,"context_line":"                )"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"            raise"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"        # Check for required keys in the import info dictionary"},{"line_number":100,"context_line":"        required_keys \u003d [\u0027import-methods\u0027]"}],"source_content_type":"text/x-python","patch_set":19,"id":"6ceb1a42_69567ec7","line":97,"range":{"start_line":77,"start_character":0,"end_line":97,"end_character":17},"updated":"2026-01-21 12:45:32.000000000","message":"See above","commit_id":"da2b913ae062e4ccd5eaa23cf51d67da62f9c428"}]}
