diff --git a/src/aipass/prax/.seedgo/bypass.json b/src/aipass/prax/.seedgo/bypass.json index 592382b2..a253ac3c 100644 --- a/src/aipass/prax/.seedgo/bypass.json +++ b/src/aipass/prax/.seedgo/bypass.json @@ -476,6 +476,21 @@ "file": "tests/test_operations.py", "standard": "encapsulation", "reason": "Unit tests must import handlers directly to test them in isolation. _load_ops() imports operations handler for unit testing. Same pattern as test_logging_handlers.py." + }, + { + "file": "tests/test_filesystem_handler.py", + "standard": "architecture", + "reason": "Test file lives in tests/ by convention, not in the 3-layer apps/ structure. This is standard for all prax test files." + }, + { + "file": "tests/test_filesystem_handler.py", + "standard": "log_structure", + "reason": "False positive — /home/ references are test fixture path strings (e.g. Path('/home/user/modules/logger.py')), not real log config." + }, + { + "file": "tests/test_filesystem_handler.py", + "standard": "documentation", + "reason": "Test helper functions use pytest naming conventions. Internal test stubs do not require docstrings." } ], "notes": { diff --git a/src/aipass/prax/tests/test_filesystem_handler.py b/src/aipass/prax/tests/test_filesystem_handler.py index 635f6693..0268aef4 100644 --- a/src/aipass/prax/tests/test_filesystem_handler.py +++ b/src/aipass/prax/tests/test_filesystem_handler.py @@ -19,8 +19,30 @@ import sys from pathlib import Path from unittest.mock import MagicMock, patch, mock_open as _mock_file_open +import pytest + _mopen = _mock_file_open +_INJECTED_MODULES = [ + "watchdog", + "watchdog.events", + "aipass.prax.apps.handlers.monitoring.event_queue", + "aipass.prax.apps.handlers.monitoring.branch_detector", + "aipass.prax.apps.handlers.monitoring.monitoring_filters", + "aipass.prax.apps.handlers.monitoring.filesystem_handler", +] + + +@pytest.fixture(autouse=True) +def _cleanup_injected_modules(): + """Remove mocked monitoring modules from sys.modules after each test.""" + saved = {k: sys.modules[k] for k in _INJECTED_MODULES if k in sys.modules} + yield + for k in _INJECTED_MODULES: + sys.modules.pop(k, None) + for k, v in saved.items(): + sys.modules[k] = v + # ============================================= # MODULE IMPORT HELPER diff --git a/src/aipass/prax/tests/test_log_watcher.py b/src/aipass/prax/tests/test_log_watcher.py index 548dac07..efab823c 100644 --- a/src/aipass/prax/tests/test_log_watcher.py +++ b/src/aipass/prax/tests/test_log_watcher.py @@ -1048,11 +1048,18 @@ class TestInitializePositionsAdditional: log_file = tmp_path / "bad.log" log_file.write_text("content\n", encoding="utf-8") + original_stat = Path.stat + + def failing_stat(self_path, *args, **kwargs): + """Fail stat only for .log files, not directory existence.""" + if str(self_path).endswith(".log"): + raise OSError("stat failed") + return original_stat(self_path, *args, **kwargs) + with ( patch.object(mod, "get_system_logs_dir", return_value=tmp_path), - patch.object(Path, "stat", side_effect=OSError("stat failed")), + patch.object(Path, "stat", failing_stat), ): - # Should not raise watcher.initialize_positions() assert str(log_file) not in watcher.log_positions diff --git a/src/aipass/seedgo/tests/test_coverage_audit.py b/src/aipass/seedgo/tests/test_coverage_audit.py index be4151f2..f644db10 100644 --- a/src/aipass/seedgo/tests/test_coverage_audit.py +++ b/src/aipass/seedgo/tests/test_coverage_audit.py @@ -8,6 +8,9 @@ # Modified: 2026-04-26 # ============================================= +# seedgo:bypass standard=architecture reason="test files live in tests/, not apps/" +# seedgo:bypass standard=encapsulation reason="tests import handlers directly for unit testing" + import types import pytest @@ -30,9 +33,7 @@ def _mock_infrastructure(monkeypatch): mock_json_handler = MagicMock() mock_json_handler.log_operation = MagicMock(return_value=True) mock_ignore_handler = MagicMock() - mock_ignore_handler.get_audit_ignore_patterns = MagicMock( - return_value=[] - ) + mock_ignore_handler.get_audit_ignore_patterns = MagicMock(return_value=[]) mock_scan_branch = MagicMock(return_value=None) # -- prax --------------------------------------------------------------- @@ -48,9 +49,7 @@ def _mock_infrastructure(monkeypatch): # -- seedgo json handler ------------------------------------------------ json_pkg = MagicMock() json_pkg.json_handler = mock_json_handler - monkeypatch.setitem( - sys.modules, "aipass.seedgo.apps.handlers.json", json_pkg - ) + monkeypatch.setitem(sys.modules, "aipass.seedgo.apps.handlers.json", json_pkg) json_mod = MagicMock() json_mod.log_operation = mock_json_handler.log_operation monkeypatch.setitem( @@ -62,9 +61,7 @@ def _mock_infrastructure(monkeypatch): # -- bypass handler ----------------------------------------------------- bypass_pkg = MagicMock() bypass_pkg.ignore_handler = mock_ignore_handler - monkeypatch.setitem( - sys.modules, "aipass.seedgo.apps.handlers.bypass", bypass_pkg - ) + monkeypatch.setitem(sys.modules, "aipass.seedgo.apps.handlers.bypass", bypass_pkg) monkeypatch.setitem( sys.modules, "aipass.seedgo.apps.handlers.bypass.ignore_handler", @@ -87,13 +84,13 @@ def _mock_infrastructure(monkeypatch): scanner_mod, ) - # -- audit package (must be a real module with __path__ so - # submodule imports like audit.audit_display work) -------------------- + # -- audit package (must be a real module with __path__ pointing to the + # actual directory so submodule imports like audit.audit_display work) audit_pkg = types.ModuleType("aipass.seedgo.apps.handlers.audit") - audit_pkg.__path__ = [] # type: ignore[attr-defined] - monkeypatch.setitem( - sys.modules, "aipass.seedgo.apps.handlers.audit", audit_pkg - ) + audit_pkg.__path__ = [ # type: ignore[attr-defined] + str(Path(__file__).resolve().parents[1] / "apps" / "handlers" / "audit") + ] + monkeypatch.setitem(sys.modules, "aipass.seedgo.apps.handlers.audit", audit_pkg) # Force re-imports so modules pick up fresh mocks for mod_name in [ @@ -201,10 +198,7 @@ class TestRenderViolations: ) mock_con = MagicMock() - violations = [ - {"path": f"/file{i}.py", "score": 10, "issues": []} - for i in range(8) - ] + violations = [{"path": f"/file{i}.py", "score": 10, "issues": []} for i in range(8)] _render_violations("naming", violations, mock_con) calls = [str(c) for c in mock_con.print.call_args_list] assert any("3 more" in c for c in calls) @@ -216,10 +210,7 @@ class TestRenderViolations: ) mock_con = MagicMock() - violations = [ - {"path": f"/file{i}.py", "score": 10, "issues": []} - for i in range(5) - ] + violations = [{"path": f"/file{i}.py", "score": 10, "issues": []} for i in range(5)] _render_violations("naming", violations, mock_con) calls = [str(c) for c in mock_con.print.call_args_list] assert not any("more" in c for c in calls) @@ -246,15 +237,7 @@ class TestRenderArchitectureViolations: ) mock_con = MagicMock() - audit_result = { - "results": { - "architecture": { - "checks": [ - {"passed": True, "name": "Dir: apps"} - ] - } - } - } + audit_result = {"results": {"architecture": {"checks": [{"passed": True, "name": "Dir: apps"}]}}} _render_architecture_violations(audit_result, mock_con) assert mock_con.print.call_count == 0 @@ -273,9 +256,7 @@ class TestRenderArchitectureViolations: "message": "x", }, ] - audit_result = { - "results": {"architecture": {"checks": checks}} - } + audit_result = {"results": {"architecture": {"checks": checks}}} _render_architecture_violations(audit_result, mock_con) calls = [str(c) for c in mock_con.print.call_args_list] assert any("ARCHITECTURE VIOLATIONS" in c for c in calls) @@ -295,9 +276,7 @@ class TestRenderArchitectureViolations: "message": "x", }, ] - audit_result = { - "results": {"architecture": {"checks": checks}} - } + audit_result = {"results": {"architecture": {"checks": checks}}} _render_architecture_violations(audit_result, mock_con) calls = [str(c) for c in mock_con.print.call_args_list] assert any("Missing files" in c for c in calls) @@ -316,9 +295,7 @@ class TestRenderArchitectureViolations: "message": "Something wrong", }, ] - audit_result = { - "results": {"architecture": {"checks": checks}} - } + audit_result = {"results": {"architecture": {"checks": checks}}} _render_architecture_violations(audit_result, mock_con) calls = [str(c) for c in mock_con.print.call_args_list] assert any("Something wrong" in c for c in calls) @@ -330,13 +307,8 @@ class TestRenderArchitectureViolations: ) mock_con = MagicMock() - checks = [ - {"passed": False, "name": f"Dir: dir{i}"} - for i in range(7) - ] - audit_result = { - "results": {"architecture": {"checks": checks}} - } + checks = [{"passed": False, "name": f"Dir: dir{i}"} for i in range(7)] + audit_result = {"results": {"architecture": {"checks": checks}}} _render_architecture_violations(audit_result, mock_con) calls = [str(c) for c in mock_con.print.call_args_list] assert any("2 more" in c for c in calls) @@ -348,13 +320,8 @@ class TestRenderArchitectureViolations: ) mock_con = MagicMock() - checks = [ - {"passed": False, "name": f"File: file{i}.py"} - for i in range(8) - ] - audit_result = { - "results": {"architecture": {"checks": checks}} - } + checks = [{"passed": False, "name": f"File: file{i}.py"} for i in range(8)] + audit_result = {"results": {"architecture": {"checks": checks}}} _render_architecture_violations(audit_result, mock_con) calls = [str(c) for c in mock_con.print.call_args_list] assert any("3 more" in c for c in calls) @@ -385,9 +352,7 @@ class TestRenderArchitectureViolations: "message": "Missing config", }, ] - audit_result = { - "results": {"architecture": {"checks": checks}} - } + audit_result = {"results": {"architecture": {"checks": checks}}} _render_architecture_violations(audit_result, mock_con) calls = [str(c) for c in mock_con.print.call_args_list] assert any("Missing directories" in c for c in calls) @@ -405,9 +370,7 @@ class TestRenderTypeErrors: ) mock_con = MagicMock() - _render_type_errors( - {"type_errors": 0, "files_checked": 0}, mock_con - ) + _render_type_errors({"type_errors": 0, "files_checked": 0}, mock_con) assert mock_con.print.call_count == 0 def test_no_type_errors_with_files_checked(self): @@ -417,9 +380,7 @@ class TestRenderTypeErrors: ) mock_con = MagicMock() - _render_type_errors( - {"type_errors": 0, "files_checked": 5}, mock_con - ) + _render_type_errors({"type_errors": 0, "files_checked": 5}, mock_con) calls = [str(c) for c in mock_con.print.call_args_list] assert any("No type errors" in c for c in calls) @@ -517,9 +478,7 @@ class TestRenderTestMap: ) mock_con = MagicMock() - _render_test_map( - {"test_map": {"total_functions": 0}}, mock_con - ) + _render_test_map({"test_map": {"total_functions": 0}}, mock_con) assert mock_con.print.call_count == 0 def test_test_map_with_data(self): @@ -564,9 +523,7 @@ class TestRenderDeprecatedPatterns: ) mock_con = MagicMock() - _render_deprecated_patterns( - {"deprecated_patterns": []}, mock_con - ) + _render_deprecated_patterns({"deprecated_patterns": []}, mock_con) assert mock_con.print.call_count == 0 def test_with_patterns(self): @@ -582,9 +539,7 @@ class TestRenderDeprecatedPatterns: "message": "Rename DOCUMENTS/ to docs/", }, ] - _render_deprecated_patterns( - {"deprecated_patterns": patterns}, mock_con - ) + _render_deprecated_patterns({"deprecated_patterns": patterns}, mock_con) calls = [str(c) for c in mock_con.print.call_args_list] assert any("DEPRECATED PATTERNS" in c for c in calls) assert any("DOCUMENTS" in c for c in calls) @@ -635,9 +590,7 @@ class TestPrintBranchSummary: "name": branch_name, "path": "/fake/path", }, - "scores": scores - if scores is not None - else {"architecture": 90, "naming": 80}, + "scores": scores if scores is not None else {"architecture": 90, "naming": 80}, "average": average, "files_checked": files_checked, "results": results if results is not None else {}, @@ -661,9 +614,7 @@ class TestPrintBranchSummary: print_branch_summary, ) - result = self._make_audit_result( - scores={"architecture": 95, "naming": 92}, average=93 - ) + result = self._make_audit_result(scores={"architecture": 95, "naming": 92}, average=93) print_branch_summary(result) def test_medium_scores(self): @@ -672,9 +623,7 @@ class TestPrintBranchSummary: print_branch_summary, ) - result = self._make_audit_result( - scores={"architecture": 80, "naming": 76}, average=78 - ) + result = self._make_audit_result(scores={"architecture": 80, "naming": 76}, average=78) print_branch_summary(result) def test_low_scores(self): @@ -683,9 +632,7 @@ class TestPrintBranchSummary: print_branch_summary, ) - result = self._make_audit_result( - scores={"architecture": 50, "naming": 60}, average=55 - ) + result = self._make_audit_result(scores={"architecture": 50, "naming": 60}, average=55) print_branch_summary(result) def test_odd_number_of_scores(self): @@ -895,9 +842,7 @@ class TestPrintSystemSummary: return { "branch": {"name": name}, "average": avg, - "scores": scores - if scores is not None - else {"architecture": avg, "naming": avg}, + "scores": scores if scores is not None else {"architecture": avg, "naming": avg}, "type_errors": type_errors, } @@ -977,12 +922,8 @@ class TestPrintSystemSummary: ) results = [ - self._make_result( - "a", 60, scores={"arch": 50, "naming": 70} - ), - self._make_result( - "b", 80, scores={"arch": 90, "naming": 70} - ), + self._make_result("a", 60, scores={"arch": 50, "naming": 70}), + self._make_result("b", 80, scores={"arch": 90, "naming": 70}), ] print_system_summary(results) @@ -1051,9 +992,7 @@ class TestDiscoverCheckers: standards_dir = tmp_path / "standards" standards_dir.mkdir() checker_file = standards_dir / "broken_check.py" - checker_file.write_text( - "raise RuntimeError('broken')\n", encoding="utf-8" - ) + checker_file.write_text("raise RuntimeError('broken')\n", encoding="utf-8") result = discover_checkers(standards_dir) assert "broken" not in result @@ -1135,9 +1074,7 @@ class TestCollectPyFiles: (apps_dir / "module.py").write_text("pass", encoding="utf-8") subdir = apps_dir / "handlers" subdir.mkdir() - (subdir / "handler.py").write_text( - "pass", encoding="utf-8" - ) + (subdir / "handler.py").write_text("pass", encoding="utf-8") result = _collect_py_files(tmp_path) names = [f["name"] for f in result] assert "module.py" in names @@ -1148,9 +1085,7 @@ class TestCollectPyFiles: """Files matching ignore patterns are excluded.""" import sys - mock_ign = sys.modules[ - "aipass.seedgo.apps.handlers.bypass" - ].ignore_handler + mock_ign = sys.modules["aipass.seedgo.apps.handlers.bypass"].ignore_handler mock_ign.get_audit_ignore_patterns.return_value = ["test_"] from aipass.seedgo.apps.handlers.audit.branch_audit import ( @@ -1159,12 +1094,8 @@ class TestCollectPyFiles: apps_dir = tmp_path / "apps" apps_dir.mkdir() - (apps_dir / "module.py").write_text( - "pass", encoding="utf-8" - ) - (apps_dir / "test_module.py").write_text( - "pass", encoding="utf-8" - ) + (apps_dir / "module.py").write_text("pass", encoding="utf-8") + (apps_dir / "test_module.py").write_text("pass", encoding="utf-8") result = _collect_py_files(tmp_path) names = [f["name"] for f in result] assert "module.py" in names @@ -1305,9 +1236,7 @@ class TestRunAllFiles: ) checker.FILE_FILTER = None files = [{"file": "/foo.py", "name": "foo.py"}] - violations, scores = _run_all_files( - checker, "naming", files, [] - ) + violations, scores = _run_all_files(checker, "naming", files, []) assert len(scores) == 1 assert scores[0] == 90 @@ -1318,14 +1247,10 @@ class TestRunAllFiles: ) checker = MagicMock() - checker.check_module = MagicMock( - side_effect=RuntimeError("boom") - ) + checker.check_module = MagicMock(side_effect=RuntimeError("boom")) checker.FILE_FILTER = None files = [{"file": "/foo.py", "name": "foo.py"}] - violations, scores = _run_all_files( - checker, "naming", files, [] - ) + violations, scores = _run_all_files(checker, "naming", files, []) assert violations == [] assert scores == [] @@ -1350,9 +1275,7 @@ class TestRunAllFiles: {"file": "/handler.py", "name": "handler.py"}, {"file": "/module.py", "name": "module.py"}, ] - violations, scores = _run_all_files( - checker, "naming", files, [] - ) + violations, scores = _run_all_files(checker, "naming", files, []) assert checker.check_module.call_count == 1 def test_skipped_checks_excluded(self): @@ -1376,9 +1299,7 @@ class TestRunAllFiles: ) checker.FILE_FILTER = None files = [{"file": "/foo.py", "name": "foo.py"}] - violations, scores = _run_all_files( - checker, "naming", files, [] - ) + violations, scores = _run_all_files(checker, "naming", files, []) assert scores == [] def test_failing_checks_collected(self): @@ -1400,9 +1321,7 @@ class TestRunAllFiles: ) checker.FILE_FILTER = None files = [{"file": "/bad.py", "name": "bad.py"}] - violations, scores = _run_all_files( - checker, "naming", files, [] - ) + violations, scores = _run_all_files(checker, "naming", files, []) assert len(violations) == 1 assert violations[0]["score"] == 40 assert "Bad naming" in violations[0]["issues"] @@ -1444,9 +1363,7 @@ class TestLoadDiagnosticsChecker: ) mock_spec = MagicMock() - mock_spec.loader.exec_module.side_effect = RuntimeError( - "fail" - ) + mock_spec.loader.exec_module.side_effect = RuntimeError("fail") with ( patch("pathlib.Path.exists", return_value=True), patch( @@ -1519,9 +1436,7 @@ def _make_checker( "score": 100, "checks": [], } - checker.check_module = MagicMock( - return_value=check_module_result or default_mod - ) + checker.check_module = MagicMock(return_value=check_module_result or default_mod) else: del checker.check_module @@ -1531,16 +1446,12 @@ def _make_checker( "score": 100, "checks": [], } - checker.check_branch = MagicMock( - return_value=check_branch_result or default_br - ) + checker.check_branch = MagicMock(return_value=check_branch_result or default_br) else: del checker.check_branch if has_post: - checker.check_branch_post = MagicMock( - return_value=post_result or ([], []) - ) + checker.check_branch_post = MagicMock(return_value=post_result or ([], [])) else: del checker.check_branch_post @@ -1566,9 +1477,7 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["branch"] == branch @@ -1600,16 +1509,12 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["scores"]["dead_code"] == 85 - def test_branch_level_checker_exception( - self, tmp_path, monkeypatch - ): + def test_branch_level_checker_exception(self, tmp_path, monkeypatch): """Branch-level checker that raises produces score 0.""" from aipass.seedgo.apps.handlers.audit import branch_audit @@ -1630,17 +1535,13 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["scores"]["broken"] == 0 assert "error" in result["results"]["broken"] - def test_entry_point_checker_exception( - self, tmp_path, monkeypatch - ): + def test_entry_point_checker_exception(self, tmp_path, monkeypatch): """Entry-point checker that raises produces score 0.""" from aipass.seedgo.apps.handlers.audit import branch_audit @@ -1657,9 +1558,7 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["scores"]["naming"] == 0 @@ -1671,9 +1570,7 @@ class TestAuditBranch: branch, branch_path = _setup_branch(tmp_path) apps_dir = Path(branch_path) / "apps" - (apps_dir / "other.py").write_text( - "pass", encoding="utf-8" - ) + (apps_dir / "other.py").write_text("pass", encoding="utf-8") checker = _make_checker( scope="all_files", @@ -1695,24 +1592,18 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["scores"]["naming"] == 80 - def test_all_files_with_violations( - self, tmp_path, monkeypatch - ): + def test_all_files_with_violations(self, tmp_path, monkeypatch): """all_files scope with failing checks updates results.""" from aipass.seedgo.apps.handlers.audit import branch_audit branch, branch_path = _setup_branch(tmp_path) apps_dir = Path(branch_path) / "apps" - (apps_dir / "bad.py").write_text( - "pass", encoding="utf-8" - ) + (apps_dir / "bad.py").write_text("pass", encoding="utf-8") def check_side_effect(path, bypass_rules=None): """Return different results based on path.""" @@ -1747,9 +1638,7 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert "naming_violations" in result @@ -1780,26 +1669,20 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) # Post check: (100 + 50) / 2 = 75 assert result["scores"]["naming"] == 75 assert len(result["naming_violations"]) == 1 - def test_post_check_raises_exception( - self, tmp_path, monkeypatch - ): + def test_post_check_raises_exception(self, tmp_path, monkeypatch): """check_branch_post that raises is caught.""" from aipass.seedgo.apps.handlers.audit import branch_audit branch, _ = _setup_branch(tmp_path) checker = _make_checker(has_post=True) - checker.check_branch_post.side_effect = RuntimeError( - "fail" - ) + checker.check_branch_post.side_effect = RuntimeError("fail") monkeypatch.setattr( branch_audit, "discover_checkers", @@ -1810,16 +1693,12 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["scores"]["naming"] == 100 - def test_diagnostics_checker_added( - self, tmp_path, monkeypatch - ): + def test_diagnostics_checker_added(self, tmp_path, monkeypatch): """Diagnostics checker loaded and added.""" from aipass.seedgo.apps.handlers.audit import branch_audit @@ -1847,16 +1726,12 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: diag_mod, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert "diagnostics" in result["scores"] - def test_deprecated_documents_dir( - self, tmp_path, monkeypatch - ): + def test_deprecated_documents_dir(self, tmp_path, monkeypatch): """DOCUMENTS/ directory detected as deprecated.""" from aipass.seedgo.apps.handlers.audit import branch_audit @@ -1873,18 +1748,14 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert len(result["deprecated_patterns"]) == 1 dep = result["deprecated_patterns"][0] assert dep["old"] == "DOCUMENTS/" - def test_no_deprecated_without_documents( - self, tmp_path, monkeypatch - ): + def test_no_deprecated_without_documents(self, tmp_path, monkeypatch): """No deprecated patterns without DOCUMENTS/.""" from aipass.seedgo.apps.handlers.audit import branch_audit @@ -1899,9 +1770,7 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["deprecated_patterns"] == [] @@ -1959,9 +1828,7 @@ class TestAuditBranch: result = branch_audit.audit_branch(branch, []) assert result["test_map"] == scan_result - def test_no_checkers_zero_average( - self, tmp_path, monkeypatch - ): + def test_no_checkers_zero_average(self, tmp_path, monkeypatch): """No checkers returns average 0.""" from aipass.seedgo.apps.handlers.audit import branch_audit @@ -1976,16 +1843,12 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["average"] == 0 - def test_implicit_branch_level( - self, tmp_path, monkeypatch - ): + def test_implicit_branch_level(self, tmp_path, monkeypatch): """Checker without check_module treated as branch-level.""" from aipass.seedgo.apps.handlers.audit import branch_audit @@ -2010,9 +1873,7 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["scores"]["implicit"] == 75 @@ -2029,25 +1890,19 @@ class TestAuditBranch: captured["value"] = pack_path return {} - monkeypatch.setattr( - branch_audit, "discover_checkers", mock_discover - ) + monkeypatch.setattr(branch_audit, "discover_checkers", mock_discover) monkeypatch.setattr( branch_audit, "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) pack = tmp_path / "custom_standards" branch_audit.audit_branch(branch, [], pack_path=pack) assert captured["value"] == pack - def test_diagnostics_not_duplicated( - self, tmp_path, monkeypatch - ): + def test_diagnostics_not_duplicated(self, tmp_path, monkeypatch): """Existing diagnostics not overwritten by loader.""" from aipass.seedgo.apps.handlers.audit import branch_audit @@ -2076,16 +1931,12 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: different, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["scores"]["diagnostics"] == 80 - def test_branch_level_violations_extraction( - self, tmp_path, monkeypatch - ): + def test_branch_level_violations_extraction(self, tmp_path, monkeypatch): """Branch-level results have violations extracted.""" from aipass.seedgo.apps.handlers.audit import branch_audit @@ -2123,16 +1974,12 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert len(result["dead_code_violations"]) == 1 - def test_output_diagnostics_fields( - self, tmp_path, monkeypatch - ): + def test_output_diagnostics_fields(self, tmp_path, monkeypatch): """Output includes type_errors and type_error_files.""" from aipass.seedgo.apps.handlers.audit import branch_audit @@ -2159,19 +2006,13 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["type_errors"] == 3 - assert result["type_error_files"] == [ - {"file": "a.py", "errors": 3} - ] + assert result["type_error_files"] == [{"file": "a.py", "errors": 3}] - def test_post_check_empty_scores( - self, tmp_path, monkeypatch - ): + def test_post_check_empty_scores(self, tmp_path, monkeypatch): """Post-check with empty scores does not change score.""" from aipass.seedgo.apps.handlers.audit import branch_audit @@ -2190,9 +2031,7 @@ class TestAuditBranch: "_load_diagnostics_checker", lambda: None, ) - monkeypatch.setattr( - branch_audit, "scan_branch", lambda p: None - ) + monkeypatch.setattr(branch_audit, "scan_branch", lambda p: None) result = branch_audit.audit_branch(branch, []) assert result["scores"]["naming"] == 100