| import argparse |
| import json |
| import logging |
| import sys |
| from typing import Any, Optional |
|
|
| logger = logging.getLogger(__name__) |
|
|
|
|
| def _json(data: Any) -> None: |
| print(json.dumps(data, indent=2, default=str)) |
|
|
|
|
| def _table(rows: list[dict], cols: Optional[list[str]] = None) -> None: |
| if not rows: |
| print("(empty)") |
| return |
| cols = cols or list(rows[0].keys()) |
| widths = {c: max(len(c), max(len(str(r.get(c, ""))) for r in rows)) |
| for c in cols} |
| sep = " " |
| print(sep.join(c.ljust(widths[c]) for c in cols)) |
| print("-" * (sum(widths.values()) + len(sep) * (len(cols) - 1))) |
| for row in rows: |
| print(sep.join(str(row.get(c, "")).ljust(widths[c]) for c in cols)) |
|
|
|
|
| def cmd_list(args: argparse.Namespace) -> int: |
| logger.debug("list: %s", vars(args)) |
| print(f"Listing (page={args.page} size={args.size})") |
| return 0 |
|
|
|
|
| def cmd_add(args: argparse.Namespace) -> int: |
| logger.debug("add: name=%s", args.name) |
| print(f"Added: {args.name!r}") |
| return 0 |
|
|
|
|
| def cmd_delete(args: argparse.Namespace) -> int: |
| logger.debug("delete: id=%s", args.id) |
| print(f"Deleted: {args.id}") |
| return 0 |
|
|
|
|
| def cmd_show(args: argparse.Namespace) -> int: |
| logger.debug("show: id=%s", args.id) |
| print(f"Record: {args.id}") |
| return 0 |
|
|
|
|
| def cmd_export(args: argparse.Namespace) -> int: |
| logger.debug("export: fmt=%s", args.format) |
| print(f"Exported as {args.format}") |
| return 0 |
|
|
|
|
| def build_parser() -> argparse.ArgumentParser: |
| p = argparse.ArgumentParser(prog="app", |
| formatter_class=argparse.ArgumentDefaultsHelpFormatter) |
| p.add_argument("--json", dest="as_json", action="store_true") |
| sub = p.add_subparsers(dest="cmd", required=True) |
|
|
| ls = sub.add_parser("list") |
| ls.add_argument("--page", type=int, default=1) |
| ls.add_argument("--size", type=int, default=20) |
| ls.set_defaults(func=cmd_list) |
|
|
| add = sub.add_parser("add") |
| add.add_argument("name") |
| add.add_argument("--tag", action="append", dest="tags", default=[]) |
| add.set_defaults(func=cmd_add) |
|
|
| rm = sub.add_parser("delete") |
| rm.add_argument("id") |
| rm.add_argument("-y", "--yes", action="store_true") |
| rm.set_defaults(func=cmd_delete) |
|
|
| show = sub.add_parser("show") |
| show.add_argument("id") |
| show.set_defaults(func=cmd_show) |
|
|
| exp = sub.add_parser("export") |
| exp.add_argument("--format", choices=["csv", "json", "text"], default="text") |
| exp.add_argument("--output", "-o", default="-") |
| exp.set_defaults(func=cmd_export) |
|
|
| return p |
|
|
|
|
| def run_cli() -> int: |
| args = build_parser().parse_args() |
| try: |
| return args.func(args) |
| except Exception as exc: |
| logger.error("%s", exc) |
| return 1 |
|
|
|
|
| if __name__ == "__main__": |
| sys.exit(run_cli()) |
|
|