import argparse import subprocess import sys import time from voussoirkit import betterhelp class NoMoreRetries(Exception): pass def normalize_limit(limit): if limit is not None: limit = int(limit) if limit < 1: raise ValueError('Limit must be >= 1, or None.') return limit def normalize_sleepy(sleepy): if sleepy is not None: sleepy = float(sleepy) if sleepy <= 0: raise ValueError('Sleep must be > 0, or None.') return sleepy def retry(command, limit, sleepy): limit = normalize_limit(limit) sleepy = normalize_sleepy(sleepy) status = 1 while limit is None or limit > 0: status = subprocess.run(command, shell=True).returncode if status == 0: return print(f'{command} failed with status {status}.') if limit is not None: limit -= 1 if sleepy is not None: time.sleep(sleepy) raise NoMoreRetries() def retry_argparse(args): return retry( command=args.command, limit=args.limit, sleepy=args.sleep, ) def main(argv): parser = argparse.ArgumentParser( description=''' Run a command line command multiple times until it returns 0. ''', ) parser.add_argument( 'command', nargs='+', help=''' A command line command. You may need to put this after -- to avoid confusion with arguments to this program. ''', ) parser.add_argument( '--limit', type=int, default=None, help=''' Maximum number of retries before giving up. ''', ) parser.add_argument( '--sleep', type=float, default=None, help=''' Number of seconds of sleep between each retry. ''', ) parser.set_defaults(func=retry_argparse) return betterhelp.go(parser, argv) if __name__ == '__main__': raise SystemExit(main(sys.argv[1:]))