feat(consume): a CLI with three exit codes and an asserted ref
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
42ab9c1d1a
commit
5d066f1799
2 changed files with 215 additions and 0 deletions
|
|
@ -31,6 +31,7 @@ wheel-installed command is a move rather than a rewrite.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
|
|
@ -957,3 +958,81 @@ def serialise(payload: Mapping[str, object]) -> str:
|
|||
the headroom. LF only, one trailing newline.
|
||||
"""
|
||||
return json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=False) + "\n"
|
||||
|
||||
|
||||
# --- The CLI ------------------------------------------------------------------
|
||||
|
||||
|
||||
def parse_args(argv: list[str] | None) -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument("bundle", type=Path, help="the OKF bundle directory to read")
|
||||
parser.add_argument("--question", required=True, help="the question to cut the bundle for")
|
||||
parser.add_argument(
|
||||
"--k", type=int, default=DEFAULT_K, help=f"cap on delivered excerpts (default {DEFAULT_K})"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--limit",
|
||||
type=int,
|
||||
default=DEFAULT_LIMIT,
|
||||
help=f"budget in {BUDGET_UNIT} (default {DEFAULT_LIMIT})",
|
||||
)
|
||||
parser.add_argument("--out", type=Path, default=None, help="write here instead of stdout")
|
||||
parser.add_argument(
|
||||
"--ref",
|
||||
default=None,
|
||||
help=(
|
||||
"assert the bundle's content identity. NOT an override: the identity "
|
||||
"is computed regardless and a mismatch refuses, because labelling a "
|
||||
"payload with an identity its bytes do not have is what SS 3.3 exists "
|
||||
"to prevent"
|
||||
),
|
||||
)
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
"""Three exit codes, not two.
|
||||
|
||||
**0** a payload was written, **1** the run happened and refused, **2** the
|
||||
run did not happen. Collapsing 2 into 1 would report an unread bundle as a
|
||||
failed cut -- two findings with different owners under one number.
|
||||
"""
|
||||
args = parse_args(argv)
|
||||
if not args.bundle.is_dir():
|
||||
print(f"okf_consume: FAILED - {args.bundle} is not a directory", file=sys.stderr)
|
||||
return 2
|
||||
try:
|
||||
payload = build_payload(args.bundle, question=args.question, k=args.k, limit=args.limit)
|
||||
except ConsumeError as error:
|
||||
print(f"okf_consume: FAILED - {error}", file=sys.stderr)
|
||||
return 1
|
||||
except OSError as error:
|
||||
print(f"okf_consume: FAILED - the bundle could not be read: {error}", file=sys.stderr)
|
||||
return 2
|
||||
except UnicodeDecodeError as error:
|
||||
print(f"okf_consume: FAILED - the bundle is not utf-8: {error}", file=sys.stderr)
|
||||
return 2
|
||||
computed = payload["bundle"]
|
||||
assert isinstance(computed, dict)
|
||||
if args.ref is not None and args.ref != computed["ref"]:
|
||||
# Refuses BEFORE writing: a payload on disk under an asserted ref that
|
||||
# the bytes contradict is worse than no payload.
|
||||
print(
|
||||
f"okf_consume: FAILED - the bundle's identity is {computed['ref']}, "
|
||||
f"not the asserted {args.ref}; refusing to write a payload the "
|
||||
"caller would label with an identity its bytes do not have",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
text = serialise(payload)
|
||||
if args.out is None:
|
||||
sys.stdout.write(text)
|
||||
else:
|
||||
args.out.write_text(text, encoding="utf-8", newline="\n")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue