Update littlecheck

Now featuring Context display on error, which should make it a bit
easier to make out any problems.
This commit is contained in:
Fabian Homborg 2020-03-29 10:47:27 +02:00
parent e49b4df562
commit edad6aa607

View File

@ -6,6 +6,7 @@ from __future__ import unicode_literals
from __future__ import print_function
import argparse
from collections import deque
import datetime
import io
import re
@ -33,6 +34,8 @@ class Config(object):
self.progress = False
# How many after lines to print
self.after = 5
# How many before lines to print
self.before = 5
def colors(self):
""" Return a dictionary mapping color names to ANSI escapes """
@ -118,13 +121,14 @@ class RunCmd(object):
class TestFailure(object):
def __init__(self, line, check, testrun, after=None):
def __init__(self, line, check, testrun, before=None, after=None):
self.line = line
self.check = check
self.testrun = testrun
self.error_annotation_line = None
# The output that comes *after* the failure.
self.after = after
self.before = before
def message(self):
afterlines = self.testrun.config.after
@ -181,7 +185,15 @@ class TestFailure(object):
" additional output on stderr:{error_annotation_lineno}:",
" {BOLD}{error_annotation}{RESET}",
]
if self.after:
if self.before:
fields["before_output"] = " ".join(self.before)
fields["additional_output"] = " ".join(self.after[:afterlines])
fmtstrs += [
" Context:",
" {BOLD}{before_output} {RED}{output_line}{RESET} <= does not match '{LIGHTBLUE}{input_line}{RESET}'",
" {BOLD}{additional_output}{RESET}",
]
elif self.after:
fields["additional_output"] = " ".join(self.after[:afterlines])
fmtstrs += [" additional output:", " {BOLD}{additional_output}{RESET}"]
fmtstrs += [" when running command:", " {subbed_command}"]
@ -227,6 +239,8 @@ class TestRun(object):
# Reverse our lines and checks so we can pop off the end.
lineq = lines[::-1]
checkq = checks[::-1]
# We keep the last couple of lines in a deque so we can show context.
before = deque(maxlen=self.config.before)
while lineq and checkq:
line = lineq[-1]
check = checkq[-1]
@ -234,6 +248,7 @@ class TestRun(object):
# This line matched this checker, continue on.
lineq.pop()
checkq.pop()
before.append(line.text)
elif line.is_empty_space():
# Skip all whitespace input lines.
lineq.pop()
@ -245,6 +260,7 @@ class TestRun(object):
line,
check,
self,
before=before,
after=[
line.text for line in lineq[::-1] if not line.is_empty_space()
],
@ -459,6 +475,14 @@ def get_argparse():
action="store",
default=5,
)
parser.add_argument(
"-B",
"--before",
type=int,
help="How many non-empty lines of output before a failure to print (default: 5)",
action="store",
default=5,
)
return parser
@ -474,6 +498,12 @@ def main():
config.progress = args.progress
fields = config.colors()
config.after = args.after
config.before = args.before
if config.before < 0:
raise ValueError("Before must be at least 0")
if config.after < 0:
raise ValueError("After must be at least 0")
for path in args.file:
fields["path"] = path
if config.progress: