#!/usr/bin/env python3 import sys, re import os import glob import hashlib # len(txt.split("\n"))) is off by 1 def wc(fn): i = 0 with open(fn) as f: for i, _l in enumerate(f, 1): pass return i def bytehex(x): return ''.join('{:02x}'.format(x) for x in x) def calc_stable_iters(todo_dir, max_iter): m5s = [] wcs = [] m5_last = None stablen = 0 for fni in range(1, max_iter + 1, 1): fn = "%s/%u_all.txt" % (todo_dir, fni) txt = open(fn, "r").read() m5 = hashlib.md5(txt.encode("ascii")).hexdigest() m5s.append(m5) wc_this = wc(fn) wcs.append(wc_this) if m5_last == m5: stablen += 1 else: stablen = 1 print( "% 4u %s % 6u lines % 6u stable" % (fni, m5[0:8], wc_this, stablen)) m5_last = m5 return stablen def run( todo_dir, min_iters=None, stable_iters=None, timeout_iters=None, max_iters=None, zero_entries=None, verbose=False): timeout_fn = "%s/timeout" % todo_dir # make clean removes todo dir, but helps debugging if os.path.exists(timeout_fn): print("WARNING: removing %s" % timeout_fn) os.remove(timeout_fn) alls = glob.glob("%s/*_all.txt" % todo_dir) max_iter = 0 for fn in alls: n = int(re.match(r".*/([0-9]*)_all.txt", fn).group(1)) max_iter = max(max_iter, n) if max_iter == 0: print("Incomplete: no iters") sys.exit(1) verbose and print("Max iter: %u, need: %s" % (max_iter, min_iters)) fn = "%s/%u_all.txt" % (todo_dir, max_iter) txt = open(fn, "r").read() nbytes = len(txt) stablen = calc_stable_iters(todo_dir, max_iter) if min_iters is not None and max_iter < min_iters: print("Incomplete: not enough iters") sys.exit(1) if max_iters is not None and max_iter >= max_iters: print( "Complete: reached max iters (want %u, got %u)" % (max_iters, max_iter)) sys.exit(0) if timeout_iters is not None and max_iter > timeout_iters: print("ERROR: timeout (max %u, got %u)" % (timeout_iters, max_iter)) with open(timeout_fn, "w") as _f: pass sys.exit(1) if zero_entries and nbytes: print("%s: %u bytes, %s lines" % (fn, nbytes, wc(fn))) print("Incomplete: need zero entries") sys.exit(1) if stable_iters: if stablen < stable_iters: print( "Incomplete: insufficient stable iters (got %s, need %s)" % (stablen, stable_iters)) sys.exit(1) print("Complete!") sys.exit(0) def main(): import argparse parser = argparse.ArgumentParser( description= "Check int_loop completion. Exits 0 on done, 1 if more loops are needed" ) parser.add_argument('--verbose', action='store_true', help='') parser.add_argument('--todo-dir', default="build/todo", help='') parser.add_argument( '--min-iters', default=None, help='Minimum total number of iterations') parser.add_argument( '--stable-iters', default=None, help='Number of iterations without any change') parser.add_argument( '--timeout-iters', default=None, help='Max number of entries before creating todo/timeout') parser.add_argument( '--max-iters', default=None, help='Max number of entries before declaring success') parser.add_argument( '--zero-entries', action="store_true", help='Must be no unsolved entries in latest') args = parser.parse_args() def zint(x): return None if x is None else int(x) run( args.todo_dir, zint(args.min_iters), zint(args.stable_iters), zint(args.timeout_iters), zint(args.max_iters), args.zero_entries, verbose=args.verbose) if __name__ == '__main__': main()