net-kingdom/tools/contract-tests/excerpt.py

63 lines
2.5 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Contract excerpt for a worker on a cross-repo change (NK-WP-0058-T08). Read-only.
python3 tools/contract-tests/excerpt.py E1 C5 O1 # rows of docs/bounded-execution-contract-table.md
Prints, for each row: its line in the table (owner and source of truth, consumer, mark), its detail sections (names,
paths, roles, payloads, exit codes, and the one owning script or file per step), and the contract tests that cover
it. A worker gets this excerpt before starting and checks its result with those tests and `make contract-test`.
An unknown row fails: a new interface gets its row in the table first.
"""
import re
import sys
from pathlib import Path
TABLE = Path(__file__).resolve().parents[2] / 'docs/bounded-execution-contract-table.md'
ROW = re.compile(r'^[EROCF]\d+$')
def ids_in(text):
"""Row ids named in a cell or heading, with ranges like O2–O4 expanded."""
found = set()
for first, last in re.findall(r'\b([EROCF]\d+)\s*[–-]\s*([EROCF]\d+)\b', text):
if first[0] == last[0]:
found |= {f'{first[0]}{n}' for n in range(int(first[1:]), int(last[1:]) + 1)}
return found | set(re.findall(r'\b[EROCF]\d+\b', text))
def sections(text):
"""(heading, body) for each ### section."""
parts = re.split(r'^(### .+)$', text, flags=re.M)
return [(parts[i], parts[i + 1].split('\n## ')[0]) for i in range(1, len(parts) - 1, 2)]
def excerpt(row_ids, text=None):
text = text if text is not None else TABLE.read_text()
out = []
for row in row_ids:
if not ROW.match(row):
raise SystemExit(f'not a row id: {row}')
line = next((l for l in text.splitlines() if l.startswith(f'| {row} |')), None)
if line is None:
raise SystemExit(f'{row}: no such row; add the interface to the table first')
out += [f'## {row}', '', line, '']
for heading, body in sections(text):
if row in ids_in(heading.split(':')[0]):
out += [heading, body.strip(), '']
coverage = [l for l in text[text.index('### Coverage by row'):].splitlines()
if l.startswith('| ') and not l.startswith('| Row') and row in ids_in(l.split('|')[1])]
out += ['**Contract tests:**', *(coverage or ['none recorded: add one with the change']), '']
return '\n'.join(out)
def main(argv=None):
rows = argv if argv is not None else sys.argv[1:]
if not rows:
raise SystemExit(__doc__)
print(excerpt(rows))
return 0
if __name__ == '__main__':
sys.exit(main())