add ferror script to parse nix-unit stderr
This commit is contained in:
parent
370ae9c9c0
commit
e31dc6dea8
1 changed files with 97 additions and 0 deletions
97
scripts/ferror
Executable file
97
scripts/ferror
Executable file
|
|
@ -0,0 +1,97 @@
|
|||
#!/usr/bin/env python3
|
||||
import re
|
||||
import sys
|
||||
import subprocess
|
||||
from typing import Iterable
|
||||
from string import printable
|
||||
from subprocess import CompletedProcess
|
||||
|
||||
ENCODING = 'utf-8'
|
||||
ANSI_RE = re.compile(rb'\x1B\[[0-?]*[ -/]*[@-~]')
|
||||
|
||||
def zip_n(l: Iterable, n: int) -> zip:
|
||||
return zip(*[l[i:] for i in range(n)])
|
||||
|
||||
def run_tests() -> CompletedProcess:
|
||||
return subprocess.run(
|
||||
["nix-unit", "tests"],
|
||||
capture_output=True)
|
||||
|
||||
def sanitize_bytes(b: bytes, encoding='utf-8', errors='replace') -> str:
|
||||
# remove ANSI escapes first
|
||||
b = ANSI_RE.sub(b'', b)
|
||||
# decode (replace undecodable bytes)
|
||||
s = b.decode(encoding, errors=errors)
|
||||
# remove control chars except newline/tab
|
||||
s = ''.join(ch for ch in s if ch.isprintable() or ch in '\n\t')
|
||||
return s
|
||||
|
||||
def sanitize_nix(s: str) -> str:
|
||||
s = s.replace('«', '"«').replace('»', '»"')
|
||||
return s
|
||||
|
||||
def parse_result(stderr: bytes, index: int) -> None:
|
||||
line_start = index
|
||||
line_end = 0
|
||||
line = '' # exists solely for debugging
|
||||
lines_lhs = []
|
||||
lines_rhs = []
|
||||
|
||||
find_newline = lambda: stderr.index('\n', line_start)
|
||||
def progress() -> None:
|
||||
nonlocal line_start, line_end, line
|
||||
nonlocal lines_lhs, lines_rhs
|
||||
line_end = find_newline()
|
||||
line = stderr[line_start:line_end]
|
||||
line_start = line_end + 1
|
||||
# NOTE: exploit the fact that nix-unit always aligns
|
||||
# NOTE: itself to the $COLUMNS environment variable
|
||||
# NOTE: rounded down to the nearest odd number
|
||||
midpoint = len(line) // 2 + 1
|
||||
lhs = line[2 : midpoint - 1]
|
||||
rhs = line[midpoint + 2 : ]
|
||||
lines_lhs.append(lhs)
|
||||
lines_rhs.append(rhs)
|
||||
|
||||
# header is two lines
|
||||
for i in range(2):
|
||||
line_start = find_newline() + 1
|
||||
|
||||
progress()
|
||||
while True:
|
||||
progress()
|
||||
if not len(line) or line[0] != '.':
|
||||
break
|
||||
|
||||
lines_lhs = sanitize_nix(''.join(lines_lhs))
|
||||
lines_rhs = sanitize_nix(''.join(lines_rhs))
|
||||
return lines_lhs, lines_rhs
|
||||
|
||||
def main() -> None:
|
||||
result = run_tests()
|
||||
stderr = sanitize_bytes(result.stderr)
|
||||
|
||||
# delimiter = '❌'.encode(ENCODING)
|
||||
# error_indices = [i for i, b in enumerate(zip_n(stderr, len(delimiter))) if bytes(b) == delimiter]
|
||||
# for index in error_indices:
|
||||
# parse_result(stderr, index)
|
||||
|
||||
error_indices = [i for i, c in enumerate(stderr) if c == '❌']
|
||||
for index in error_indices:
|
||||
lhs, rhs = parse_result(stderr, index)
|
||||
print(lhs)
|
||||
print()
|
||||
print(rhs)
|
||||
print('\n\n\n')
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print('[!] Interrupt (SIGINT)', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except EOFError:
|
||||
print('[!] Interrupt (EOF)', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
Loading…
Add table
Add a link
Reference in a new issue