Created
October 4, 2022 02:38
-
-
Save groner/0ba32d4489b6c865318098e26cd84cc5 to your computer and use it in GitHub Desktop.
coverage.py crossreferencer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from argparse import ArgumentParser | |
from os import fspath | |
from pathlib import Path | |
import re | |
import sys | |
from textwrap import dedent | |
from coverage import Coverage | |
from coverage.exceptions import NotPython | |
def main(): | |
parser = ArgumentParser( | |
description=dedent('''\ | |
Cross reference fn:ln annotated text with python coverage database | |
example usage: | |
:; git grep -n some_function | python3 coverage-xref.py -v | |
''')) | |
parser.add_argument( | |
'-v', dest='invert', action='store_true', help='Match unexecuted lines') | |
parser.add_argument( | |
'-s', dest='silent', action='store_true', help='Supress error messages') | |
args = parser.parse_args() | |
# match filename:line[:col]:CONTENT | |
location_pattern = re.compile(r'(\S+):(\d+)(?:(:\d+))?:(.*)') | |
cdb = CoverageCoverage() | |
cwd = Path.cwd() | |
if args.invert: | |
def report(line, covered): | |
if covered is False: | |
print(line, end='') | |
else: | |
def report(line, covered): | |
if covered is True: | |
print(line, end='') | |
# Lines that don't match location_pattern get reported like the previous | |
# line that did match. | |
last_covered = None | |
for line in sys.stdin: | |
m = location_pattern.match(line) | |
if m is None: | |
report(line, last_covered) | |
continue | |
fn, ln, col, content = m.groups() | |
fn = fspath(cwd/fn) | |
ln = int(ln) | |
try: | |
covered = cdb.lookup(fn, ln) | |
except NotPython as e: | |
if not args.silent: | |
print(e, file=sys.stderr) | |
else: | |
report(line, covered) | |
last_covered = covered | |
class CoverageCoverage: | |
def __init__(self): | |
self.cov = Coverage() | |
self.cov.load() | |
self.fn_lines = {} | |
def lookup(self, fn, ln): | |
if fn not in self.fn_lines: | |
_, executable, not_executed, _ = self.cov.analysis(fn) | |
not_executed = {*not_executed} | |
executed = {*executable} - not_executed | |
self.fn_lines[fn] = executed, not_executed | |
else: | |
executed, not_executed = self.fn_lines[fn] | |
if ln in executed: | |
return True | |
if ln in not_executed: | |
return False | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment