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 或自定义路径
  • S3pip 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:9000MinIO/ s3.us-east-1.amazonaws.comAWS
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"
# 凭证走 envexport 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 前端)。 改了前端 TypeScriptjlpm watch 自动重编,浏览器刷新即可。

验证

# 后端
.venv/bin/pytest snapshot/tests/ -vv

# 前端类型检查 + 打包
.venv/bin/jlpm build

# Lint
.venv/bin/jlpm lint:check

架构

参见 design.md

简要:

  • 后端/snapshot/ 命名空间下三个端点(commit / list / content);SnapshotStore 包装 StorageAdapterLocal + 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)、securehttp/https)、bucket 存在性;凭证走 env 别写进配置

卸载

jupyter server extension disable snapshot
pip uninstall snapshot

AI 工具支持

本项目遵循 AGENTS.md 标准,配套符号链接:

  • CLAUDE.mdAGENTS.mdClaude Code
  • 其他工具:Cursor / Copilot / Windsurf / Aider 等直接读取 AGENTS.md

详细开发规范见 AGENTS.md,设计文档见 design.md

S
Description
No description provided
Readme BSD-3-Clause
358 KiB
2026-07-22 11:24:22 +08:00
Languages
Python 57.9%
TypeScript 31.8%
CSS 5.1%
JavaScript 2.8%
Shell 2.4%