Metadata-Version: 2.4
Name: mooncat-checkpoint
Version: 0.1.0
Summary: 轻量级 step 幂等/断点续跑 checkpoint。默认文件存储，SQLite 标准库开箱即用，全 API 对齐 TS mooncat-checkpoint。
Project-URL: Homepage, https://github.com/earendil-works/mooncat-checkpoint
License: MIT
Keywords: cache,checkpoint,idempotency,mooncat,resumable,step,workflow
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# mooncat-checkpoint (Python)

> `mooncat-checkpoint` 的 Python SDK。
> 与 TypeScript 版**协议、JSON 格式、file/sqlite 数据完全互通**。
> **零运行时依赖**（sqlite3/json/secrets/hashlib 全是标准库），SQLite 开箱即用（无需 better-sqlite3 编译）。

## 安装

```bash
# uv（推荐）
uv pip install mooncat-checkpoint

# 或 pip（从本地）
pip install -e .
```

要求 Python ≥ 3.10。

## 快速开始

```python
from mooncat_checkpoint import CheckpointClient, LeaseLostError

cp = CheckpointClient("file://./.mooncat/checkpoints")

c = cp.claim("vision", image_hash, owner_run_id="run-1")
if c.kind == "done":
    print("已处理，复用:", c.checkpoint.result)
elif c.kind == "claimed":
    try:
        result = expensive_call()
        cp.done("vision", image_hash, lease_token=c.lease_token, result={"ok": True})
    except LeaseLostError:
        pass  # lease 被重抢，放弃
    except Exception as e:
        cp.fail("vision", image_hash, str(e), lease_token=c.lease_token)
        raise
```

## 与 TypeScript 互通

Python SDK 与 TS `mooncat-checkpoint` 共享：
- **协议**：状态机、fencing token、错误类型一一对应
- **file 后端**：JSON 格式完全一致（camelCase 键），TS 写的文件 Python 直接读，反之亦然
- **sqlite 后端**：表结构完全一致，TS 写的 db Python 直接读
- **key hash**：`safe_key_segment` 用相同 sha256 算法，同 key 在 TS/Python 产生相同 storage_key

```python
# Python 读 TS 写的文件
cp = CheckpointClient("file:///path/to/ts-checkpoints")
r = cp.claim("vision", "img-001")  # 读到 TS done 的记录
```

```typescript
// TS 读 Python 写的文件
const cp = new CheckpointClient({ url: "file:///path/to/py-checkpoints" });
const r = await cp.claim("vision", "img-001");
```

## API（与 TS 对齐）

```python
cp.claim(ns, key, owner_run_id=None, lease_ms=None)      → ClaimResult（claimed 含 lease_token）
cp.touch(ns, key, lease_token, extend_ms=None)            → Checkpoint | None
cp.done(ns, key, lease_token, result=None, result_ref=None) → Checkpoint
cp.fail(ns, key, error, lease_token)                       → Checkpoint
cp.get(ns, key)                                            → Checkpoint | None
cp.reset(ns, key)                                          → bool
cp.list(ns, status=None)                                   → list[Checkpoint]
cp.gc(older_than=0)                                        → int
```

## 后端

| 后端 | URL | 并发安全 | 说明 |
|------|-----|---------|------|
| **file**（默认） | `file://./.mooncat/checkpoints` | 单进程 | JSON 文件，透明可读 |
| **sqlite** | `sqlite://./checkpoints.db` | 跨进程 | **标准库，开箱即用**（Python 相对 TS 的优势） |
| **memory** | `memory://` | 单进程 | 测试用 |

## 测试

```bash
uv run --with pytest pytest
```

含跨语言互通测试（需 TS `npm run build` 后运行 `tests/test_cross_language.py`）。

## License

MIT
