oc_chat
Loading...
Searching...
No Matches
checkpoint.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# oc_chat/registry/cli/checkpoint.py
4
5# OCT-LINT: disable=tests_exist reason="Covered by oc_chat/tests/registry/test_checkpoint_*.py"
6"""
7Operator CLI for registry JSON checkpoints.
8
9Purpose
10-------
11Expose `python -m oc_chat.registry checkpoint export|import` for portable
12registry state transfer.
13
14Responsibilities
15----------------
16- Resolve registry paths through standard discovery.
17- Wire export/import arguments to the checkpoint library.
18- Format checkpoint results as human text or JSON.
19
20Diagnostics
21-----------
22Domain: OC_CHAT.MAIN
23Levels:
24 L2 - checkpoint command lifecycle events
25 L3 - checkpoint result summaries
26 L4 - argparse/dispatch tracing
27
28Contracts
29---------
30- Import delegates signature verification and restore to `checkpoint.py`.
31- Export does not mutate registry state.
32
33Dependencies
34------------
35- oc_diagnostics (structured debug logging via _dbg)
36- oc_chat.registry.checkpoint (checkpoint implementation)
37- oc_chat.registry.discovery (path resolution)
38- oc_chat.registry (Registry facade passed to the checkpoint export)
39- oc_chat.registry.backends.sqlite (SQLiteBackend opened for export and restored on import)
40"""
41from __future__ import annotations
42
43import argparse
44import json
45from pathlib import Path
46
47from oc_diagnostics import _dbg
48
49from oc_chat.registry import Registry
50from oc_chat.registry.backends.sqlite import SQLiteBackend
52 import_checkpoint,
53 write_checkpoint,
54)
55from oc_chat.registry.discovery import discover_registry_location
56
57
58_dbg("OC_CHAT.MAIN", "module", "loaded", 4)
59
60
61def add_checkpoint_subcommands(parser: argparse.ArgumentParser) -> None:
62 """Attach ``checkpoint export|import`` subcommands."""
63
64 parser.set_defaults(handler=_cmd_checkpoint_group, checkpoint_parser=parser)
65 subcommands = parser.add_subparsers(dest="checkpoint_command")
66
67 export = subcommands.add_parser("export", help="Export a JSON checkpoint.")
68 export.add_argument(
69 "registry",
70 nargs="?",
71 help="Registry SQLite path. Defaults to the discovery algorithm.",
72 )
73 export.add_argument("--out", required=True, help="Output checkpoint JSON path.")
74 export.add_argument("--sign", action="store_true", help="Sign with HMAC-SHA256.")
75 export.add_argument("--json", action="store_true")
76 export.set_defaults(handler=_cmd_export)
77
78 import_parser = subcommands.add_parser("import", help="Import a JSON checkpoint.")
79 import_parser.add_argument(
80 "registry",
81 nargs="?",
82 help="Registry SQLite path. Defaults to the discovery algorithm.",
83 )
84 import_parser.add_argument(
85 "--from",
86 dest="from_file",
87 required=True,
88 help="Checkpoint JSON file to import.",
89 )
90 import_parser.add_argument(
91 "--skip-signature-check",
92 action="store_true",
93 help="Allow importing an unsigned checkpoint.",
94 )
95 import_parser.add_argument("--json", action="store_true")
96 import_parser.set_defaults(handler=_cmd_import)
97
98
99def _cmd_checkpoint_group(args: argparse.Namespace) -> int:
100 parser = args.checkpoint_parser
101 parser.print_help()
102 return 1
103
104
105def _cmd_export(args: argparse.Namespace) -> int:
106 location = discover_registry_location(registry_path=args.registry)
107 backend = SQLiteBackend(location.registry_path)
108 result = write_checkpoint(
109 Registry(backend),
110 out=Path(args.out),
111 sign=args.sign,
112 )
113 payload = result.to_dict()
114 if args.json:
115 print(json.dumps(payload, indent=2, sort_keys=True))
116 else:
117 print(f"checkpoint exported: {result.path}")
118 print(f"sha256: {result.sha256}")
119 return 0
120
121
122def _cmd_import(args: argparse.Namespace) -> int:
123 location = discover_registry_location(registry_path=args.registry)
124 backend = SQLiteBackend(location.registry_path)
125 result = import_checkpoint(
126 backend,
127 checkpoint_path=Path(args.from_file),
128 skip_signature_check=args.skip_signature_check,
129 )
130 payload = result.to_dict()
131 if args.json:
132 print(json.dumps(payload, indent=2, sort_keys=True))
133 else:
134 print(f"checkpoint imported: {result.path}")
135 print(f"tables: {len(result.tables)}")
136 return 0
int _cmd_checkpoint_group(argparse.Namespace args)
Definition checkpoint.py:99
int _cmd_export(argparse.Namespace args)
None add_checkpoint_subcommands(argparse.ArgumentParser parser)
Definition checkpoint.py:61
int _cmd_import(argparse.Namespace args)