)]}'
{"watcher_dashboard/api/watcher.py":[{"robot_id":"zuul","robot_run_id":"e21c5b66a73942f78897a4399a4e9f92","url":"https://zuul.teim.app/t/main/buildset/e21c5b66a73942f78897a4399a4e9f92","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"2dde1f964cdd3bb6f385f2fcd32e63fbaedf13b1","patch_set":2,"id":"81e81466_722cb656","line":48,"updated":"2026-03-30 15:38:11.000000000","message":"insert_watcher_policy_file() in watcher.py uses a hardcoded \u0027infra-optim\u0027 string instead of referencing common_client.WATCHER_SERVICE. The refactored code reintroduced a magic string that the original avoided.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: If the service type string \u0027infra-optim\u0027 is ever changed in common_client.WATCHER_SERVICE, this hardcoded value would not be updated, causing the policy file existence check to silently pass when it should fail, or fail when it should pass.\n\n**Suggestion**:\nReplace the hardcoded \u0027infra-optim\u0027 string with common_client.WATCHER_SERVICE to maintain the original coupling. The line should read: if common_client.WATCHER_SERVICE not in config.get_policy_files(): config.set_policy_file(common_client.WATCHER_SERVICE, \u0027watcher_policy.yaml\u0027)","commit_id":"97a6e1e2de27477e4d216158cc21db6626f84263"},{"robot_id":"zuul","robot_run_id":"5a31855b8e674c1fb72302a111550aad","url":"https://zuul.teim.app/t/main/buildset/5a31855b8e674c1fb72302a111550aad","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"007dd8cbe2df4482e1b12d7c5cab68b14b799b45","patch_set":3,"id":"b502f93a_7d5fc278","line":49,"updated":"2026-04-04 01:48:39.000000000","message":"insert_watcher_policy_file calls config.get_policy_files() to check for key existence, then config.set_policy_file() which internally re-reads settings.POLICY_FILES, causing a redundant dict read.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Eliminating the redundant read would make the function slightly more efficient, though the performance impact is negligible since it runs once per watcherclient() call.\n\n**Recommendation**:\nThe current approach is clear and correct. If efficiency becomes a concern, set_policy_file could return a boolean indicating whether the key was newly added, allowing the caller to skip the existence check entirely.","commit_id":"6bf0ac6676d604ccf12478788382a9e9a33ae116"}],"watcher_dashboard/config.py":[{"robot_id":"zuul","robot_run_id":"39ad3327df264e1b83c3018f790fe564","url":"https://zuul.teim.app/t/main/buildset/39ad3327df264e1b83c3018f790fe564","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"fa6a643fbd7fa63b4ce40e8dd92a0b0f4dd77327","patch_set":1,"id":"0d19cee0_0937910c","line":27,"updated":"2026-02-28 12:35:37.000000000","message":"Consider adding logging for config value lookups\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Debug logging would help troubleshoot configuration issues in production environments.\n\n**Recommendation**:\nConsider adding LOG.debug statements in the getter functions to log when settings are retrieved (especially on cache miss). This would aid debugging without impacting performance significantly.","commit_id":"4d595335a3bb947ed77d57a3efcb8f478ecb835e"},{"robot_id":"zuul","robot_run_id":"39ad3327df264e1b83c3018f790fe564","url":"https://zuul.teim.app/t/main/buildset/39ad3327df264e1b83c3018f790fe564","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"fa6a643fbd7fa63b4ce40e8dd92a0b0f4dd77327","patch_set":1,"id":"c105351a_59344946","line":40,"updated":"2026-02-28 12:35:37.000000000","message":"Type hint uses PEP 695 syntax (str | None) which requires Python 3.10+\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: The code uses modern type hint syntax that requires Python 3.10+. While the project specifies Python 3.10+ in pyproject.toml, this should be verified for runtime compatibility with older Python versions if any exist in deployment environments.\n\n**Suggestion**:\nThe project configuration shows requires-python \u003d \"\u003e\u003d3.10\", so PEP 695 syntax is acceptable. However, consider using typing.Optional[str] for broader compatibility if the code might run on Python 3.9. If Python 3.10+ is guaranteed, current syntax is fine.","commit_id":"4d595335a3bb947ed77d57a3efcb8f478ecb835e"},{"robot_id":"zuul","robot_run_id":"39ad3327df264e1b83c3018f790fe564","url":"https://zuul.teim.app/t/main/buildset/39ad3327df264e1b83c3018f790fe564","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"fa6a643fbd7fa63b4ce40e8dd92a0b0f4dd77327","patch_set":1,"id":"fb4cf1f5_112ed9c7","line":68,"updated":"2026-02-28 12:35:37.000000000","message":"Missing type validation for service and filename parameters in set_policy_file\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Adding explicit type checks would provide clearer error messages and prevent potential issues with non-string inputs.\n\n**Recommendation**:\nConsider adding isinstance checks: `if not isinstance(service, str) or not service:` and similarly for filename. This would provide more specific error handling for type mismatches rather than relying on truthiness checks alone.","commit_id":"4d595335a3bb947ed77d57a3efcb8f478ecb835e"},{"robot_id":"zuul","robot_run_id":"39ad3327df264e1b83c3018f790fe564","url":"https://zuul.teim.app/t/main/buildset/39ad3327df264e1b83c3018f790fe564","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"fa6a643fbd7fa63b4ce40e8dd92a0b0f4dd77327","patch_set":1,"id":"3827af9b_4ba06785","line":78,"updated":"2026-02-28 12:35:37.000000000","message":"set_policy_file may mutate settings.POLICY_FILES in place if it already exists\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: The function gets the existing POLICY_FILES dict, modifies it in place, then reassigns it. If POLICY_FILES already exists as a dict in settings, the in-place mutation could affect other code holding references to the original dict object.\n\n**Suggestion**:\nConsider creating a copy before modification to avoid unintended side effects: `policy_files \u003d dict(getattr(settings, \u0027POLICY_FILES\u0027, {}))`. This ensures isolation when modifying the dictionary.","commit_id":"4d595335a3bb947ed77d57a3efcb8f478ecb835e"},{"robot_id":"zuul","robot_run_id":"e21c5b66a73942f78897a4399a4e9f92","url":"https://zuul.teim.app/t/main/buildset/e21c5b66a73942f78897a4399a4e9f92","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"2dde1f964cdd3bb6f385f2fcd32e63fbaedf13b1","patch_set":2,"id":"caa1e0f6_e77e7cfd","line":17,"updated":"2026-03-30 15:38:11.000000000","message":"The module docstring in config.py references ``functools.lru_cache`` but the code uses ``@functools.cache``. The docstring should name the actual decorator.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Misleading documentation could confuse future maintainers who read the docstring and expect lru_cache semantics or try to use lru_cache-specific attributes like cache_info().maxsize.\n\n**Suggestion**:\nChange the docstring to reference ``functools.cache`` instead of ``functools.lru_cache``. The line in question is: \"Functions that return immutable values are cached with ``functools.lru_cache`` so repeated look-ups are free\". This should read: \"Functions that return immutable values are cached with ``functools.cache`` so repeated look-ups are free\".","commit_id":"97a6e1e2de27477e4d216158cc21db6626f84263"},{"robot_id":"zuul","robot_run_id":"5a31855b8e674c1fb72302a111550aad","url":"https://zuul.teim.app/t/main/buildset/5a31855b8e674c1fb72302a111550aad","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"007dd8cbe2df4482e1b12d7c5cab68b14b799b45","patch_set":3,"id":"81f306cf_36ac67bf","line":37,"updated":"2026-04-04 01:48:39.000000000","message":"get_ssl_no_verify coerces the setting value with bool(), which means the string \u0027False\u0027 would be treated as True. This may be surprising if a deployer sets OPENSTACK_SSL_NO_VERIFY\u003d\u0027False\u0027 in local_settings.py.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: More predictable handling of string-typed settings values, reducing the risk of a deployer accidentally enabling SSL bypass by setting the value to \u0027False\u0027 as a string.\n\n**Recommendation**:\nConsider adding a docstring note about the bool() coercion behaviour, or handling the string \u0027False\u0027 / \u00270\u0027 explicitly. The existing behaviour matches the original direct-attribute access pattern, so this is a documentation improvement rather than a code change.","commit_id":"6bf0ac6676d604ccf12478788382a9e9a33ae116"},{"robot_id":"zuul","robot_run_id":"5a31855b8e674c1fb72302a111550aad","url":"https://zuul.teim.app/t/main/buildset/5a31855b8e674c1fb72302a111550aad","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"007dd8cbe2df4482e1b12d7c5cab68b14b799b45","patch_set":3,"id":"f5764b79_40a4597b","line":41,"updated":"2026-04-04 01:48:39.000000000","message":"Return type annotation \u0027str | None\u0027 is a string literal rather than a proper type expression. Since the project targets Python 3.10+, the native union syntax can be used directly without quoting.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: The string-literal annotation is functionally correct at runtime but is inconsistent with the other annotations in the same file which use bare built-in types. Static type checkers (mypy, pyright) will treat the annotation differently than an unquoted type expression.\n\n**Suggestion**:\nChange the return annotation from \u0027\"str | None\"\u0027 to \u0027str | None\u0027 (unquoted). The project requires Python \u003e\u003d 3.10 (per pyproject.toml), so the native union syntax is available.","commit_id":"6bf0ac6676d604ccf12478788382a9e9a33ae116"},{"robot_id":"zuul","robot_run_id":"5a31855b8e674c1fb72302a111550aad","url":"https://zuul.teim.app/t/main/buildset/5a31855b8e674c1fb72302a111550aad","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"007dd8cbe2df4482e1b12d7c5cab68b14b799b45","patch_set":3,"id":"0acebe66_e87a894f","line":66,"updated":"2026-04-04 01:48:39.000000000","message":"get_policy_files returns dict(value) which is a shallow copy. If the dict values are themselves mutable (e.g. nested dicts), caller mutation of nested values could still affect the cached state.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Defensive copying would fully protect the cached dict from any form of caller mutation, even for deeply nested values.\n\n**Recommendation**:\nThe POLICY_FILES dict maps service names to policy file paths (strings), so shallow copy is sufficient for the current use case. If the schema ever changes to include mutable values, consider using copy.deepcopy or a frozen dataclass. A comment noting this assumption would improve clarity.","commit_id":"6bf0ac6676d604ccf12478788382a9e9a33ae116"},{"robot_id":"zuul","robot_run_id":"5a31855b8e674c1fb72302a111550aad","url":"https://zuul.teim.app/t/main/buildset/5a31855b8e674c1fb72302a111550aad","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"007dd8cbe2df4482e1b12d7c5cab68b14b799b45","patch_set":3,"id":"6c0bd425_ca115220","line":77,"updated":"2026-04-04 01:48:39.000000000","message":"set_policy_file validates that service and filename are non-empty strings via truthiness checks, but does not validate their type. Passing non-string values (e.g. integers) would pass the \u0027not service\u0027 check when the value is 0.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: An integer 0 would pass the \u0027not service\u0027 check while being an invalid type. In practice, callers pass string literals, so the risk is low but the validation is inconsistent with the strict type-checking pattern used in get_ssl_cacert and get_policy_files.\n\n**Suggestion**:\nAdd isinstance(service, str) and isinstance(filename, str) checks before the truthiness validation, matching the defensive pattern used in the read functions.","commit_id":"6bf0ac6676d604ccf12478788382a9e9a33ae116"},{"robot_id":"zuul","robot_run_id":"68f6e03b36e844f0972f6bbd7b05cb10","url":"https://zuul.teim.app/t/main/buildset/68f6e03b36e844f0972f6bbd7b05cb10","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"c6f1339c2b11ace00f7586528462829302344b31","patch_set":4,"id":"5cd934d9_1fb89554","line":29,"updated":"2026-04-30 18:40:21.000000000","message":"get_ssl_no_verify() uses @functools.cache on a setting that may be changed at runtime via override_settings in tests or dynamic reconfiguration. While ConfigMemoizedCache handles test isolation, production code cannot change this value after the first call within a process.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: If OPENSTACK_SSL_NO_VERIFY is changed at runtime (e.g., via Django settings override in production), the cached value will be stale. For the current usage pattern in watcher-dashboard this is unlikely to be an issue since these settings are typically set once at startup.\n\n**Suggestion**:\nAdd a brief note in the docstring that the cached value reflects the setting at first call and will not update if the setting is changed later. This makes the caching trade-off explicit for future maintainers.","commit_id":"0caf38892b8f11064c84a5752327b6c042a8485e"},{"robot_id":"zuul","robot_run_id":"68f6e03b36e844f0972f6bbd7b05cb10","url":"https://zuul.teim.app/t/main/buildset/68f6e03b36e844f0972f6bbd7b05cb10","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"c6f1339c2b11ace00f7586528462829302344b31","patch_set":4,"id":"de0323bc_c2615c18","line":62,"updated":"2026-04-30 18:40:21.000000000","message":"The get_policy_files() return type annotation is \u0027dict\u0027 without specifying key/value types. Using dict[str, str] would be more precise and consistent with the actual usage where both service names and filenames are strings.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: More precise type hints help static analysers and IDEs catch type mismatches earlier, and better document the expected data shape.\n\n**Recommendation**:\nChange the return type annotation from \u0027dict\u0027 to \u0027dict[str, str]\u0027 to match the actual usage pattern. This is valid syntax for the Python \u003e\u003d 3.10 baseline declared in pyproject.toml.","commit_id":"0caf38892b8f11064c84a5752327b6c042a8485e"},{"robot_id":"zuul","robot_run_id":"68f6e03b36e844f0972f6bbd7b05cb10","url":"https://zuul.teim.app/t/main/buildset/68f6e03b36e844f0972f6bbd7b05cb10","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"c6f1339c2b11ace00f7586528462829302344b31","patch_set":4,"id":"06541d13_4f9c78e3","line":62,"updated":"2026-04-30 18:40:21.000000000","message":"get_policy_files() uses @functools.cache but returns dict(value) -- the copy only happens on the first call. Subsequent calls return the SAME cached dict object. Caller mutation leaks into the cache, contradicting the docstring promise of copy-on-read protection.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: If any caller mutates the returned dict (e.g., policy_files[\u0027key\u0027] \u003d \u0027val\u0027), the mutation persists in the cache. This could cause stale or incorrect policy file mappings to be served to subsequent callers, potentially bypassing policy enforcement.\n\n**Priority**: Before merge\n**Why This Matters**: The docstring explicitly promises copy-on-read protection but functools.cache does not re-execute the function body, so no fresh copy is made after the first call. The documented contract is violated by the implementation.\n\n**Recommendation**:\nEither (a) remove @functools.cache from get_policy_files() and have it always return dict(getattr(settings, \u0027POLICY_FILES\u0027, {})), or (b) keep the cache but cache an internal value and return a fresh copy each time, or (c) remove the misleading docstring and document that callers must not mutate the return value.","commit_id":"0caf38892b8f11064c84a5752327b6c042a8485e"},{"robot_id":"zuul","robot_run_id":"68f6e03b36e844f0972f6bbd7b05cb10","url":"https://zuul.teim.app/t/main/buildset/68f6e03b36e844f0972f6bbd7b05cb10","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"c6f1339c2b11ace00f7586528462829302344b31","patch_set":4,"id":"057e04d4_e67aa5ad","line":85,"updated":"2026-04-30 18:40:21.000000000","message":"set_policy_file() reads getattr(settings, \u0027POLICY_FILES\u0027, {}) independently rather than calling get_policy_files(), creating a duplicate settings-read path that bypasses the cache layer.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Consolidating the settings read through get_policy_files() would eliminate the duplicated isinstance check and default-value logic, reducing the surface area for bugs if the setting name or default ever changes.\n\n**Recommendation**:\nConsider having set_policy_file() read the current value through the cached get_policy_files() (clearing the cache afterward as it already does), or at minimum extract the getattr+isinstance validation into a shared private helper to reduce duplication.","commit_id":"0caf38892b8f11064c84a5752327b6c042a8485e"}],"watcher_dashboard/test/unit/test_config.py":[{"robot_id":"zuul","robot_run_id":"39ad3327df264e1b83c3018f790fe564","url":"https://zuul.teim.app/t/main/buildset/39ad3327df264e1b83c3018f790fe564","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"fa6a643fbd7fa63b4ce40e8dd92a0b0f4dd77327","patch_set":1,"id":"9f1f43dd_dfdf06f1","line":73,"updated":"2026-02-28 12:35:37.000000000","message":"Test coverage for cache clearing behavior in set_policy_file\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Verifying cache invalidation ensures the caching strategy works correctly and prevents stale data issues.\n\n**Recommendation**:\nAdd a test that verifies get_policy_files.cache_clear() is called when set_policy_file is invoked. This could test that calling set_policy_file followed by get_policy_files returns the updated value, confirming the cache was cleared.","commit_id":"4d595335a3bb947ed77d57a3efcb8f478ecb835e"},{"robot_id":"zuul","robot_run_id":"e21c5b66a73942f78897a4399a4e9f92","url":"https://zuul.teim.app/t/main/buildset/e21c5b66a73942f78897a4399a4e9f92","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"2dde1f964cdd3bb6f385f2fcd32e63fbaedf13b1","patch_set":2,"id":"49245203_462ebb92","line":1,"updated":"2026-03-30 15:38:11.000000000","message":"The test file test_config.py uses a license header indented with a single space (\u0027# Licensed\u0027), while config.py uses four spaces (\u0027#    Licensed\u0027). The new file\u0027s header does not match the project convention.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: Consistent license headers across all files make the project look more polished and reduce noise in future license header audits or automated checks.\n\n**Recommendation**:\nAlign the license header indentation in test_config.py to match the project convention used in config.py: use \u0027#    Licensed\u0027 (4 spaces after \u0027#\u0027) for each license line.","commit_id":"97a6e1e2de27477e4d216158cc21db6626f84263"},{"robot_id":"zuul","robot_run_id":"5a31855b8e674c1fb72302a111550aad","url":"https://zuul.teim.app/t/main/buildset/5a31855b8e674c1fb72302a111550aad","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"007dd8cbe2df4482e1b12d7c5cab68b14b799b45","patch_set":3,"id":"d907d4ce_8c6fb29d","line":58,"updated":"2026-04-04 01:48:39.000000000","message":"The test file uses assertRaises without a context manager, which works but is less readable than the context manager form and does not assert the exception message.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Using assertRaises as a context manager and asserting the exception message would catch regressions if error messages change, and follows the preferred OpenStack testing pattern.\n\n**Recommendation**:\nConsider converting the assertRaises calls to context manager form and adding msg\u003d assertions for the TypeError and ValueError messages. This aligns with the style guide recommendation for more explicit test assertions.","commit_id":"6bf0ac6676d604ccf12478788382a9e9a33ae116"}],"watcher_dashboard/tests/local_fixtures/fixtures.py":[{"robot_id":"zuul","robot_run_id":"68f6e03b36e844f0972f6bbd7b05cb10","url":"https://zuul.teim.app/t/main/buildset/68f6e03b36e844f0972f6bbd7b05cb10","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"c6f1339c2b11ace00f7586528462829302344b31","patch_set":4,"id":"182bfd18_933554e8","line":26,"updated":"2026-04-30 18:40:21.000000000","message":"The ConfigMemoizedCache docstring mentions \u0027@functools.lru_cache\u0027 but config.py uses \u0027@functools.cache\u0027. While the mixin works correctly for both (both expose cache_clear), the docstring is slightly misleading about which decorator is actually used.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Minor documentation inaccuracy that could confuse future developers reading the test fixture code and trying to understand how caching works in config.py.\n\n**Suggestion**:\nUpdate the docstring to say \u0027functions decorated with @functools.cache or similar caching decorators\u0027 instead of specifically mentioning @functools.lru_cache.","commit_id":"0caf38892b8f11064c84a5752327b6c042a8485e"}],"watcher_dashboard/tests/unit/test_config.py":[{"robot_id":"zuul","robot_run_id":"68f6e03b36e844f0972f6bbd7b05cb10","url":"https://zuul.teim.app/t/main/buildset/68f6e03b36e844f0972f6bbd7b05cb10","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"c6f1339c2b11ace00f7586528462829302344b31","patch_set":4,"id":"b2d8887b_9da6eadb","line":13,"updated":"2026-04-30 18:40:21.000000000","message":"test_config.py imports \u0027settings\u0027 from django.conf at module level (line 13) but only uses it in one test method (test_set_policy_file_shallow_copy). Consider using override_settings or config.get_policy_files() instead for better test isolation.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Removing the direct settings import makes tests more self-contained and reinforces the pattern that all settings access should go through the config module, even in tests.\n\n**Recommendation**:\nIn test_set_policy_file_shallow_copy, capture the before state via config.get_policy_files() instead of settings.POLICY_FILES, allowing the direct settings import to be removed.","commit_id":"0caf38892b8f11064c84a5752327b6c042a8485e"}]}
