manzt / juv

Reproducible Jupyter notebooks, powered by uv.
MIT License
49 stars 2 forks source link

Add `lock` command and support `juv run Untitled.ipynb --locked` #7

Open manzt opened 1 week ago

manzt commented 1 week ago

Ref: https://x.com/rahuldave/status/1848072186340196391

The idea would be to put a lockfile in the notebook metadata (either cell-level or top-level) and we could update the lock file on run/add/lock.

Then we could add a flag to --locked to skip dependency resolution and just create the enviroment from the lockfile.

flying-sheep commented 5 days ago

I saw this project and had the exact same thought!

In fact I don‘t think we’d need dependency specification in a code cell at all: jupyter has a perfect place for notebook-wide structured metadata already.

manzt commented 20 hours ago

Should be able to benefit from:

When it lands to save the export to the notebook metadata.

manzt commented 20 hours ago

In fact I don‘t think we’d need dependency specification in a code cell at all: jupyter has a perfect place for notebook-wide structured metadata already.

Yeah, I'm a bit torn on this. Keeping in a notebook cell as a comment aligns closer with scripts, but hiding means we could do more to control the behavior of adding/removing dependencies. We'd probably need better ways to show this metadata to users though in the notebook, if we choose to hide it. When/if we introduce locking, we could always write a new lock on any command (add, run, ...) and also offer something like juv sync to sync the lock.

manzt commented 20 hours ago

uv scripts now also support uv.tool.exclude-newer metadata. Even without a lock file, this could go a long way for making one-off notebooks more reproducible to add a timestamp to the notebook meta that we could have a flag to run.

e.g.,

juv init Untitled.ipynb # writes a timestamp to the notebook metadata
juv add Untitled.ipynb notebook
# juv timestamp Untitled.ipynb # explicitly update
juv run Untitled.ipynb
juv run --exclude-newer=last-timestamp Untitled.ipyng
flying-sheep commented 4 hours ago

The purpose of putting it into the metadata isn’t supposed to hide it, but to allow us to

  1. create a jupyterlab plugin to display and modify dependencies. since we start the jupyterlab instance with juv run, we’ll be able to inject the plugin into that environment, making that not a problem
  2. move the feature from the plugin into jupyterlab upstream (possibly with some changes after feedback)
  3. this makes it likely that alternative frontends like VS Code will also be able to support it