Manual-commit notebook snapshot extension (JupyterLab 4):
Backend
- Storage adapter layer (Local + S3 via boto3, pip extra)
- Dumb put/get/list/delete contract; key validation
- S3Storage: lazy boto3 import, S3ConnectionError with friendly
messages + connectivity check at startup
- SnapshotStore
- Strip code outputs/execution_count, MD5 on cleaned JSON
- Gzipped envelope (id/timestamp/name/description/hash/size/notebook)
- Append-only manifest.json (rebuildable from version files)
- SnapshotUnchangedError when new hash matches most recent version
- REST API (commit / list / content) under /snapshot/ namespace
- traitlets config (storage_type, local_root, s3_* + S3_* env fallback)
Frontend
- snapshot:commit command (toolbar button + command palette)
- Dialog for name + description
- SnapshotPanel (left sidebar timeline) + DiffWidget (main area)
- Cell diff: id-match first, LCS fallback; jsdiff for line diff
- Restore via model.fromJSON() + context.save() (no refresh)
- All AGENTS.md hard conventions enforced
Tests: 33 backend pytest passing (storage + store + routes)
Docs: AGENTS.md, design.md, README.md synced with implementation.
Co-Authored-By: Claude <noreply@anthropic.com>
4.9 KiB
4.9 KiB
notebook-snapshot
JupyterLab 扩展:手动保存 .ipynb 快照,无 Git 依赖。
左侧栏查看版本时间轴、Cell 级 diff、一键无刷新恢复。
功能
- 工具栏「保存快照」按钮 / 命令面板
snapshot:commit触发 - 对话框填写
name(必填)+description(可选)后保存 - 内容与最近版本相同时自动跳过(弹 warning),避免重复快照
- 左侧栏时间轴,支持对比(Cell 级 diff,行级红绿高亮)和恢复
- 恢复走
model.fromJSON()+context.save(),无页面刷新 - 历史 append-only,永不删除 / 改写
存储后端
- Local(默认):
<root_dir>/.notebook_versions或自定义路径 - S3(pip extra):通过 boto3 对接 AWS S3 / MinIO / 任何 S3-API 兼容服务
环境要求
- JupyterLab >= 4.0.0
- Python >= 3.10
- Node.js(构建前端用)
安装
# 1. 后端(基础包零依赖)
pip install snapshot
# 2. 前端构建
jlpm install
jlpm build
# 3. 启用 server extension
jupyter server extension enable snapshot
jupyter labextension develop . --overwrite # dev 安装;正式版 wheel 跳过此步
可选 S3 后端:
pip install "snapshot[s3]" # 装 boto3
配置
写在 ~/.jupyter/jupyter_server_config.py(用户级)或 <项目>/jupyter_server_config.py(项目级):
| 字段 | 默认 | 说明 |
|---|---|---|
storage_type |
"local" |
"local" 或 "s3" |
local_root |
"" → <root_dir>/.notebook_versions |
Local 存储根目录;建议显式设置避免污染 notebook 目录 |
s3_endpoint |
""(env: S3_ENDPOINT) |
localhost:9000(MinIO)/ s3.us-east-1.amazonaws.com(AWS) |
s3_access_key |
""(env: S3_ACCESS_KEY) |
|
s3_secret_key |
""(env: S3_SECRET_KEY) |
|
s3_bucket |
"notebook-snapshot" |
不存在自动建 |
s3_secure |
False |
HTTPS |
s3_prefix |
"" |
桶内 key 前缀 |
示例
# 切到自定义 local 目录
c.SnapshotConfig.local_root = "/var/lib/jupyter/snapshots"
# 切到 MinIO
c.SnapshotConfig.storage_type = "s3"
c.SnapshotConfig.s3_endpoint = "minio.example.com:9000"
c.SnapshotConfig.s3_bucket = "team-snapshots"
# 凭证走 env:export S3_ACCESS_KEY=... ; export S3_SECRET_KEY=...
# 切到 AWS S3
c.SnapshotConfig.storage_type = "s3"
c.SnapshotConfig.s3_endpoint = "s3.us-east-1.amazonaws.com"
c.SnapshotConfig.s3_secure = True
# 用 AWS 标准凭证:export AWS_ACCESS_KEY_ID=... ; export AWS_SECRET_ACCESS_KEY=...
# (注:当前版本仅读取 S3_* 环境变量;如需 AWS_* 自动识别,参考 boto3 文档配置)
环境变量 / 命令行 / 配置文件三种方式优先级遵循 traitlets 规则;改完配置必须重启 jupyter lab。
开发
source .venv/bin/activate # 本仓库用 uv/venv
pip install -e ".[dev,test,s3]" # 后端装 dev/test/s3 依赖
.venv/bin/jlpm install # 前端依赖
.venv/bin/jlpm build # 一次性构建(tsc + rspack + labextension)
.venv/bin/jlpm watch # 终端 1:监听 src/ 自动重编
jupyter lab # 终端 2:启动 JupyterLab
改了 Python 后端:重启 jupyter lab(不需要 rebuild 前端)。
改了前端 TypeScript:jlpm watch 自动重编,浏览器刷新即可。
验证
# 后端
.venv/bin/pytest snapshot/tests/ -vv
# 前端类型检查 + 打包
.venv/bin/jlpm build
# Lint
.venv/bin/jlpm lint:check
架构
参见 design.md。
简要:
- 后端:
/snapshot/命名空间下三个端点(commit / list / content);SnapshotStore包装StorageAdapter(Local + S3),gzip + envelope 存盘,manifest 是可重建的索引 - 前端:
SnapshotModel+SnapshotPanel(左侧栏) +DiffWidget(主区) +snapshot:commit命令(工具栏 + 命令面板)
硬约定(实现时不得违背)见 AGENTS.md。
排错
jupyter server extension list # 后端 extension 状态
jupyter labextension list # 前端 extension 状态
- 工具栏没有「保存快照」按钮:刷新浏览器;确认
jupyter labextension list显示 enabled + OK - 保存时 400:检查
path/content/name是否齐全 - 保存后弹"内容未变更":正常行为——内容与最近版本 hash 相同会自动跳过,改动 cell 后再保存即可
- S3 连不上:确认
endpoint(不带 scheme)、secure(http/https)、bucket 存在性;凭证走 env 别写进配置
卸载
jupyter server extension disable snapshot
pip uninstall snapshot
AI 工具支持
本项目遵循 AGENTS.md 标准,配套符号链接:
CLAUDE.md→AGENTS.md(Claude Code)- 其他工具:Cursor / Copilot / Windsurf / Aider 等直接读取
AGENTS.md