|
7 | 7 | from pydantic import BaseModel, Field
|
8 | 8 | from rich.console import Console
|
9 | 9 |
|
10 |
| -EXCLUDE_COMMENT = 'pragma: no cover' |
11 | 10 |
|
12 |
| - |
13 |
| -def main() -> int: |
| 11 | +def main(exclude_comment: str = 'pragma: no cover') -> int: |
14 | 12 | with NamedTemporaryFile(suffix='.json') as coverage_json:
|
15 | 13 | with NamedTemporaryFile(mode='w', suffix='.toml') as config_file:
|
16 |
| - config_file.write(f"[tool.coverage.report]\nexclude_lines = ['{EXCLUDE_COMMENT}']\n") |
| 14 | + config_file.write(f"[tool.coverage.report]\nexclude_lines = ['{exclude_comment}']\n") |
17 | 15 | config_file.flush()
|
18 | 16 | p = subprocess.run(
|
19 | 17 | ['uv', 'run', 'coverage', 'json', f'--rcfile={config_file.name}', '-o', coverage_json.name],
|
20 | 18 | stdout=subprocess.PIPE,
|
| 19 | + stderr=subprocess.STDOUT, |
21 | 20 | )
|
22 | 21 | if p.returncode != 0:
|
23 |
| - print(f'Error running coverage: {p.stderr.decode()}', file=sys.stderr) |
| 22 | + print(f'Error running coverage:\n{p.stdout.decode()}', file=sys.stderr) |
24 | 23 | return p.returncode
|
25 | 24 |
|
26 | 25 | r = CoverageReport.model_validate_json(coverage_json.read())
|
@@ -64,12 +63,12 @@ def add_block(start: int, end: int):
|
64 | 63 |
|
65 | 64 | console = Console()
|
66 | 65 | if blocks:
|
67 |
| - console.print(f"❎ {total_lines} lines marked with '{EXCLUDE_COMMENT}' and covered") |
| 66 | + console.print(f"❎ {total_lines} lines marked with '{exclude_comment}' and covered") |
68 | 67 | for block in blocks:
|
69 | 68 | console.print(block)
|
70 | 69 | return 1
|
71 | 70 | else:
|
72 |
| - console.print(f"✅ No lines wrongly marked with '{EXCLUDE_COMMENT}'") |
| 71 | + console.print(f"✅ No lines wrongly marked with '{exclude_comment}'") |
73 | 72 | return 0
|
74 | 73 |
|
75 | 74 |
|
@@ -101,14 +100,14 @@ class CoverageReport(BaseModel):
|
101 | 100 |
|
102 | 101 | # python expressions that can open blocks so can have the `# pragma: no cover` comment on them
|
103 | 102 | # even though they're covered
|
104 |
| -BLOCK_OPENINGS = re.compile(r'\s*(?:def|async def|@|class|if|elif|else)') |
| 103 | +BLOCK_OPENINGS = re.compile(rb'\s*(?:def|async def|@|class|if|elif|else)') |
105 | 104 |
|
106 | 105 |
|
107 | 106 | class CodeAnalyzer:
|
108 | 107 | def __init__(self, file_path: str) -> None:
|
109 |
| - with open(file_path) as f: |
| 108 | + with open(file_path, 'rb') as f: |
110 | 109 | content = f.read()
|
111 |
| - self.lines: dict[int, str] = dict(enumerate(content.splitlines(), start=1)) |
| 110 | + self.lines: dict[int, bytes] = dict(enumerate(content.splitlines(), start=1)) |
112 | 111 |
|
113 | 112 | def all_block_openings(self, start: int, end: int) -> bool:
|
114 | 113 | return all(self._is_block_opening(line_no) for line_no in range(start, end + 1))
|
|
0 commit comments