""" Tests for the check-deprecated-settings-wrapper pre-commit hook. Covers regressions: - Previously, every call site of the deprecated wrapper produced *two* errors: one from the per-line string scan and another from the AST walk. Verify a single call site now produces exactly one error. - Comments and docstrings mentioning the deprecated name must not fire. Note: DEP is built at runtime to avoid embedding the literal deprecated name in this test file (the hook under test would otherwise flag its own test file). """ import subprocess import sys import tempfile from pathlib import Path HOOK_SCRIPT = ( Path(__file__).parent.parent.parent / ".pre-commit-hooks" / "check-deprecated-settings-wrapper.py" ) DEP = "get_setting_from" + "_db_main_thread" def _run_hook( content: str, filename: str = "service.py" ) -> subprocess.CompletedProcess: with tempfile.TemporaryDirectory() as d: path = Path(d) / filename path.parent.mkdir(parents=True, exist_ok=True) path.write_text(content) return subprocess.run( [sys.executable, str(HOOK_SCRIPT), str(path)], capture_output=True, text=True, ) def _count_line_errors(stdout: str) -> int: """Count lines of the form ' Line N: '.""" return sum( 1 for line in stdout.splitlines() if line.lstrip().startswith("Line ") ) class TestSingleErrorPerCallSite: """Regression: each call site must produce exactly one error, not two.""" def test_single_call_single_error(self): result = _run_hook(f"value = {DEP}('key')\n") assert result.returncode == 1 assert _count_line_errors(result.stdout) == 1 def test_single_import_single_error(self): result = _run_hook( f"from local_deep_research.utilities.db_utils import {DEP}\n" ) assert result.returncode == 1 assert _count_line_errors(result.stdout) == 1 def test_two_call_sites_two_errors(self): content = f"x = {DEP}('a')\ny = {DEP}('b')\n" result = _run_hook(content) assert result.returncode == 1 assert _count_line_errors(result.stdout) == 2 class TestCommentAndDocstringSkip: """Comments and docstring lines must not be flagged.""" def test_comment_not_flagged(self): result = _run_hook(f"# {DEP} is deprecated\n") assert result.returncode == 0 def test_docstring_line_not_flagged(self): result = _run_hook(f'"""{DEP} is deprecated."""\n') assert result.returncode == 0 def test_single_quote_docstring_not_flagged(self): result = _run_hook(f"'''{DEP} is deprecated.'''\n") assert result.returncode == 0 class TestFilesExempted: """db_utils.py and the hook itself must remain exempt.""" def test_db_utils_exempted(self): result = _run_hook(f"value = {DEP}('key')\n", filename="db_utils.py") assert result.returncode == 0 def test_test_file_exempted(self): result = _run_hook( f"value = {DEP}('key')\n", filename="test_db_utils.py" ) assert result.returncode == 0 class TestNoMentionShortCircuits: """Files that never mention the name must pass cleanly.""" def test_clean_file_passes(self): result = _run_hook("def hello(): return 'world'\n") assert result.returncode == 0