Skip to main content

jupytext-notebook-helper

Author your teaching notebooks once, in plain Python, and generate every version you hand out — while a build that actually runs the code keeps you honest.

Why

A single practical (TP) usually has to exist in several shapes at once:

  • a teacher notebook with the full solutions,
  • a student notebook where those solutions are blanked out,
  • a Colab variant that installs its own dependencies,
  • a local variant shipped with a pinned uv environment,
  • optionally a solution hand-out (solutions kept, instructor scaffolding gone).

Maintaining those by hand means copy-pasting between notebooks, re-blanking answers, chasing pip install lines, and discovering in front of the class that a cell no longer runs. Notebooks are also miserable to diff and review in git.

This project takes a different approach: you write one source file per TP in the jupytext percent format — an ordinary, diffable, lintable .py file — annotate it with a few lightweight markers, and a build step produces all the variants above. The same build can execute each notebook (at three levels of fidelity) so a broken example fails on your machine, not the student's.

The idea in one picture

                         ┌─ student/  local/tp1.ipynb   (solutions blanked)
                         │            colab/tp1.ipynb   (+ auto %pip install cell)
   tp1.py   ──filter──▶  ├─ teacher/  local/tp1.ipynb   (solutions kept)
 (py:percent)            │            colab/tp1.ipynb
                         └─ solution/ local/tp1.ipynb   (optional corrigé)
                                      colab/tp1.ipynb
        │
        └─ + uv bundle (pyproject + uv.lock + notebooks) for a reproducible
             local install

Every output directory has the same two sub-directories, local/ and colab/, with the same file names, so a link only changes by one path segment.

You author in tp1.py; students never see the machinery.

What you write

An ordinary percent notebook, with a small marker vocabulary interpreted by the filter (python -m jupytext_notebook_helper.filter):

# %% [markdown]
# ## Exercise 1 — cosine similarity

# %%
import numpy as np

def cosine(a, b):
    # [[student]] Return the cosine similarity of two vectors
    return a @ b / (np.linalg.norm(a) * np.linalg.norm(b))
    # [[/student]]

[[student]] … [[/student]] is blanked in the student version (the instruction becomes a comment followed by assert False), [[remove]] … [[/remove]] is stripped from everything handed out, and cell tags gate content per variant. The full vocabulary is in Writing a source.

Percent files open as notebooks in VS Code with the Text as Notebook extension (with the Jupyter extension for the kernel): cells run against a real kernel, and the file on disk stays the plain .py source.

What you get

Beyond the variant generation, the runtime helpers and build integrate a few things that otherwise bite you late:

  • Imports are gathered automatically from wherever you wrote them — put each import next to the code that needs it.
  • Internal library code is inlined so a self-contained student notebook carries exactly the helper functions it uses — nothing more.
  • Colab gets a pinned %pip install cell generated from uv.lock, so the first cell just works.
  • Everything is testable at three fidelity levels (make check = resolved inlined subset, make check-raw = plain script, and the real notebook build), catching missing dependencies and broken cells before students do.

Quick start

Include the shared make rules from the course's Makefile:

ROOT := ..
include $(shell uv run python -m jupytext_notebook_helper.tpmk)

Then, from that directory:

make help       # every target, by section
make student    # student notebooks (local + Colab) and the uv bundle
make teacher    # teacher notebooks, with the solutions
make check      # run every source, with the code students get

Documentation

Page Covers
The pipeline, end to end source → build → check → deploy → index page → manifest, with the target for each step
Writing a source markers, gathered imports, inlined library code, the Colab install cell
Runtime helpers hardware(), profiles, where output goes
Checking and running check, check-raw, lab, run-teacher, check-resources
Setting up a course the Makefile, [tool.jupytext-notebook-helper], bundles, solutions, rsync, the index page
Breaking changes what changed between major versions, and how to migrate

The header of jupytext_notebook_helper/tp.mk lists every configurable variable.

Metadata

Release files for jupytext-notebook-helper 2.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jupytext-notebook-helper 2.3.0
File Size Uploaded
jupytext_notebook_helper-2.3.0.tar.gz 99.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jupytext-notebook-helper 2.3.0
File Interpreter ABI Platform
jupytext_notebook_helper-2.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 167.8 kB

Release files / jupytext_notebook_helper-2.3.0.tar.gz

Download URL jupytext_notebook_helper-2.3.0.tar.gz
Size 99.5 kB
Tags Source
SHA-256 checksum
How to use checksums
585947b8e3c6636eb578ee535666b2d0844546eeb69fd0da1fff94cea9f2d252
BLAKE2b-256 checksum
How to use checksums
327e9b80c7621ab5911f8f1f861333b5e36ade5dce1925e679e676b75f8c5c0c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Release files / jupytext_notebook_helper-2.3.0-py3-none-any.whl

Download URL jupytext_notebook_helper-2.3.0-py3-none-any.whl
Size 68.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
28f4e4a574d6f30f40bebb964119f2ad27fc8a9e2e1f32e162087adf89199c68
BLAKE2b-256 checksum
How to use checksums
ba53d7329ccfb3c382ae18107a33789138364aece84ff9b41dbe8b48851e96c4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Release history Release notifications | RSS feed

3.2.0

2 release files

3.1.0

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.5.0

2 release files

2.4.0

2 release files

This release

2.3.0 This release

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.12.0

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page