aboutsummaryrefslogtreecommitdiff
path: root/tests/discipline/pragmas.test.py
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>'."
            )