nt/scripts/ferror

98 lines
2.8 KiB
Text
Raw Permalink Normal View History

#!/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)