)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"1598d6a54ba974c0e0963cf0f79558c25aed1499","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"0d242c71_51a1afce","updated":"2025-11-21 12:37:57.000000000","message":"need to address reviewer\u0027s comment and make sure all tests passes.","commit_id":"fba8ad6d5e49743cffa0401aca1ab4d76fcd3aa2"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"ab17e471f90fd6b080cb34c2e20ae23d2d229b4e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"b5d3d570_a090a3e8","updated":"2025-11-24 06:25:47.000000000","message":"Thank you @smooney@redhat.com for the review, I tried to address most of the comments, Do let know if I missed anything, thank you!","commit_id":"35883e84eca32187602b77cbb0b1737757ecc30c"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"896cbb18d6e5c73a7ff971e22c3e8ca064910747","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"8e42133c_45fcb920","updated":"2025-11-24 13:31:33.000000000","message":"somehow tempest picked 6 concurrency\nhttps://storage.bhs.cloud.ovh.net/v1/AUTH_dcaab5e32b234d56b626f72581e3644c/zuul_opendev_logs_5ab/openstack/5abe6cf7a6ad4dea8925dbb1c7fc681e/job-output.txt\n```\n2025-11-24 12:52:02.811810 | controller | all run-test: commands[1] | tempest run --regex watcher_tempest_plugin.tests.api --concurrency\u003d6\n2025-11-24 12:52:07.682193 | controller | /opt/stack/tempest/.tox/tempest/lib/python3.12/site-packages/watcher_tempest_plugin/tests/client_functional/__init__.py:20: DeprecationWarning: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module usage is deprecated and will be removed in version \u00272026.1\u0027, please use watcherclient.tests.client_functional instead: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module is deprecated and will be removed in version 2026.1. We recommend using watcherclient.tests.client_functional for running functional tests.\n2025-11-24 12:52:07.682258 | controller |   removals.removed_module(\n2025-11-24 12:52:09.390130 | controller | /opt/stack/tempest/.tox/tempest/lib/python3.12/site-packages/watcher_tempest_plugin/tests/client_functional/__init__.py:20: DeprecationWarning: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module usage is deprecated and will be removed in version \u00272026.1\u0027, please use watcherclient.tests.client_functional instead: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module is deprecated and will be removed in version 2026.1. We recommend using watcherclient.tests.client_functional for running functional tests.\n2025-11-24 12:52:09.390190 | controller |   removals.removed_module(\n2025-11-24 12:52:09.392317 | controller | /opt/stack/tempest/.tox/tempest/lib/python3.12/site-packages/watcher_tempest_plugin/tests/client_functional/__init__.py:20: DeprecationWarning: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module usage is deprecated and will be removed in version \u00272026.1\u0027, please use watcherclient.tests.client_functional instead: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module is deprecated and will be removed in version 2026.1. We recommend using watcherclient.tests.client_functional for running functional tests.\n2025-11-24 12:52:09.392348 | controller |   removals.removed_module(\n2025-11-24 12:52:09.399471 | controller | /opt/stack/tempest/.tox/tempest/lib/python3.12/site-packages/watcher_tempest_plugin/tests/client_functional/__init__.py:20: DeprecationWarning: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module usage is deprecated and will be removed in version \u00272026.1\u0027, please use watcherclient.tests.client_functional instead: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module is deprecated and will be removed in version 2026.1. We recommend using watcherclient.tests.client_functional for running functional tests.\n2025-11-24 12:52:09.399527 | controller |   removals.removed_module(\n2025-11-24 12:52:09.403421 | controller | /opt/stack/tempest/.tox/tempest/lib/python3.12/site-packages/watcher_tempest_plugin/tests/client_functional/__init__.py:20: DeprecationWarning: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module usage is deprecated and will be removed in version \u00272026.1\u0027, please use watcherclient.tests.client_functional instead: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module is deprecated and will be removed in version 2026.1. We recommend using watcherclient.tests.client_functional for running functional tests.\n2025-11-24 12:52:09.403453 | controller |   removals.removed_module(\n2025-11-24 12:52:09.403947 | controller | /opt/stack/tempest/.tox/tempest/lib/python3.12/site-packages/watcher_tempest_plugin/tests/client_functional/__init__.py:20: DeprecationWarning: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module usage is deprecated and will be removed in version \u00272026.1\u0027, please use watcherclient.tests.client_functional instead: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module is deprecated and will be removed in version 2026.1. We recommend using watcherclient.tests.client_functional for running functional tests.\n2025-11-24 12:52:09.403966 | controller |   removals.removed_module(\n2025-11-24 12:52:09.452598 | controller | /opt/stack/tempest/.tox/tempest/lib/python3.12/site-packages/watcher_tempest_plugin/tests/client_functional/__init__.py:20: DeprecationWarning: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module usage is deprecated and will be removed in version \u00272026.1\u0027, please use watcherclient.tests.client_functional instead: The \u0027watcher_tempest_plugin.tests.client_functional\u0027 module is deprecated and will be removed in version 2026.1. We recommend using watcherclient.tests.client_functional for running functional tests.\n2025-11-24 12:52:09.452655 | controller |   removals.removed_module(\n2025-11-24 12:52:09.571008 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.571062 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.571085 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.571104 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.609867 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.609922 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.613414 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.613454 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.646001 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.646046 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.659168 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.659208 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.683618 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.683677 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.693038 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.693069 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.721427 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.721476 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.736884 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.736930 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.757547 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.757592 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.768999 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:09.769037 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:09.803393 | controller | {1} watcher_tempest_plugin.tests.api.admin.test_api_discovery.TestApiDiscovery.test_api_versions [0.209567s] ... ok\n2025-11-24 12:52:10.299298 | controller | {1} watcher_tempest_plugin.tests.api.admin.test_api_discovery.TestApiDiscovery.test_default_version [0.500853s] ... ok\n2025-11-24 12:52:10.324233 | controller | {4} watcher_tempest_plugin.tests.api.admin.test_data_model.TestNegativeListDataModel.test_list_data_models_storage [0.647410s] ... ok\n2025-11-24 12:52:10.470584 | controller | {1} watcher_tempest_plugin.tests.api.admin.test_api_discovery.TestApiDiscovery.test_version_1_resources [0.170246s] ... ok\n2025-11-24 12:52:10.485515 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:10.485559 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:10.652234 | controller | /opt/stack/tempest/tempest/lib/common/http.py:101: DeprecationWarning: HTTPResponse.getheaders() is deprecated and will be removed in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.\n2025-11-24 12:52:10.652282 | controller |   for key, value in info.getheaders().items():\n2025-11-24 12:52:10.714998 | controller | {4} watcher_tempest_plugin.tests.api.admin.test_scoring_engine.TestShowListScoringEngine.test_list_scoring_engines [0.331900s] ... ok\n2025-11-24 12:52:10.810375 | controller | {2} watcher_tempest_plugin.tests.api.admin.test_audit_template.TestAuditTemplate.test_filter_audit_template_by_goal_uuid [1.145708s] ... ok\n2025-11-24 12:52:10.815757 | controller | {4} watcher_tempest_plugin.tests.api.admin.test_scoring_engine.TestShowListScoringEngine.test_show_scoring_engine [0.101242s] ... ok\n2025-11-24 12:52:10.902144 | controller | {4} watcher_tempest_plugin.tests.api.admin.test_scoring_engine.TestShowListScoringEngine.test_show_scoring_engine_with_links [0.085180s] ... ok\n2025-11-24 12:52:11.298436 | controller | {2} watcher_tempest_plugin.tests.api.admin.test_audit_template.TestAuditTemplate.test_filter_audit_template_by_strategy_uuid [0.485956s] ... ok\n2025-11-24 12:52:11.730310 | controller | {1} watcher_tempest_plugin.tests.api.admin.test_audit.TestShowListAudit.test_list_audits [1.192026s] ... FAILED\n2025-11-24 12:52:11.997507 | controller | Early failure in job, matched regex \"\\{\\d+\\} (.*?) \\[[\\d\\.]+s\\] \\.\\.\\. FAILED\"\nfailure\n2025-11-24 12:52:11.730404 | controller |\n2025-11-24 12:52:11.730428 | controller | Captured traceback:\n2025-11-24 12:52:11.730450 | controller | ~~~~~~~~~~~~~~~~~~~\n2025-11-24 12:52:11.730468 | controller |     Traceback (most recent call last):\n2025-11-24 12:52:11.730506 | controller |\n2025-11-24 12:52:11.730526 | controller |       File \"/opt/stack/tempest/tempest/lib/common/utils/test_utils.py\", line 87, in call_and_ignore_notfound_exc\n2025-11-24 12:52:11.730546 | controller |     return func(*args, **kwargs)\n2025-11-24 12:52:11.730567 | controller |            ^^^^^^^^^^^^^^^^^^^^^\n2025-11-24 12:52:11.730585 | controller |\n2025-11-24 12:52:11.730602 | controller |       File \"/opt/stack/tempest/.tox/tempest/lib/python3.12/site-packages/watcher_tempest_plugin/tests/common/base.py\", line 248, in delete_audit\n2025-11-24 12:52:11.730620 | controller |     resp, _ \u003d self.client.delete_audit(audit_uuid)\n2025-11-24 12:52:11.730691 | controller |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n2025-11-24 12:52:11.730722 | controller |\n2025-11-24 12:52:11.730743 | controller |       File \"/opt/stack/tempest/.tox/tempest/lib/python3.12/site-packages/watcher_tempest_plugin/services/base.py\", line 45, in wrapper\n2025-11-24 12:52:11.730756 | controller |     return f(*args, **kwargs)\n2025-11-24 12:52:11.730766 | controller |            ^^^^^^^^^^^^^^^^^^\n2025-11-24 12:52:11.730774 | controller |\n2025-11-24 12:52:11.730783 | controller |       File \"/opt/stack/tempest/.tox/tempest/lib/python3.12/site-packages/watcher_tempest_plugin/services/infra_optim/v1/json/client.py\", line 161, in delete_audit\n2025-11-24 12:52:11.730793 | controller |     return self._delete_request(\u0027audits\u0027, audit_uuid)\n2025-11-24 12:52:11.730802 | controller |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n2025-11-24 12:52:11.730810 | controller |\n2025-11-24 12:52:11.730819 | controller |       File \"/opt/stack/tempest/.tox/tempest/lib/python3.12/site-packages/watcher_tempest_plugin/services/base.py\", line 173, in _delete_request\n2025-11-24 12:52:11.730828 | controller |     resp, body \u003d self.delete(uri, headers\u003dheaders)\n2025-11-24 12:52:11.730836 | controller |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n2025-11-24 12:52:11.730845 | controller |\n2025-11-24 12:52:11.730854 | controller |       File \"/opt/stack/tempest/tempest/lib/common/rest_client.py\", line 359, in delete\n2025-11-24 12:52:11.730863 | controller |     return self.request(\u0027DELETE\u0027, url, extra_headers, headers, body)\n2025-11-24 12:52:11.730872 | controller |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n2025-11-24 12:52:11.730881 | controller |\n2025-11-24 12:52:11.730889 | controller |       File \"/opt/stack/tempest/tempest/lib/common/rest_client.py\", line 762, in request\n2025-11-24 12:52:11.730898 | controller |     self._error_checker(resp, resp_body)\n2025-11-24 12:52:11.730907 | controller |\n2025-11-24 12:52:11.730915 | controller |       File \"/opt/stack/tempest/tempest/lib/common/rest_client.py\", line 877, in _error_checker\n2025-11-24 12:52:11.730924 | controller |     raise exceptions.BadRequest(resp_body, resp\u003dresp)\n2025-11-24 12:52:11.730932 | controller |\n2025-11-24 12:52:11.730941 | controller |     tempest.lib.exceptions.BadRequest: Bad request\n2025-11-24 12:52:11.730950 | controller | Details: {\u0027error_message\u0027: \u0027{\"faultcode\": \"Client\", \"faultstring\": \"Couldn\\\u0027t delete when state is \\\u0027ONGOING\\\u0027.\", \"debuginfo\": null}\u0027}\n2025-11-24 12:52:11.730958 | controller |\n```","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c93885086999c3bb7888576267315112565033ef","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"b1fe52a6_ceb09c1f","updated":"2025-11-24 13:39:44.000000000","message":"this is much closer thanks for working on it","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ac9e802db905a520acfa10af9f651be1b7993457","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"7c6d0555_f2fb7959","updated":"2025-11-24 15:28:20.000000000","message":"some of my comments are redutant if we implement the mappiing interface on the frozen enuma metaclass","commit_id":"c9a5d2d3fcf0988bf79c9225d6b92694603983e9"},{"author":{"_account_id":30002,"name":"Douglas Viroel","email":"viroel@gmail.com","username":"dviroel"},"change_message_id":"1efd802be662d7cb77a15b077b0430560f062cd1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":17,"id":"7778b162_6571d672","updated":"2025-11-25 17:31:03.000000000","message":"It is a good refactoring and duplicated code deletion, thanks!","commit_id":"d1edf92c8fa92c2221fc7364a0aa27a8018565dd"}],"watcher_tempest_plugin/tests/api/admin/base.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c93885086999c3bb7888576267315112565033ef","unresolved":true,"context_lines":[{"line_number":23,"context_line":"from watcher_tempest_plugin.services.infra_optim.v1.json import ("},{"line_number":24,"context_line":"    api_microversion_fixture"},{"line_number":25,"context_line":")"},{"line_number":26,"context_line":"from watcher_tempest_plugin.tests.common import base as common_base"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"CONF \u003d config.CONF"},{"line_number":29,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"a9eec09c_34ff7deb","line":26,"updated":"2025-11-24 13:39:44.000000000","message":"```suggestion\nfrom watcher_tempest_plugin.tests.common import base\n```","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8fa564b511ceaf74546096236151907e3da185c2","unresolved":false,"context_lines":[{"line_number":23,"context_line":"from watcher_tempest_plugin.services.infra_optim.v1.json import ("},{"line_number":24,"context_line":"    api_microversion_fixture"},{"line_number":25,"context_line":")"},{"line_number":26,"context_line":"from watcher_tempest_plugin.tests.common import base as common_base"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"CONF \u003d config.CONF"},{"line_number":29,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"b184ed73_928fb4f0","line":26,"in_reply_to":"a9eec09c_34ff7deb","updated":"2025-11-24 14:28:17.000000000","message":"Done","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c93885086999c3bb7888576267315112565033ef","unresolved":true,"context_lines":[{"line_number":28,"context_line":"CONF \u003d config.CONF"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"class BaseInfraOptimTest(common_base.BaseCommon,"},{"line_number":32,"context_line":"                         api_version_utils.BaseMicroversionTest,"},{"line_number":33,"context_line":"                         test.BaseTestCase):"},{"line_number":34,"context_line":"    \"\"\"Base class for Infrastructure Optimization API tests.\"\"\""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    @classmethod"}],"source_content_type":"text/x-python","patch_set":12,"id":"52aaf842_6d247440","line":33,"range":{"start_line":31,"start_character":0,"end_line":33,"end_character":44},"updated":"2025-11-24 13:39:44.000000000","message":"```suggestion\nclass BaseInfraOptimTest(\n    api_version_utils.BaseMicroversionTest, test.BaseTestCase\n    base.WatcherHelperMixin):\n```","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8fa564b511ceaf74546096236151907e3da185c2","unresolved":false,"context_lines":[{"line_number":28,"context_line":"CONF \u003d config.CONF"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"class BaseInfraOptimTest(common_base.BaseCommon,"},{"line_number":32,"context_line":"                         api_version_utils.BaseMicroversionTest,"},{"line_number":33,"context_line":"                         test.BaseTestCase):"},{"line_number":34,"context_line":"    \"\"\"Base class for Infrastructure Optimization API tests.\"\"\""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    @classmethod"}],"source_content_type":"text/x-python","patch_set":12,"id":"a22b70fa_ed985539","line":33,"range":{"start_line":31,"start_character":0,"end_line":33,"end_character":44},"in_reply_to":"52aaf842_6d247440","updated":"2025-11-24 14:28:17.000000000","message":"Done","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ac9e802db905a520acfa10af9f651be1b7993457","unresolved":true,"context_lines":[{"line_number":28,"context_line":"CONF \u003d config.CONF"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"class BaseInfraOptimTest(base.WatcherHelperMixin,"},{"line_number":32,"context_line":"                         api_version_utils.BaseMicroversionTest,"},{"line_number":33,"context_line":"                         test.BaseTestCase):"},{"line_number":34,"context_line":"    \"\"\"Base class for Infrastructure Optimization API tests.\"\"\""}],"source_content_type":"text/x-python","patch_set":13,"id":"168f8612_ea4e9005","line":31,"range":{"start_line":31,"start_character":25,"end_line":31,"end_character":49},"updated":"2025-11-24 15:28:20.000000000","message":"you didnt put this last like i asked.\n\nthis actully does mater as the order of classes impact method resolution order\n\nin principa this only patter if a futcion is decared diffently in 2 diffetn classes but plase actuly put the mixin classes last like i previously asked.","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"cd5cb0ddabb7e64ad056c03432af91794c5db0bf","unresolved":false,"context_lines":[{"line_number":28,"context_line":"CONF \u003d config.CONF"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"class BaseInfraOptimTest(base.WatcherHelperMixin,"},{"line_number":32,"context_line":"                         api_version_utils.BaseMicroversionTest,"},{"line_number":33,"context_line":"                         test.BaseTestCase):"},{"line_number":34,"context_line":"    \"\"\"Base class for Infrastructure Optimization API tests.\"\"\""}],"source_content_type":"text/x-python","patch_set":13,"id":"6a8d57c3_5e079e3c","line":31,"range":{"start_line":31,"start_character":25,"end_line":31,"end_character":49},"in_reply_to":"168f8612_ea4e9005","updated":"2025-11-25 11:53:14.000000000","message":"Done","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"}],"watcher_tempest_plugin/tests/api/admin/test_action.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c93885086999c3bb7888576267315112565033ef","unresolved":true,"context_lines":[{"line_number":27,"context_line":"    \"\"\"Tests for actions\"\"\""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def setUp(self):"},{"line_number":30,"context_line":"        super(TestShowListAction, self).setUp()"},{"line_number":31,"context_line":"        _, self.goal \u003d self.client.show_goal(\"DUMMY\")"},{"line_number":32,"context_line":"        _, self.audit_template \u003d self.create_audit_template(self.goal[\u0027uuid\u0027])"},{"line_number":33,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"ddaef52a_2436e103","line":30,"range":{"start_line":30,"start_character":8,"end_line":30,"end_character":47},"updated":"2025-11-24 13:39:44.000000000","message":"please use the new styel supper calles for new code or when your modifying the existing code\n\n\n```suggestion\n        super().setUp()\n```\n\npassing the instance refecnce and start class was required for python 2 compaitablity but has never been required for python 3","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8fa564b511ceaf74546096236151907e3da185c2","unresolved":false,"context_lines":[{"line_number":27,"context_line":"    \"\"\"Tests for actions\"\"\""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def setUp(self):"},{"line_number":30,"context_line":"        super(TestShowListAction, self).setUp()"},{"line_number":31,"context_line":"        _, self.goal \u003d self.client.show_goal(\"DUMMY\")"},{"line_number":32,"context_line":"        _, self.audit_template \u003d self.create_audit_template(self.goal[\u0027uuid\u0027])"},{"line_number":33,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"917ac777_6367e94f","line":30,"range":{"start_line":30,"start_character":8,"end_line":30,"end_character":47},"in_reply_to":"ddaef52a_2436e103","updated":"2025-11-24 14:28:17.000000000","message":"Done","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ac9e802db905a520acfa10af9f651be1b7993457","unresolved":true,"context_lines":[{"line_number":135,"context_line":""},{"line_number":136,"context_line":"        _, self.audit \u003d self.create_audit(self.audit_template[\u0027uuid\u0027])"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"        assert test_utils.call_until_true("},{"line_number":139,"context_line":"            func\u003dfunctools.partial(self.has_audit_succeeded,"},{"line_number":140,"context_line":"                                   self.audit[\u0027uuid\u0027]),"},{"line_number":141,"context_line":"            duration\u003d30,"}],"source_content_type":"text/x-python","patch_set":13,"id":"ca1bb78b_ab0feaa4","line":138,"updated":"2025-11-24 15:28:20.000000000","message":"sigh we shoudl have caught this before \nmaybe we need to clean up all direct useage of bare assert seperatly\n\nthis is not in line wiht oepsntack codeign congetion so we shoudl not do this goign forward and fix all exetistin tests.\n\nhttps://github.com/openstack/hacking/blob/master/HACKING.rst#unit-tests-and-assertraises","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8c428ea97342a69fadce677cb07dc828314e1607","unresolved":false,"context_lines":[{"line_number":135,"context_line":""},{"line_number":136,"context_line":"        _, self.audit \u003d self.create_audit(self.audit_template[\u0027uuid\u0027])"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"        assert test_utils.call_until_true("},{"line_number":139,"context_line":"            func\u003dfunctools.partial(self.has_audit_succeeded,"},{"line_number":140,"context_line":"                                   self.audit[\u0027uuid\u0027]),"},{"line_number":141,"context_line":"            duration\u003d30,"}],"source_content_type":"text/x-python","patch_set":13,"id":"9e18ec9b_b4b46504","line":138,"in_reply_to":"ca1bb78b_ab0feaa4","updated":"2025-11-25 06:36:17.000000000","message":"Acknowledged","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"}],"watcher_tempest_plugin/tests/api/admin/test_audit.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c93885086999c3bb7888576267315112565033ef","unresolved":true,"context_lines":[{"line_number":221,"context_line":"class TestShowListAudit(base.BaseInfraOptimTest):"},{"line_number":222,"context_line":"    \"\"\"Tests for audit.\"\"\""},{"line_number":223,"context_line":""},{"line_number":224,"context_line":"    audit_states \u003d [\u0027ONGOING\u0027, \u0027SUCCEEDED\u0027, \u0027FAILED\u0027,"},{"line_number":225,"context_line":"                    \u0027CANCELLED\u0027, \u0027DELETED\u0027, \u0027PENDING\u0027, \u0027SUSPENDED\u0027]"},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":12,"id":"3b466f71_d2559529","line":224,"updated":"2025-11-24 13:39:44.000000000","message":"you should factor these out into \n\nhttps://review.opendev.org/c/openstack/watcher-tempest-plugin/+/967522/12/watcher_tempest_plugin/tests/common/base.py as well","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8fa564b511ceaf74546096236151907e3da185c2","unresolved":false,"context_lines":[{"line_number":221,"context_line":"class TestShowListAudit(base.BaseInfraOptimTest):"},{"line_number":222,"context_line":"    \"\"\"Tests for audit.\"\"\""},{"line_number":223,"context_line":""},{"line_number":224,"context_line":"    audit_states \u003d [\u0027ONGOING\u0027, \u0027SUCCEEDED\u0027, \u0027FAILED\u0027,"},{"line_number":225,"context_line":"                    \u0027CANCELLED\u0027, \u0027DELETED\u0027, \u0027PENDING\u0027, \u0027SUSPENDED\u0027]"},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":12,"id":"5e9ded46_e7d17332","line":224,"in_reply_to":"3b466f71_d2559529","updated":"2025-11-24 14:28:17.000000000","message":"Done","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ac9e802db905a520acfa10af9f651be1b7993457","unresolved":true,"context_lines":[{"line_number":27,"context_line":"class TestCreateUpdateDeleteAudit(base.BaseInfraOptimTest):"},{"line_number":28,"context_line":"    \"\"\"Tests for audit.\"\"\""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"    audit_states \u003d tuple(s.value for s in common_base.AuditStates)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"    def assert_expected(self, expected, actual,"},{"line_number":33,"context_line":"                        keys\u003d(\u0027created_at\u0027, \u0027updated_at\u0027, \u0027next_run_time\u0027,"}],"source_content_type":"text/x-python","patch_set":13,"id":"89a37429_102d8877","line":30,"updated":"2025-11-24 15:28:20.000000000","message":"this works but is there a reason you are not defineing it here\n\nin WatcherHelperMixin so that you can just do self.AUDIT_STATE\n\nalthogu hthinking about this more why are you converting to a tupple at all.\n\nyou only use this in an insert in check\n\nyou can just do that with common_base.AuditStates.values()\n\nthere is no reason to ever create a tuple form that.","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8c428ea97342a69fadce677cb07dc828314e1607","unresolved":false,"context_lines":[{"line_number":27,"context_line":"class TestCreateUpdateDeleteAudit(base.BaseInfraOptimTest):"},{"line_number":28,"context_line":"    \"\"\"Tests for audit.\"\"\""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"    audit_states \u003d tuple(s.value for s in common_base.AuditStates)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"    def assert_expected(self, expected, actual,"},{"line_number":33,"context_line":"                        keys\u003d(\u0027created_at\u0027, \u0027updated_at\u0027, \u0027next_run_time\u0027,"}],"source_content_type":"text/x-python","patch_set":13,"id":"f1ead3e8_5874cb7c","line":30,"in_reply_to":"89a37429_102d8877","updated":"2025-11-25 06:36:17.000000000","message":"Done","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ac9e802db905a520acfa10af9f651be1b7993457","unresolved":true,"context_lines":[{"line_number":160,"context_line":"        _, audit \u003d self.client.show_audit(body[\u0027uuid\u0027])"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"        initial_audit_state \u003d audit.pop(\u0027state\u0027)"},{"line_number":163,"context_line":"        self.assertIn(initial_audit_state, self.audit_states)"},{"line_number":164,"context_line":""},{"line_number":165,"context_line":"        self.assert_expected(audit, body)"},{"line_number":166,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"211dfb74_600b25bb","line":163,"updated":"2025-11-24 15:28:20.000000000","message":"here you could just use common_base.AuditStates.values()","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8c428ea97342a69fadce677cb07dc828314e1607","unresolved":false,"context_lines":[{"line_number":160,"context_line":"        _, audit \u003d self.client.show_audit(body[\u0027uuid\u0027])"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"        initial_audit_state \u003d audit.pop(\u0027state\u0027)"},{"line_number":163,"context_line":"        self.assertIn(initial_audit_state, self.audit_states)"},{"line_number":164,"context_line":""},{"line_number":165,"context_line":"        self.assert_expected(audit, body)"},{"line_number":166,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"c08787e8_94934b0a","line":163,"in_reply_to":"211dfb74_600b25bb","updated":"2025-11-25 06:36:17.000000000","message":"Done","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ac9e802db905a520acfa10af9f651be1b7993457","unresolved":true,"context_lines":[{"line_number":231,"context_line":""},{"line_number":232,"context_line":"        # Wait for audit to finish to prevent race conditions"},{"line_number":233,"context_line":"        # during cleanup when running tests with high concurrency"},{"line_number":234,"context_line":"        assert test_utils.call_until_true("},{"line_number":235,"context_line":"            func\u003dfunctools.partial("},{"line_number":236,"context_line":"                self.has_audit_finished, self.audit[\u0027uuid\u0027]),"},{"line_number":237,"context_line":"            duration\u003d30,"}],"source_content_type":"text/x-python","patch_set":13,"id":"fae6a305_73d878e6","line":234,"updated":"2025-11-24 15:28:20.000000000","message":"do not use bare asserts in tests\n\nuse self.assertTrue(...)","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8c428ea97342a69fadce677cb07dc828314e1607","unresolved":false,"context_lines":[{"line_number":231,"context_line":""},{"line_number":232,"context_line":"        # Wait for audit to finish to prevent race conditions"},{"line_number":233,"context_line":"        # during cleanup when running tests with high concurrency"},{"line_number":234,"context_line":"        assert test_utils.call_until_true("},{"line_number":235,"context_line":"            func\u003dfunctools.partial("},{"line_number":236,"context_line":"                self.has_audit_finished, self.audit[\u0027uuid\u0027]),"},{"line_number":237,"context_line":"            duration\u003d30,"}],"source_content_type":"text/x-python","patch_set":13,"id":"a637bf90_6295bb1f","line":234,"in_reply_to":"fae6a305_73d878e6","updated":"2025-11-25 06:36:17.000000000","message":"Done","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"}],"watcher_tempest_plugin/tests/common/base.py":[{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"ab17e471f90fd6b080cb34c2e20ae23d2d229b4e","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            name\u003dname, description\u003ddescription, goal\u003dgoal,"},{"line_number":50,"context_line":"            strategy\u003dstrategy, scope\u003dscope)"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        cls.addClassResourceCleanup("},{"line_number":53,"context_line":"            cls.delete_audit_template,"},{"line_number":54,"context_line":"            audit_template_uuid\u003dbody[\"uuid\"]"},{"line_number":55,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":3,"id":"c3875c5e_1f48c782","line":52,"in_reply_to":"264e41e8_a3e52c52","updated":"2025-11-24 06:25:47.000000000","message":"Yes, moving to instancemethod approach works perfectly fine, fixed it now.","commit_id":"f9bcd9693ea6ab8eba62b4bec1d68e41c111c156"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"5831da15ccfae6beb3e63c21068f8de61f464be8","unresolved":true,"context_lines":[{"line_number":49,"context_line":"            name\u003dname, description\u003ddescription, goal\u003dgoal,"},{"line_number":50,"context_line":"            strategy\u003dstrategy, scope\u003dscope)"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        cls.addClassResourceCleanup("},{"line_number":53,"context_line":"            cls.delete_audit_template,"},{"line_number":54,"context_line":"            audit_template_uuid\u003dbody[\"uuid\"]"},{"line_number":55,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":3,"id":"48f1b676_629a095e","line":52,"in_reply_to":"2edf4f1a_3d46cae6","updated":"2025-11-19 07:05:35.000000000","message":"@smooney@redhat.com watcher-tempest-plugin api tests uses classmethod and scenario tests uses instance method. \n\nIn order to keep consistency, Do we want to drop addcleanup (instance method) from scenario tests and switch to addClassResourceCleanup?  \n\nI need suggestion here how to handle this case?","commit_id":"f9bcd9693ea6ab8eba62b4bec1d68e41c111c156"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"741baf1f9c97b3de647a3a1a8ac5d1c20adc8541","unresolved":true,"context_lines":[{"line_number":49,"context_line":"            name\u003dname, description\u003ddescription, goal\u003dgoal,"},{"line_number":50,"context_line":"            strategy\u003dstrategy, scope\u003dscope)"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        cls.addClassResourceCleanup("},{"line_number":53,"context_line":"            cls.delete_audit_template,"},{"line_number":54,"context_line":"            audit_template_uuid\u003dbody[\"uuid\"]"},{"line_number":55,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":3,"id":"264e41e8_a3e52c52","line":52,"in_reply_to":"48f1b676_629a095e","updated":"2025-11-19 10:36:17.000000000","message":"no we shoudl stop suing class method here and jsut use instnace methods everywhere\n\nwe shoudl also move these ideally to a mixin calss \nhttps://github.com/openstack/nova/blob/master/nova/tests/functional/integrated_helpers.py#L104\nthat is included in the base test case \n\nin the end there shoudl only be 1 defintion of create_audit_template in the tempest plugin\n\nit shoudl be a class method on a mixin so w ecan incldue it in the api and secnarios tests.\n\nthe reason it need to be a mix in is becaue\nthe api test inherit form tempest.test.BaseTestCase\n\nhttps://opendev.org/openstack/watcher-tempest-plugin/src/branch/master/watcher_tempest_plugin/tests/api/admin/base.py#L34-L35\n\nwhere as the senaior tests inherit form tempest.scenario.manager.ScenarioTest\nhttps://opendev.org/openstack/watcher-tempest-plugin/src/branch/master/watcher_tempest_plugin/tests/scenario/base.py#L61\n\n\nwe want to prefer instnace menthosd so that we can use addCleanup as taht si the function we use most often in unit testing and the majority fo core tempest.\n\n\nthe tempest coding guide deals with this here\n\nhttps://github.com/openstack/tempest/blob/8ccefd4bea48d6b38f7e16c50f97931b3fc2a5e2/HACKING.rst#test-fixtures-and-resources\n\n\n```\nTest level resources should be cleaned-up after the test execution. Clean-up is best scheduled using addCleanup which ensures that the resource cleanup code is always invoked, and in reverse order with respect to the creation order.\n\nTest class level resources should be defined in the resource_setup method of the test class, except for any credential obtained from the credentials provider, which should be set-up in the setup_credentials method. Cleanup is best scheduled using addClassResourceCleanup which ensures that the cleanup code is always invoked, and in reverse order with respect to the creation order.\n\nIn both cases - test level and class level cleanups - a wait loop should be scheduled before the actual delete of resources with an asynchronous delete.\n```\n\naddClassResourceCleanup is realy intened for the case where you want to reuse a reouce between tests\n\ni.e. creatign an audit tempelate once and then uing the same one for many tests in a given class.\n\nwe typiclly only need to that if the  creation of the reosuce is expensive liek creating a vm.\n\ni dont think we should be using that partern in our wathcer tests in general whcih is why im pushing you ot take the isntance method approch and not declare them class methods.","commit_id":"f9bcd9693ea6ab8eba62b4bec1d68e41c111c156"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"741baf1f9c97b3de647a3a1a8ac5d1c20adc8541","unresolved":true,"context_lines":[{"line_number":63,"context_line":"        :param audit_template_uuid: The unique identifier of the audit template"},{"line_number":64,"context_line":"        :return: Server response"},{"line_number":65,"context_line":"        \"\"\""},{"line_number":66,"context_line":"        try:"},{"line_number":67,"context_line":"            resp, _ \u003d cls.client.delete_audit_template(audit_template_uuid)"},{"line_number":68,"context_line":"        except exceptions.NotFound:"},{"line_number":69,"context_line":"            # Resource might already be deleted"}],"source_content_type":"text/x-python","patch_set":3,"id":"de18d03d_6aa7df7b","line":66,"in_reply_to":"266b1f25_bbbf2a84","updated":"2025-11-19 10:36:17.000000000","message":"\u003e Improve error handling in delete_audit_template to use call_and_ignore_notfound_exc pattern for consistency\n\u003e \n\u003e **Severity**: SUGGESTION | **Confidence**: 0.7\n\u003e \n\u003e **Benefit**: Consistent error handling across all deletion methods reduces maintenance burden\n\u003e \n\u003e **Recommendation**:\n\u003e Replace the try/except NotFound pattern with cls.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc, cls.delete_audit_template, audit_template_uuid) approach\n\nneat https://github.com/openstack/tempest/blob/8ccefd4bea48d6b38f7e16c50f97931b3fc2a5e2/tempest/api/network/base_security_groups.py#L32\n\ni was not aware of this pattern in tempest but yes i agree we shoudl adopt that.","commit_id":"f9bcd9693ea6ab8eba62b4bec1d68e41c111c156"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"ab17e471f90fd6b080cb34c2e20ae23d2d229b4e","unresolved":false,"context_lines":[{"line_number":63,"context_line":"        :param audit_template_uuid: The unique identifier of the audit template"},{"line_number":64,"context_line":"        :return: Server response"},{"line_number":65,"context_line":"        \"\"\""},{"line_number":66,"context_line":"        try:"},{"line_number":67,"context_line":"            resp, _ \u003d cls.client.delete_audit_template(audit_template_uuid)"},{"line_number":68,"context_line":"        except exceptions.NotFound:"},{"line_number":69,"context_line":"            # Resource might already be deleted"}],"source_content_type":"text/x-python","patch_set":3,"id":"49061bcb_4a994c0e","line":66,"in_reply_to":"de18d03d_6aa7df7b","updated":"2025-11-24 06:25:47.000000000","message":"Done","commit_id":"f9bcd9693ea6ab8eba62b4bec1d68e41c111c156"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"741baf1f9c97b3de647a3a1a8ac5d1c20adc8541","unresolved":false,"context_lines":[{"line_number":141,"context_line":""},{"line_number":142,"context_line":"            _, action_plans \u003d cls.client.list_action_plans("},{"line_number":143,"context_line":"                audit_uuid\u003daudit_uuid)"},{"line_number":144,"context_line":"            for action_plan in action_plans.get(\"action_plans\", []):"},{"line_number":145,"context_line":"                try:"},{"line_number":146,"context_line":"                    cls.delete_action_plan("},{"line_number":147,"context_line":"                        action_plan_uuid\u003daction_plan[\"uuid\"])"}],"source_content_type":"text/x-python","patch_set":3,"id":"995ad96e_e056e294","line":144,"in_reply_to":"d5945951_4775e048","updated":"2025-11-19 10:36:17.000000000","message":"\u003e Potential resource leak in delete_audit method - action plan deletion doesn\u0027t verify success before proceeding to audit deletion\n\u003e \n\u003e **Severity**: HIGH | **Confidence**: 0.8\n\u003e \n\u003e **Risk**: Action plans might remain in database if deletion fails silently, causing subsequent test failures\n\u003e \n\u003e **Priority**: Before merge\n\u003e **Why This Matters**: Silent failures in resource cleanup can cause cascade failures in test suites and waste resources in CI environments\n\u003e \n\u003e **Recommendation**:\n\u003e Add verification that action plans are actually deleted before proceeding with audit deletion, or use call_and_ignore_notfound_exc pattern consistently\n\nthis code should not need to verify that delete_action_plan is responibel for the deletion.\n\nif we need to canel/abort the actionplan to ensure the deletion happnes it should be encapsulated by delete_action_plan","commit_id":"f9bcd9693ea6ab8eba62b4bec1d68e41c111c156"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c93885086999c3bb7888576267315112565033ef","unresolved":false,"context_lines":[{"line_number":22,"context_line":"from tempest.lib import exceptions"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"class BaseCommon:"},{"line_number":26,"context_line":"    \"\"\"Base class for audit, audit template, and action plan utilities.\"\"\""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    # States where the object is waiting for some event to perform a transition"}],"source_content_type":"text/x-python","patch_set":4,"id":"d4eb6be4_baa22ea2","line":25,"in_reply_to":"11895a11_918aa9dd","updated":"2025-11-24 13:39:44.000000000","message":"Done","commit_id":"ca9abc67796ea848afd36acb472918a3e0197c6a"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"ab17e471f90fd6b080cb34c2e20ae23d2d229b4e","unresolved":true,"context_lines":[{"line_number":22,"context_line":"from tempest.lib import exceptions"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"class BaseCommon:"},{"line_number":26,"context_line":"    \"\"\"Base class for audit, audit template, and action plan utilities.\"\"\""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    # States where the object is waiting for some event to perform a transition"}],"source_content_type":"text/x-python","patch_set":4,"id":"11895a11_918aa9dd","line":25,"in_reply_to":"53a8477f_2db318bf","updated":"2025-11-24 06:25:47.000000000","message":"Thank you for sharing the example of frozen enum with code examples. Added it to the base.py.","commit_id":"ca9abc67796ea848afd36acb472918a3e0197c6a"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"741baf1f9c97b3de647a3a1a8ac5d1c20adc8541","unresolved":true,"context_lines":[{"line_number":22,"context_line":"from tempest.lib import exceptions"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"class BaseCommon:"},{"line_number":26,"context_line":"    \"\"\"Base class for audit, audit template, and action plan utilities.\"\"\""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    # States where the object is waiting for some event to perform a transition"}],"source_content_type":"text/x-python","patch_set":4,"id":"53a8477f_2db318bf","line":25,"in_reply_to":"62188fba_2c9043da","updated":"2025-11-19 10:36:17.000000000","message":"\u003e Add audit state constants to BaseCommon for consistency\n\u003e \n\u003e **Severity**: SUGGESTION | **Confidence**: 0.7\n\u003e \n\u003e **Benefit**: Would improve maintainability and reduce hardcoded state strings\n\u003e \n\u003e **Recommendation**:\n\u003e Add AUDIT_FINISHED_STATES constant to eliminate missing reference in scenario base\n\nwe could prefix this with AUDIT_\n\nbut what its really asking for is not that\n\nits saying that instead of defining these as tuples\n\nIDLE_STATES \u003d (\u0027RECOMMENDED\u0027, \u0027FAILED\u0027, \u0027SUCCEEDED\u0027,\n                   \u0027CANCELLED\u0027, \u0027SUPERSEDED\u0027, \u0027SUSPENDED\u0027)\nFINISHED_STATES \u003d (\u0027FAILED\u0027,\n                       \u0027SUCCEEDED\u0027,\n                       \u0027CANCELLED\u0027,\n                       \u0027SUPERSEDED\u0027)\n\nwe instead define them properly as str enums  like this\n\nhttps://review.opendev.org/c/openstack/nova/+/825015/21/nova/healthcheck/constants.py#46\n\n```\nfrom enum import Enum\nfrom enum import EnumMeta\n\nclass FrozenEnum(EnumMeta):\n    \"prevent creation of new attributes\"\n    def __getattr__(self, name):\n        if name not in self._member_map_:\n            raise AttributeError(\u0027%s %r has no attribute %r\u0027\n                % (self.__class__.__name__, self.__name__, name))\n        # mypy does not know this is a metaclass and that __getattr__ is\n        # defined in the superclass of the class that uses this\n        # so we need to ignore the type error here.\n        return super().__getattr__(name)  # type: ignore\n    def __setattr__(self, name, value):\n        if name in self.__dict__ or name in self._member_map_:\n            return super().__setattr__(name, value)\n        raise AttributeError(\u0027%s %r has no attribute %r\u0027\n                % (self.__class__.__name__, self.__name__, name))\ndef freeze(enum_class):\n    enum_class.__class__ \u003d FrozenEnum\n    return enum_class\n\n@freeze\nclass IdleStates(str, Enum)\n\n    RECOMMENDED \u003d \u0027RECOMMENDED\u0027\n    FAILED \u003d \u0027FAILED\u0027\n    SUCCEEDED \u003d \u0027SUCCEEDED\u0027\n    CANCELLED \u003d \u0027CANCELLED\u0027\n    SUPERSEDED \u003d \u0027SUPERSEDED\u0027\n    SUSPENDED \u003d \u0027SUSPENDED\u0027\n    \n    ALL \u003d (RECOMMENDED,FAILED,SUCCEEDED, CANCELLED, SUPERSEDED, SUSPENDED)\n```\n\nbasiclly like this \nhttps://github.com/openstack/nova/blob/master/nova/objects/fields.py#L318-L324\n\ni do agree that usign an enuma here woudl be more correct\n\nyou have impoved things by adopting not in cls.FINISHED_STATES:\n\nbut yes these really shoudl be enums\nmaking them a forzen enum is perhaps mroe then we need but it will prevent acidental mutation if a test is written incorrectly.","commit_id":"ca9abc67796ea848afd36acb472918a3e0197c6a"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"ab17e471f90fd6b080cb34c2e20ae23d2d229b4e","unresolved":false,"context_lines":[{"line_number":69,"context_line":"        :param audit_template_uuid: The unique identifier of the audit template"},{"line_number":70,"context_line":"        :return: Server response"},{"line_number":71,"context_line":"        \"\"\""},{"line_number":72,"context_line":"        try:"},{"line_number":73,"context_line":"            resp, _ \u003d cls.client.delete_audit_template(audit_template_uuid)"},{"line_number":74,"context_line":"        except exceptions.NotFound:"},{"line_number":75,"context_line":"            # Resource might already be deleted"}],"source_content_type":"text/x-python","patch_set":4,"id":"0afeb112_fdf634ae","line":72,"in_reply_to":"b76039f2_6dba1f24","updated":"2025-11-24 06:25:47.000000000","message":"Acknowledged","commit_id":"ca9abc67796ea848afd36acb472918a3e0197c6a"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"741baf1f9c97b3de647a3a1a8ac5d1c20adc8541","unresolved":true,"context_lines":[{"line_number":69,"context_line":"        :param audit_template_uuid: The unique identifier of the audit template"},{"line_number":70,"context_line":"        :return: Server response"},{"line_number":71,"context_line":"        \"\"\""},{"line_number":72,"context_line":"        try:"},{"line_number":73,"context_line":"            resp, _ \u003d cls.client.delete_audit_template(audit_template_uuid)"},{"line_number":74,"context_line":"        except exceptions.NotFound:"},{"line_number":75,"context_line":"            # Resource might already be deleted"}],"source_content_type":"text/x-python","patch_set":4,"id":"b76039f2_6dba1f24","line":72,"in_reply_to":"db4f666d_2a0111cb","updated":"2025-11-19 10:36:17.000000000","message":"\u003e Inconsistent error handling in resource cleanup methods\n\u003e \n\u003e **Severity**: WARNING | **Confidence**: 0.7\n\u003e \n\u003e **Impact**: May hide deletion failures in test scenarios\n\u003e \n\u003e **Suggestion**:\n\u003e Consider adding logging when resources are not found during cleanup to aid debugging\n\nwe could but this is not needed","commit_id":"ca9abc67796ea848afd36acb472918a3e0197c6a"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"741baf1f9c97b3de647a3a1a8ac5d1c20adc8541","unresolved":true,"context_lines":[{"line_number":84,"context_line":"        \"\"\"Wrapper utility for creating a test audit"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"        :param audit_template_uuid: Audit Template UUID this audit will use"},{"line_number":87,"context_line":"        :param type: Audit type (either ONESHOT or CONTINUOUS)"},{"line_number":88,"context_line":"        :param state: Audit state (str)"},{"line_number":89,"context_line":"        :param interval: Audit interval in seconds (int)"},{"line_number":90,"context_line":"        :param parameters: list of execution parameters"}],"source_content_type":"text/x-python","patch_set":4,"id":"64ea0d67_b838313b","line":87,"in_reply_to":"175165e3_83e973ab","updated":"2025-11-19 10:36:17.000000000","message":"ah yep this is a good catch, it is audit_type not type. although that is tecnically an unrelated chagne. so you do not need to adress it now but i wont complian if you fix it.","commit_id":"ca9abc67796ea848afd36acb472918a3e0197c6a"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"ab17e471f90fd6b080cb34c2e20ae23d2d229b4e","unresolved":false,"context_lines":[{"line_number":84,"context_line":"        \"\"\"Wrapper utility for creating a test audit"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"        :param audit_template_uuid: Audit Template UUID this audit will use"},{"line_number":87,"context_line":"        :param type: Audit type (either ONESHOT or CONTINUOUS)"},{"line_number":88,"context_line":"        :param state: Audit state (str)"},{"line_number":89,"context_line":"        :param interval: Audit interval in seconds (int)"},{"line_number":90,"context_line":"        :param parameters: list of execution parameters"}],"source_content_type":"text/x-python","patch_set":4,"id":"35af7433_0dcbb21a","line":87,"in_reply_to":"64ea0d67_b838313b","updated":"2025-11-24 06:25:47.000000000","message":"Done","commit_id":"ca9abc67796ea848afd36acb472918a3e0197c6a"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c93885086999c3bb7888576267315112565033ef","unresolved":true,"context_lines":[{"line_number":74,"context_line":"    SUPERSEDED \u003d \u0027SUPERSEDED\u0027"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"class BaseCommon:"},{"line_number":78,"context_line":"    \"\"\"Base class for audit, audit template, and action plan utilities.\"\"\""},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"    # States where the object is waiting for some event to perform a transition"}],"source_content_type":"text/x-python","patch_set":12,"id":"108b3e6b_f5ad780c","line":77,"range":{"start_line":77,"start_character":6,"end_line":77,"end_character":16},"updated":"2025-11-24 13:39:44.000000000","message":"can we name this slightly differently `WatcherHelperMixin`\n\nthe reason i want to rename it is Mixin classes general shoudl not contain and mutable data member, only implementation of functions and constant values.\n\nso i want to codify that into the name of the class.\n\nhttps://realpython.com/python-mixin/\n\nin this case WatcherHelperMixin to indircate it provide helper function to interact with watcher.\n\nwe coudl have others liek PrometheusHelperMixin ectra in this file in the future if that was required in the future.","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8fa564b511ceaf74546096236151907e3da185c2","unresolved":false,"context_lines":[{"line_number":74,"context_line":"    SUPERSEDED \u003d \u0027SUPERSEDED\u0027"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"class BaseCommon:"},{"line_number":78,"context_line":"    \"\"\"Base class for audit, audit template, and action plan utilities.\"\"\""},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"    # States where the object is waiting for some event to perform a transition"}],"source_content_type":"text/x-python","patch_set":12,"id":"44c14422_500154a6","line":77,"range":{"start_line":77,"start_character":6,"end_line":77,"end_character":16},"in_reply_to":"108b3e6b_f5ad780c","updated":"2025-11-24 14:28:17.000000000","message":"good point, Done","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ac9e802db905a520acfa10af9f651be1b7993457","unresolved":true,"context_lines":[{"line_number":15,"context_line":"# limitations under the License."},{"line_number":16,"context_line":"#"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from enum import Enum"},{"line_number":19,"context_line":"from enum import EnumMeta"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"import functools"},{"line_number":22,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"e1f63c76_a4f4bed2","line":19,"range":{"start_line":18,"start_character":0,"end_line":19,"end_character":25},"updated":"2025-11-24 15:28:20.000000000","message":"these import are incorrect \n\nthis should be\n\nimport enum\nfrom collections import abc\n\nby the way i realsise that the example i provide did this incorrectly\n\nthat was one of the thigns that was commeted on in the reveiw and it was done by ai.\n\nwe need to be carful to now break teh codeign convetion when usign ai","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8c428ea97342a69fadce677cb07dc828314e1607","unresolved":false,"context_lines":[{"line_number":15,"context_line":"# limitations under the License."},{"line_number":16,"context_line":"#"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from enum import Enum"},{"line_number":19,"context_line":"from enum import EnumMeta"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"import functools"},{"line_number":22,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"2d4a0bd0_8fee88f5","line":19,"range":{"start_line":18,"start_character":0,"end_line":19,"end_character":25},"in_reply_to":"e1f63c76_a4f4bed2","updated":"2025-11-25 06:36:17.000000000","message":"Done","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ac9e802db905a520acfa10af9f651be1b7993457","unresolved":true,"context_lines":[{"line_number":95,"context_line":"    # States where the object can only be DELETED (end of its life-cycle)"},{"line_number":96,"context_line":"    AUDIT_FINISHED_STATES \u003d tuple(s.value for s in AuditFinishedStates)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    ACTIONPLANS_FINISHED_STATES \u003d tuple("},{"line_number":99,"context_line":"        s.value for s in ActionPlanFinishedStates)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    # ### AUDIT TEMPLATES ### #"}],"source_content_type":"text/x-python","patch_set":13,"id":"701ce053_dd4e5b86","line":98,"range":{"start_line":98,"start_character":4,"end_line":98,"end_character":31},"updated":"2025-11-24 15:28:20.000000000","message":"nit: ACTIONPLANS_FINISHED_STATES -\u003e ACTIONPLAN_FINISHED_STATES\n\nwe shoudl use the singular noun to be consitent with the rest.","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8c428ea97342a69fadce677cb07dc828314e1607","unresolved":false,"context_lines":[{"line_number":95,"context_line":"    # States where the object can only be DELETED (end of its life-cycle)"},{"line_number":96,"context_line":"    AUDIT_FINISHED_STATES \u003d tuple(s.value for s in AuditFinishedStates)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    ACTIONPLANS_FINISHED_STATES \u003d tuple("},{"line_number":99,"context_line":"        s.value for s in ActionPlanFinishedStates)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    # ### AUDIT TEMPLATES ### #"}],"source_content_type":"text/x-python","patch_set":13,"id":"8defc3c1_fb778f7e","line":98,"range":{"start_line":98,"start_character":4,"end_line":98,"end_character":31},"in_reply_to":"701ce053_dd4e5b86","updated":"2025-11-25 06:36:17.000000000","message":"Done","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"ac9e802db905a520acfa10af9f651be1b7993457","unresolved":true,"context_lines":[{"line_number":89,"context_line":"class WatcherHelperMixin:"},{"line_number":90,"context_line":"    \"\"\"Mixin class providing helper utilities for Watcher resources.\"\"\""},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    # States where the object is waiting for some event to perform a transition"},{"line_number":93,"context_line":"    IDLE_STATES \u003d tuple(s.value for s in IdleStates)"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    # States where the object can only be DELETED (end of its life-cycle)"},{"line_number":96,"context_line":"    AUDIT_FINISHED_STATES \u003d tuple(s.value for s in AuditFinishedStates)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    ACTIONPLANS_FINISHED_STATES \u003d tuple("},{"line_number":99,"context_line":"        s.value for s in ActionPlanFinishedStates)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    # ### AUDIT TEMPLATES ### #"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"    def create_audit_template(self, goal, name\u003dNone, description\u003dNone,"}],"source_content_type":"text/x-python","patch_set":13,"id":"b254c63e_9eae6a51","line":100,"range":{"start_line":92,"start_character":4,"end_line":100,"end_character":1},"updated":"2025-11-24 15:28:20.000000000","message":"we can have these aliases fi we want to avoid importing the moduel to use the enums\nbut we do not need to convert these to tuples\n\nthe enuma metaclass implement __contains__ so we can just do `\"value\" in Enum`\nhttps://docs.python.org/3/library/enum.html#enum.EnumType.__contains__\n\nthe only complication with that is \n\nBefore Python 3.12, a TypeError is raised if a the value is not in the set of values of the enum instead of returning false.\n\nso that is an arguemtn to have a better interface but if we were to do that\n\ninstead of just useign a set which make lookup O(1)\nIDLE_STATES \u003d {s.value for s in IdleStates}\n\nwe coudl instead make the FrozenEnumMeta implemtne the mapping interface\n\n```\nclass FrozenEnumMeta(enum.EnumMeta, abc.Mapping):\n    \"\"\"Prevent creation of new attributes and behave like a mapping.\"\"\"\n\n    def __getattr__(self, name):\n        if name not in self._member_map_:\n            raise AttributeError(\n                f\u0027{self.__class__.__name__} {self.__name__} has no attribute {name!r}\u0027\n            )\n        return super().__getattr__(name)\n\n    def __setattr__(self, name, value):\n        if name in self.__dict__ or name in self._member_map_:\n            return super().__setattr__(name, value)\n        raise AttributeError(\n            f\u0027{self.__class__.__name__} {self.__name__} has no attribute {name!r}\u0027\n        )\n\n    # Mapping interface\n\n    def keys(self):\n        return abc.KeysView(self)\n\n    def items(self):\n        return abc.ItemsView(self)\n\n    def values(self):\n        return abc.ValuesView(self)\n```\n\nthis would allow you to do \n\n\"value\" in Myenum.values()\n\nthe same way we can with standard collections\n\nhttps://docs.python.org/3/library/stdtypes.html#dict.values\n\nthis avoid the need to conver the enuma values into a tuple or set and levertes the existing\nvaluesview object form teh backing member dictionary.\nhttps://docs.python.org/3/library/stdtypes.html#dictionary-view-objects","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"cd5cb0ddabb7e64ad056c03432af91794c5db0bf","unresolved":false,"context_lines":[{"line_number":89,"context_line":"class WatcherHelperMixin:"},{"line_number":90,"context_line":"    \"\"\"Mixin class providing helper utilities for Watcher resources.\"\"\""},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    # States where the object is waiting for some event to perform a transition"},{"line_number":93,"context_line":"    IDLE_STATES \u003d tuple(s.value for s in IdleStates)"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    # States where the object can only be DELETED (end of its life-cycle)"},{"line_number":96,"context_line":"    AUDIT_FINISHED_STATES \u003d tuple(s.value for s in AuditFinishedStates)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    ACTIONPLANS_FINISHED_STATES \u003d tuple("},{"line_number":99,"context_line":"        s.value for s in ActionPlanFinishedStates)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    # ### AUDIT TEMPLATES ### #"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"    def create_audit_template(self, goal, name\u003dNone, description\u003dNone,"}],"source_content_type":"text/x-python","patch_set":13,"id":"3cd985df_19714bcf","line":100,"range":{"start_line":92,"start_character":4,"end_line":100,"end_character":1},"in_reply_to":"8c8f5c2b_a0af2205","updated":"2025-11-25 11:53:14.000000000","message":"actully i think its becasue FrozenEnumMeta is uses as a metaclass so\nit cant also have a abstraact base class.\n\nbut cool using maping as a base clase is not actully required.","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8c428ea97342a69fadce677cb07dc828314e1607","unresolved":true,"context_lines":[{"line_number":89,"context_line":"class WatcherHelperMixin:"},{"line_number":90,"context_line":"    \"\"\"Mixin class providing helper utilities for Watcher resources.\"\"\""},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    # States where the object is waiting for some event to perform a transition"},{"line_number":93,"context_line":"    IDLE_STATES \u003d tuple(s.value for s in IdleStates)"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    # States where the object can only be DELETED (end of its life-cycle)"},{"line_number":96,"context_line":"    AUDIT_FINISHED_STATES \u003d tuple(s.value for s in AuditFinishedStates)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    ACTIONPLANS_FINISHED_STATES \u003d tuple("},{"line_number":99,"context_line":"        s.value for s in ActionPlanFinishedStates)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    # ### AUDIT TEMPLATES ### #"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"    def create_audit_template(self, goal, name\u003dNone, description\u003dNone,"}],"source_content_type":"text/x-python","patch_set":13,"id":"8c8f5c2b_a0af2205","line":100,"range":{"start_line":92,"start_character":4,"end_line":100,"end_character":1},"in_reply_to":"b254c63e_9eae6a51","updated":"2025-11-25 06:36:17.000000000","message":"Thank you the code links, yes, it is working.\nWhile using abc.mapping, I was hitting following error:\n```\nwatcher_tempest_plugin.tests.api.admin.test_action.TestShowListAction.test_list_actions_by_action_plan[id-570ef821-af69-473d-989d-bbe86b585a78,smoke]\n-----------------------------------------------------------------------------------------------------------------------------------------------------\n\nCaptured traceback:\n~~~~~~~~~~~~~~~~~~~\n    Traceback (most recent call last):\n\n      File \"/home/ubuntu/repos/watcher-tempest-plugin/watcher_tempest_plugin/tests/api/admin/test_action.py\", line 96, in test_list_actions_by_action_plan\n    action_counter \u003d collections.Counter(\n                     ^^^^^^^^^^^^^^^^^^^^\n\n      File \"/usr/lib/python3.12/collections/__init__.py\", line 607, in __init__\n    self.update(iterable, **kwds)\n\n      File \"/usr/lib/python3.12/collections/__init__.py\", line 690, in update\n    if isinstance(iterable, _collections_abc.Mapping):\n       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n      File \"\u003cfrozen abc\u003e\", line 119, in __instancecheck__\n\n      File \"\u003cfrozen abc\u003e\", line 123, in __subclasscheck__\n\n      File \"\u003cfrozen abc\u003e\", line 123, in __subclasscheck__\n\n    TypeError: unbound method type.__subclasses__() needs an argument\n\n```\nI think enum.EnumMeta and abc.Mapping functinalities conflicts with each other. Dropping abc.Mapping works perfectly here.","commit_id":"3a98df90c5e03b0514530af96d8f627247d62a84"}],"watcher_tempest_plugin/tests/scenario/base.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c93885086999c3bb7888576267315112565033ef","unresolved":true,"context_lines":[{"line_number":43,"context_line":"    api_microversion_fixture as watcher_microversion_fixture"},{"line_number":44,"context_line":")"},{"line_number":45,"context_line":"from watcher_tempest_plugin.tests.common.base import AuditFinishedStates"},{"line_number":46,"context_line":"from watcher_tempest_plugin.tests.common.base import BaseCommon"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"LOG \u003d log.getLogger(__name__)"}],"source_content_type":"text/x-python","patch_set":12,"id":"ee0ceb13_35e1d965","line":46,"updated":"2025-11-24 13:39:44.000000000","message":"importing classes or constnats is not allowed by openstack codign convetions\n\n\n```suggestion\nfrom watcher_tempest_plugin.tests.common import base\n```\n\nhttps://github.com/openstack/hacking/blob/master/HACKING.rst?plain\u003d1#L57\n\nuse base.AuditFinishedStates extra if requried.","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8fa564b511ceaf74546096236151907e3da185c2","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    api_microversion_fixture as watcher_microversion_fixture"},{"line_number":44,"context_line":")"},{"line_number":45,"context_line":"from watcher_tempest_plugin.tests.common.base import AuditFinishedStates"},{"line_number":46,"context_line":"from watcher_tempest_plugin.tests.common.base import BaseCommon"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"LOG \u003d log.getLogger(__name__)"}],"source_content_type":"text/x-python","patch_set":12,"id":"23e974b8_7167112c","line":46,"in_reply_to":"ee0ceb13_35e1d965","updated":"2025-11-24 14:28:17.000000000","message":"Done","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c93885086999c3bb7888576267315112565033ef","unresolved":true,"context_lines":[{"line_number":60,"context_line":"NOVA_API_VERSION_SERVER_PINNED_AZ \u003d \u00272.96\u0027"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"class BaseInfraOptimScenarioTest(BaseCommon, manager.ScenarioTest):"},{"line_number":64,"context_line":"    \"\"\"Base class for Infrastructure Optimization API tests.\"\"\""},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    # Default Goal and Strategy to be defined in each test class that inherit"}],"source_content_type":"text/x-python","patch_set":12,"id":"c1ebe1e9_b0c2a19c","line":63,"range":{"start_line":63,"start_character":33,"end_line":63,"end_character":43},"updated":"2025-11-24 13:39:44.000000000","message":"by convention mixin calls are put after the normal base classs\n```\nclass BaseInfraOptimScenarioTest(manager.ScenarioTest, base.BaseCommon):\n```\n\nalthough if you take my other suggestions it would looke like this\n\n```suggestion\nclass BaseInfraOptimScenarioTest(manager.ScenarioTest, base.WatcherHelperMixin):\n```","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8fa564b511ceaf74546096236151907e3da185c2","unresolved":false,"context_lines":[{"line_number":60,"context_line":"NOVA_API_VERSION_SERVER_PINNED_AZ \u003d \u00272.96\u0027"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"class BaseInfraOptimScenarioTest(BaseCommon, manager.ScenarioTest):"},{"line_number":64,"context_line":"    \"\"\"Base class for Infrastructure Optimization API tests.\"\"\""},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    # Default Goal and Strategy to be defined in each test class that inherit"}],"source_content_type":"text/x-python","patch_set":12,"id":"a05abab4_b0c2cd5a","line":63,"range":{"start_line":63,"start_character":33,"end_line":63,"end_character":43},"in_reply_to":"c1ebe1e9_b0c2a19c","updated":"2025-11-24 14:28:17.000000000","message":"Done","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"c93885086999c3bb7888576267315112565033ef","unresolved":true,"context_lines":[{"line_number":855,"context_line":"    @classmethod"},{"line_number":856,"context_line":"    def has_audit_finished(cls, audit_uuid):"},{"line_number":857,"context_line":"        _, audit \u003d cls.client.show_audit(audit_uuid)"},{"line_number":858,"context_line":"        return audit.get(\u0027state\u0027) in tuple("},{"line_number":859,"context_line":"            s.value for s in AuditFinishedStates)"},{"line_number":860,"context_line":""},{"line_number":861,"context_line":"    @classmethod"},{"line_number":862,"context_line":"    def is_audit_ongoing(cls, audit_uuid):"}],"source_content_type":"text/x-python","patch_set":12,"id":"35c93780_090268d1","line":859,"range":{"start_line":858,"start_character":37,"end_line":859,"end_character":49},"updated":"2025-11-24 13:39:44.000000000","message":"this can jsut be self.AUDIT_FINISHED_STATES because of https://review.opendev.org/c/openstack/watcher-tempest-plugin/+/967522/12/watcher_tempest_plugin/tests/common/base.py#84","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"8fa564b511ceaf74546096236151907e3da185c2","unresolved":false,"context_lines":[{"line_number":855,"context_line":"    @classmethod"},{"line_number":856,"context_line":"    def has_audit_finished(cls, audit_uuid):"},{"line_number":857,"context_line":"        _, audit \u003d cls.client.show_audit(audit_uuid)"},{"line_number":858,"context_line":"        return audit.get(\u0027state\u0027) in tuple("},{"line_number":859,"context_line":"            s.value for s in AuditFinishedStates)"},{"line_number":860,"context_line":""},{"line_number":861,"context_line":"    @classmethod"},{"line_number":862,"context_line":"    def is_audit_ongoing(cls, audit_uuid):"}],"source_content_type":"text/x-python","patch_set":12,"id":"1393339c_160817bb","line":859,"range":{"start_line":858,"start_character":37,"end_line":859,"end_character":49},"in_reply_to":"35c93780_090268d1","updated":"2025-11-24 14:28:17.000000000","message":"Done","commit_id":"7827beb5531d4c32bab56aefb65e5a75269150d5"}]}
