@@ -15,10 +15,13 @@ def main() -> int:
15
15
with NamedTemporaryFile (mode = 'w' , suffix = '.toml' ) as config_file :
16
16
config_file .write (f"[tool.coverage.report]\n exclude_lines = ['{ EXCLUDE_COMMENT } ']\n " )
17
17
config_file .flush ()
18
- subprocess .run (
18
+ p = subprocess .run (
19
19
['uv' , 'run' , 'coverage' , 'json' , f'--rcfile={ config_file .name } ' , '-o' , coverage_json .name ],
20
- check = True ,
20
+ stdout = subprocess . PIPE ,
21
21
)
22
+ if p .returncode != 0 :
23
+ print (f'Error running coverage: { p .stderr .decode ()} ' , file = sys .stderr )
24
+ return p .returncode
22
25
23
26
r = CoverageReport .model_validate_json (coverage_json .read ())
24
27
@@ -40,13 +43,11 @@ def add_block(start: int, end: int):
40
43
if code_analysise is None :
41
44
code_analysise = CodeAnalyzer (file_name )
42
45
43
- if all (code_analysise .is_expression_start (line_no ) for line_no in range (start , end + 1 )):
44
- return
45
-
46
- b = str (start ) if start == end else f'{ start } -{ end } '
47
- if not blocks or blocks [- 1 ] != b :
48
- total_lines += end - start + 1
49
- blocks .append (f' [link=file://{ cwd / file_name } ]{ file_name } { b } [/link]' )
46
+ if not code_analysise .all_block_openings (start , end ):
47
+ b = str (start ) if start == end else f'{ start } -{ end } '
48
+ if not blocks or blocks [- 1 ] != b :
49
+ total_lines += end - start + 1
50
+ blocks .append (f' [link=file://{ cwd / file_name } ]{ file_name } { b } [/link]' )
50
51
51
52
first_line , * rest = common_lines
52
53
current_start = current_end = first_line
@@ -98,7 +99,9 @@ class CoverageReport(BaseModel):
98
99
files : dict [str , FileCoverage ]
99
100
100
101
101
- EXPRESSION_START_REGEX = re .compile (r'\s*(?:def|async def|@|class|if|elif|else)' )
102
+ # python expressions that can open blocks so can have the `# pragma: no cover` comment on them
103
+ # even though they're covered
104
+ BLOCK_OPENINGS = re .compile (r'\s*(?:def|async def|@|class|if|elif|else)' )
102
105
103
106
104
107
class CodeAnalyzer :
@@ -107,9 +110,11 @@ def __init__(self, file_path: str) -> None:
107
110
content = f .read ()
108
111
self .lines : dict [int , str ] = dict (enumerate (content .splitlines (), start = 1 ))
109
112
110
- def is_expression_start (self , line_no : int ) -> bool :
111
- line = self .lines [line_no ]
112
- return bool (EXPRESSION_START_REGEX .match (line ))
113
+ def all_block_openings (self , start : int , end : int ) -> bool :
114
+ return all (self ._is_block_opening (line_no ) for line_no in range (start , end + 1 ))
115
+
116
+ def _is_block_opening (self , line_no : int ) -> bool :
117
+ return bool (BLOCK_OPENINGS .match (self .lines [line_no ]))
113
118
114
119
115
120
if __name__ == '__main__' :
0 commit comments