summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2019-03-02 08:39:51 +0100
committerStefan Behnel <stefan_ml@behnel.de>2019-03-02 08:39:51 +0100
commit869044783972599839e4915db742687609587dbb (patch)
treee1ea7625b519075d08222a71dd93f821c31b1762
parent02c019e4416cbacc5b228a7b5bd4c9d81fd6ced1 (diff)
downloadcython-869044783972599839e4915db742687609587dbb.tar.gz
Exclude non-executable lines from coverage analysis (anything that does not generate a line trace call).
-rw-r--r--Cython/Coverage.py16
1 files changed, 14 insertions, 2 deletions
diff --git a/Cython/Coverage.py b/Cython/Coverage.py
index fa2f0ede1..43b1bc9c5 100644
--- a/Cython/Coverage.py
+++ b/Cython/Coverage.py
@@ -191,6 +191,7 @@ class Plugin(CoveragePlugin):
match_source_path_line = re.compile(r' */[*] +"(.*)":([0-9]+)$').match
match_current_code_line = re.compile(r' *[*] (.*) # <<<<<<+$').match
match_comment_end = re.compile(r' *[*]/$').match
+ match_trace_line = re.compile(r' *__Pyx_TraceLine\(([0-9]+),').match
not_executable = re.compile(
r'\s*c(?:type)?def\s+'
r'(?:(?:public|external)\s+)?'
@@ -199,15 +200,20 @@ class Plugin(CoveragePlugin):
).match
code_lines = defaultdict(dict)
- filenames = set()
+ executable_lines = defaultdict(set)
+ current_filename = None
with open(c_file) as lines:
lines = iter(lines)
for line in lines:
match = match_source_path_line(line)
if not match:
+ if '__Pyx_TraceLine(' in line and current_filename is not None:
+ trace_line = match_trace_line(line)
+ if trace_line:
+ executable_lines[current_filename].add(int(trace_line.group(1)))
continue
filename, lineno = match.groups()
- filenames.add(filename)
+ current_filename = filename
lineno = int(lineno)
for comment_line in lines:
match = match_current_code_line(comment_line)
@@ -221,6 +227,12 @@ class Plugin(CoveragePlugin):
# unexpected comment format - false positive?
break
+ # Remove lines that generated code but are not traceable.
+ for filename, lines in code_lines.items():
+ dead_lines = set(lines).difference(executable_lines.get(filename, ()))
+ for lineno in dead_lines:
+ del lines[lineno]
+
self._parsed_c_files[c_file] = code_lines
if self._c_files_map is None: