8Validate the linter's func = "..." pattern detection logic.
12- Confirm that compliant files pass check_func_pattern().
13- Confirm that non-compliant files fail check_func_pattern() with a
15- Confirm that trivial files (< 20 lines) are exempt from the check.
16- Confirm that functions with no _dbg() calls are not flagged.
27Inputs: temp_project_root pytest fixture (conftest.py)
28Outputs: pass/fail assertions
31from pathlib
import Path
36 """Files where every _dbg()-using function defines func = "..." pass."""
37 fixture = temp_project_root /
"tests_linter" /
"fixtures" /
"dbg_with_func.py"
38 text = fixture.read_text(encoding=
"utf-8")
39 ok, msg = oct_lint.check_func_pattern(text)
40 assert ok, f
"Expected PASS but got: {msg}"
44 """Files where _dbg() is called without a preceding func = "..." fail."""
45 fixture = temp_project_root /
"tests_linter" /
"fixtures" /
"dbg_without_func.py"
46 text = fixture.read_text(encoding=
"utf-8")
47 ok, msg = oct_lint.check_func_pattern(text)
49 assert "func" in msg.lower()
50 assert "process" in msg
or "helper" in msg
54 """Files under 20 lines are exempt — same threshold as check_dbg_usage."""
55 short_text =
"#!/usr/bin/env python3\ndef f():\n _dbg('L2', 'x')\n"
56 ok, msg = oct_lint.check_func_pattern(short_text)
58 assert msg ==
"trivial"
62 """Functions that never call _dbg() do not need func = '...'."""
63 fixture = temp_project_root /
"tests_linter" /
"fixtures" /
"minimal_valid.py"
64 text = fixture.read_text(encoding=
"utf-8")
65 ok, msg = oct_lint.check_func_pattern(text)
70 """Decorated functions with correct func = '...' + _dbg() pass."""
71 fixture = temp_project_root /
"tests_linter" /
"fixtures" /
"decorated_func.py"
72 text = fixture.read_text(encoding=
"utf-8")
73 ok, msg = oct_lint.check_func_pattern(text)
74 assert ok, f
"Expected PASS but got: {msg}"
78 """Async functions with correct func = '...' + _dbg() pass."""
79 fixture = temp_project_root /
"tests_linter" /
"fixtures" /
"async_func.py"
80 text = fixture.read_text(encoding=
"utf-8")
81 ok, msg = oct_lint.check_func_pattern(text)
82 assert ok, f
"Expected PASS but got: {msg}"
86 """Nested function missing func = '...' fails independently of outer."""
87 fixture = temp_project_root /
"tests_linter" /
"fixtures" /
"nested_func.py"
88 text = fixture.read_text(encoding=
"utf-8")
89 ok, msg = oct_lint.check_func_pattern(text)
90 assert not ok,
"Expected FAIL for inner function missing func assignment"
92 assert "outer" not in msg
96 """Multi-line function signatures with correct pattern pass."""
97 fixture = temp_project_root /
"tests_linter" /
"fixtures" /
"multiline_sig.py"
98 text = fixture.read_text(encoding=
"utf-8")
99 ok, msg = oct_lint.check_func_pattern(text)
100 assert ok, f
"Expected PASS but got: {msg}"
104 """func = '...' after a type annotation should pass (OI-409)."""
107 +
'from oc_diagnostics import _dbg\n'
108 'def process(data: list) -> None:\n'
109 ' """Process data."""\n'
110 ' result: list = []\n'
111 ' func = "process"\n'
112 ' _dbg("GENERAL", 2, f"{func}: starting")\n'
114 ok, msg = oct_lint.check_func_pattern(source)
115 assert ok, f
"Expected PASS but got: {msg}"
test_func_pattern_trivial_exempt(Path temp_project_root)
test_func_pattern_after_type_annotation()
test_func_pattern_decorated(Path temp_project_root)
test_func_pattern_valid(Path temp_project_root)
test_func_pattern_async(Path temp_project_root)
test_func_pattern_nested_inner_missing(Path temp_project_root)
test_func_pattern_missing(Path temp_project_root)
test_func_pattern_no_dbg_calls(Path temp_project_root)
test_func_pattern_multiline_signature(Path temp_project_root)