#!/usr/bin/env python3 from __future__ import annotations import hashlib import json from pathlib import Path ROOT = Path(__file__).resolve().parents[1] NOTEBOOKS = ROOT / "notebooks" def cell_id(index: int, cell: dict) -> str: source = "".join(cell.get("source", [])) digest = hashlib.sha1(f"{cell.get('cell_type', 'cell')}:{index}:{source}".encode()).hexdigest() return digest[:8] def normalize_notebook(path: Path) -> bool: data = json.loads(path.read_text()) changed = False for index, cell in enumerate(data.get("cells", [])): if "id" not in cell: cell["id"] = cell_id(index, cell) changed = True if changed: path.write_text(json.dumps(data, indent=2) + "\n") return changed def main() -> None: changed_paths = [] for path in sorted(NOTEBOOKS.rglob("*.ipynb")): if ".ipynb_checkpoints" in path.parts: continue if normalize_notebook(path): changed_paths.append(path) print(f"normalized_notebooks={len(changed_paths)}") for path in changed_paths: print(path.relative_to(ROOT)) if __name__ == "__main__": main()