1#!/usr/bin/env python3
2"""Cold-validate exported offline page batches in disposable OneNote clones."""
3import argparse
4from concurrent.futures import ThreadPoolExecutor
5import json
6from pathlib import Path
7import subprocess
8import sys
9from tempfile import TemporaryDirectory
10
11ROOT = Path(__file__).resolve().parent.parent
12
13
14def capture(case, output):
15 destination = output / case.name
16 with TemporaryDirectory() as temporary:
17 source = Path(temporary)
18 (source / 'Lifecycle.one').symlink_to((case / 'Lifecycle.one').resolve(strict=True))
19 with (output / (case.name + '.log')).open('w') as log:
20 subprocess.run([sys.executable, ROOT / 'tools/native_runner.py', source,
21 destination, '--expected-pages', '9', '--collect-notebook'],
22 stdout=log, stderr=subprocess.STDOUT, check=True)
23 subprocess.run([sys.executable, ROOT / 'tools/verify_page_creation.py', case,
24 destination], stdout=log, stderr=subprocess.STDOUT, check=True)
25 assert json.loads((destination / 'teardown.json').read_text())['absent']
26 assert (case / 'Lifecycle.one').read_bytes()[1024:] == (
27 destination / 'notebook/Lifecycle.one').read_bytes()[1024:]
28 print(f'Verified and removed: {case.name}', flush=True)
29 return case.name
30
31
32if __name__ == '__main__':
33 parser = argparse.ArgumentParser(description=__doc__)
34 parser.add_argument('candidates', type=Path)
35 parser.add_argument('output', type=Path)
36 parser.add_argument('--workers', type=int, default=4, choices=range(1, 9))
37 args = parser.parse_args()
38 cases = sorted(p for p in args.candidates.iterdir() if (p / 'Lifecycle.one').is_file())
39 if len(cases) != 18:
40 parser.error('Export all 18 native/offline page cases before starting the captures.')
41 args.output.mkdir(parents=True, exist_ok=False)
42 with ThreadPoolExecutor(max_workers=args.workers) as pool:
43 completed = list(pool.map(lambda case: capture(case, args.output), cases))
44 (args.output / 'verified.json').write_text(json.dumps(completed, indent=2) + '\n')