mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-07-15 21:28:33 -05:00
[PR #1950] [MERGED] fix(tinytorch): nbgrader generate can silently overwrite a student's notebook #34674
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/harvard-edge/cs249r_book/pull/1950
Author: @Shashank-Tripathi-07
Created: 7/7/2026
Status: ✅ Merged
Merged: 7/10/2026
Merged by: @profvjreddi
Base:
dev← Head:fix/nbgrader-notebook-overwrite📝 Commits (1)
2d0e5acfix(tinytorch): nbgrader generate can silently overwrite a student's notebook📊 Changes
2 files changed (+33 additions, -11 deletions)
View changed files
📝
tinytorch/.gitignore(+1 -0)📝
tinytorch/tito/commands/nbgrader.py(+32 -11)📄 Description
Summary
_ensure_module_notebook()regeneratesmodules/<name>/<name>.ipynbfromsrc/<name>.pywhenever the source file's mtime is newer than the notebook's -- but that exact path is the same notebooktito module start/resumeopen for students to edit (confirmed againstworkflow.pylines 518, 777, 1190, 1239, which all construct the identicalmodules/<module>/<short_name>.ipynbpath).git pullthat bumps a source file's mtime, followed by an instructor runningtito nbgrader generate --all(or per-module) on a shared checkout, silently overwrote any student notebook whose file mtime was older than the source -- no backup, no confirmation, just a benign "Source file is newer; converting..." message.Fix
Never write to the student-facing notebook path once it exists. If it needs regenerating from a newer source, stage the fresh conversion into a private
.nbgrader_staging/cache instead, and read from there for nbgrader's own assignment staging (_generate_single_modulealready just reads whatever path_ensure_module_notebookreturns, so no other caller needed to change). First-time creation (no notebook yet) and the already-up-to-date case are unaffected -- both still return the directmodules/path with no staging detour.Test plan
_ensure_module_notebook(jupytext subprocess call mocked, everything else real file I/O) across three scenarios:.nbgrader_staging/<module>/<name>.ipynbinstead..nbgrader_staging/to.gitignoresince it's a generated cache.pre-commit runpasses (only the known, unrelated, always-runbook-check-cli-contracthook fails locally due to a Windows interpreter mismatch in this dev environment).🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.