Option C Tools
Loading...
Searching...
No Matches
test_parsing.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# tests/tests_core/test_parsing.py
4
5"""
6Purpose
7-------
8OI-509 / FS-505 regression tests — :func:`oct.core.parsing.header_boundary`
9is the single implementation shared by the linter and the formatter for
10locating the start of file content after an Option-C 4-line header
11(shebang → encoding → file-identity → blank).
12
13Also covers :func:`oct.core.parsing.safe_parse` — shared AST helper that
14captures ``SyntaxWarning`` diagnostics instead of leaking them to stderr.
15
16Responsibilities
17----------------
18- Full 4-line header → boundary is 4.
19- Missing shebang → skips straight to encoding.
20- No header at all → boundary is 0.
21- Trailing blank is only consumed when at least one header element matched.
22- Identity comment is matched via either the strict expected string or the
23 path-basename fallback.
24- ``safe_parse`` returns (None, []) on syntax error.
25- ``safe_parse`` captures invalid-escape SyntaxWarnings without printing.
26
27Diagnostics
28-----------
29Domain: CORE-TESTS
30Levels:
31 L2 — test lifecycle
32 L3 — assertion details
33 L4 — deep tracing
34
35Contracts
36---------
37- Tests operate on in-memory strings; no files are created or read.
38"""
39
40from pathlib import Path
41
42from oct.core.parsing import header_boundary, safe_parse
43
44
45def _lines(text: str) -> list[str]:
46 return text.splitlines()
47
48
50 path = Path("oct/core/parsing.py")
51 text = (
52 "#!/usr/bin/env python3\n"
53 "# -*- coding: utf-8 -*-\n"
54 "# oct/core/parsing.py\n"
55 "\n"
56 "import os\n"
57 )
58 assert header_boundary(
59 _lines(text), path, expected_identity="# oct/core/parsing.py"
60 ) == 4
61
62
64 path = Path("oct/core/parsing.py")
65 text = (
66 "# -*- coding: utf-8 -*-\n"
67 "# oct/core/parsing.py\n"
68 "\n"
69 "import os\n"
70 )
71 assert header_boundary(
72 _lines(text), path, expected_identity="# oct/core/parsing.py"
73 ) == 3
74
75
77 path = Path("foo.py")
78 text = "import os\nprint('hi')\n"
79 assert header_boundary(_lines(text), path) == 0
80
81
83 path = Path("foo.py")
84 text = "\nimport os\n"
85 assert header_boundary(_lines(text), path) == 0
86
87
89 """When no expected_identity is passed, any `# ...basename` qualifies."""
90 path = Path("pkg/mod.py")
91 text = (
92 "#!/usr/bin/env python3\n"
93 "# some/other/prefix mod.py\n"
94 "\n"
95 "x = 1\n"
96 )
97 assert header_boundary(_lines(text), path) == 3
98
99
101 tree, warns = safe_parse("def broken(:\n")
102 assert tree is None
103 assert warns == []
104
105
107 src = 's = "\\d+"\n'
108 tree, warns = safe_parse(src)
109 assert tree is not None
110 assert any("invalid escape" in w for w in warns)
test_safe_parse_captures_invalid_escape_warning()
test_trailing_blank_not_consumed_without_header()
list[str] _lines(str text)