Option C Tools
Loading...
Searching...
No Matches
test_func_pattern.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# tests/tests_linter/test_func_pattern.py
4
5"""
6Purpose
7-------
8Validate the linter's func = "..." pattern detection logic.
9
10Responsibilities
11----------------
12- Confirm that compliant files pass check_func_pattern().
13- Confirm that non-compliant files fail check_func_pattern() with a
14 useful error message.
15- Confirm that trivial files (< 20 lines) are exempt from the check.
16- Confirm that functions with no _dbg() calls are not flagged.
17
18Diagnostics
19-----------
20Domain: LINTER-TESTS
21L2: test lifecycle
22L3: assertion details
23L4: deep tracing
24
25Contracts
26---------
27Inputs: temp_project_root pytest fixture (conftest.py)
28Outputs: pass/fail assertions
29"""
30
31from pathlib import Path
32from oct.linter import oct_lint
33
34
35def test_func_pattern_valid(temp_project_root: 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}"
41
42
43def test_func_pattern_missing(temp_project_root: Path):
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)
48 assert not ok
49 assert "func" in msg.lower()
50 assert "process" in msg or "helper" in msg
51
52
53def test_func_pattern_trivial_exempt(temp_project_root: Path):
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)
57 assert ok
58 assert msg == "trivial"
59
60
61def test_func_pattern_no_dbg_calls(temp_project_root: Path):
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)
66 assert ok
67
68
69def test_func_pattern_decorated(temp_project_root: Path):
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}"
75
76
77def test_func_pattern_async(temp_project_root: Path):
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}"
83
84
85def test_func_pattern_nested_inner_missing(temp_project_root: Path):
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"
91 assert "inner" in msg
92 assert "outer" not in msg
93
94
95def test_func_pattern_multiline_signature(temp_project_root: Path):
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}"
101
102
104 """func = '...' after a type annotation should pass (OI-409)."""
105 source = (
106 '# header\n' * 20
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'
113 )
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_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)