blob: d1b184025a28a88d4403ac7466f3759a4958b641 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
"""Discipline test — every ``# pragma: no cover`` carries an inline reason.
The rule: pragmas are allowed only on individual lines, each with an inline
reason after the pragma text. File-level pragmas and bare pragmas without
a reason are banned outright — same discipline as the type-ignore rule.
"""
import io
import re
import tokenize
from collections.abc import Iterator
from pathlib import Path
import pytest
_REPO_ROOT = Path(__file__).parent.parent.parent
_EDIFY_ROOT = _REPO_ROOT / "edify"
_TESTS_ROOT = _REPO_ROOT / "tests"
_PRAGMA_LINE_PATTERN = re.compile(r"#\s*pragma:\s*no cover\b(.*)$")
def _every_python_file() -> Iterator[Path]:
for source_root in (_EDIFY_ROOT, _TESTS_ROOT):
yield from source_root.rglob("*.py")
def _pragma_comments(python_file: Path) -> Iterator[tuple[int, str, str]]:
source_text = python_file.read_text()
for token in tokenize.tokenize(io.BytesIO(source_text.encode("utf-8")).readline):
if token.type != tokenize.COMMENT:
continue
matched = _PRAGMA_LINE_PATTERN.search(token.string)
if matched is None:
continue
yield token.start[0], token.string, matched.group(1)
@pytest.mark.parametrize("python_file", sorted(_every_python_file()), ids=str)
def test_no_bare_pragma_no_cover_without_inline_reason(python_file: Path):
for line_number, comment_text, reason_suffix in _pragma_comments(python_file):
stripped_reason = reason_suffix.strip()
if stripped_reason == "" or stripped_reason[0] not in "—:-":
pytest.fail(
f"{python_file.relative_to(_REPO_ROOT)}:{line_number} carries "
f"{comment_text!r} without an inline reason. The rule is: every pragma "
"gets an em-dash-separated reason on the same line, e.g. "
"'# pragma: no cover — <why this branch is unreachable>'."
)
|