diff --git a/docs/api/examples/simple2.py b/docs/api/examples/simple2.py index 2b1f7ad..8c56b00 100644 --- a/docs/api/examples/simple2.py +++ b/docs/api/examples/simple2.py @@ -27,6 +27,12 @@ def add_arguments(parser: argparse.ArgumentParser) -> None: "--range", action="append", type=cli.flags.type_range, help="add ranged hosts" ) + # adds rexec flags + cli.flags.add_arguments_rexec(parser) + + # add a new time flag + parser.add_argument("--time", type=cli.flags.type_hhmm) + def process_args(args: argparse.Namespace) -> argparse.Namespace | None: args.x = 2 * args.x @@ -38,9 +44,14 @@ def process_args(args: argparse.Namespace) -> argparse.Namespace | None: @cli.cli(add_arguments, process_args) async def main(args: argparse.Namespace): """a simple test script with a simple description""" - print(f"Got for x='{args.x}'") - for host, port in args.range or []: - print(f" {host}:{port}") + + if args.range: + print("args.range") + for host, port in args.range or []: + print(f" {host}:{port}") + for key in ["x", "time", "timeout", "max_retries", "delay_retry"]: + if getattr(args, key, None) is not None: + print(f"args.{key}: {getattr(args, key)} ({type(getattr(args, key))})") if __name__ == "__main__": diff --git a/src/luxos/cli/flags.py b/src/luxos/cli/flags.py index bf3fba2..91cbed6 100644 --- a/src/luxos/cli/flags.py +++ b/src/luxos/cli/flags.py @@ -3,9 +3,23 @@ from __future__ import annotations import argparse +import contextlib +import datetime def type_range(txt: str) -> list[tuple[str, int | None]]: + """type conversion for ranges + + This will enforce conversion between a string and a ranged object. + + Eg. + parser.add_argument("--range", type=type_range) + + The --range argument will be: + 127.0.0.1 # single ip address + 127.0.0.1:1234 # single ip address with port + 127.0.0.1-127.0.0.3 # a list of (ip, port) tuple between *.1 and.3 + """ from luxos.ips import iter_ip_ranges try: @@ -14,3 +28,41 @@ def type_range(txt: str) -> list[tuple[str, int | None]]: raise argparse.ArgumentTypeError(f"conversion failed '{txt}': {exc.args[0]}") except Exception as exc: raise argparse.ArgumentTypeError(f"conversion failed for {txt}") from exc + + +def type_hhmm(txt: str): + """type conversion for ranges + + This will enforce conversion between a string and datetime.time object. + + Eg. + parser.add_argument("--time", type=type_hhmm) + + The --time format is HH:MM + """ + if not txt: + return + with contextlib.suppress(ValueError, TypeError): + hh, _, mm = txt.partition(":") + hh1 = int(hh) + mm1 = int(mm) + return datetime.time(hh1, mm1) + raise argparse.ArgumentTypeError(f"failed conversion into HH:MM for '{txt}'") + + +def add_arguments_rexec(parser: argparse.ArgumentParser) -> None: + group = parser.add_argument_group( + "Remote execution", "rexec remote execution limits/timeouts" + ) + group.add_argument( + "--timeout", type=float, default=3.0, help="Timeout for each command" + ) + group.add_argument( + "--max-retries", + type=int, + default=3, + help="Maximum number of retries for each command", + ) + group.add_argument( + "--delay-retry", type=float, default=3.0, help="Delay in s between retries" + )