code / library / script for converting teacher notebook to student notebook?

91 views
Skip to first unread message

Gary Steele

unread,
Mar 7, 2025, 10:54:16 AMMar 7
to Teaching with Jupyter Notebooks
Dear all,

Does anyone know if there is a way to generate a "student copy" of a notebook from a "teacher copy" (aka. strip solutions and lock appropriate cells) that operates modularly and separately from a full nbgrader deployment / filesystem configuration?  

eg something like:

$ nbgrader_convert -i teacher_copy.ipynb -o student_copy.ipynb

Thanks!
Gary

Jason Moore

unread,
Mar 7, 2025, 11:00:47 AMMar 7
to Gary Steele, Teaching with Jupyter Notebooks

--
You received this message because you are subscribed to the Google Groups "Teaching with Jupyter Notebooks" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter-educat...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/jupyter-education/b83f53c5-0415-4ea3-9734-2790856cb271n%40googlegroups.com.

Gary Steele

unread,
Mar 7, 2025, 11:05:55 AMMar 7
to Teaching with Jupyter Notebooks
Hi Jason, 

Thanks for the quick response. 

The command seems quite rigid, it does assume that you have the "nbgrader filesystem hierarchy" configured. I guess I just need to replicate that in a folder and then collect the file in the default ouput dir ("source/test/test_file.ipynb" => "release/test/test_file.ipynb): I'll give it a try.

Cheers,
Gary

Jason Moore

unread,
Mar 7, 2025, 11:08:31 AMMar 7
to Gary Steele, Teaching with Jupyter Notebooks
HI Gary,

Yes, I think you have to adhere to the file structure for nbgrader.

Jason


Chris Holdgraf

unread,
Mar 7, 2025, 12:30:29 PMMar 7
to Jason Moore, Gary Steele, Teaching with Jupyter Notebooks
The jupyter book team is working on something like this right now actually. Would be very helpful to see +1s or suggestions that can help get that PR merged if you think it'd be helpful. It is not quite the same usecase but I think it might be useful for this. PR link below


Jonathan Gutow

unread,
Mar 7, 2025, 1:19:45 PMMar 7
to Teaching with Jupyter Notebooks
I wrote and use a package that might do part of what you want. It should be completely nbgrader agnostic. I use it to create notebooks for my students that are not coupled to any grading package, but do have locked cells and potential custom highlighting. I primarily use it to provide templates for students doing messy multistep analyses of laboratory data. It helps the analyses to come to me in a consistent format and prevents the students from deleting instructions and examples.
Some of the features (all menu driven):
  • The ability to set up data input tables that can create pandas data frames and survive clearing of cell output.
  • Adding highlight bars to markdown cells (I don't use this much).
  • Ability to protect/deprotect cells and mark them for collapse under selected conditions.
  • Ability to make it difficult for students to install the same package and use it on the notebook to deprotect cells.
More information at the github repo: https://github.com/JupyterPhysSciLab/jupyter-instructortools. I would be happy to get requests for abilities and collaborators interested in extending the tool.

Jonathan

Matthew Brett

unread,
Mar 7, 2025, 1:47:21 PMMar 7
to Jonathan Gutow, Teaching with Jupyter Notebooks
Hi,

I also wrote myself a standalone markup / processing pipeline, where I
annotate the notebooks like this:

https://github.com/matthew-brett/rmdex

and use the library to process the template notebook to a solution and
an exercise notebook.

I found it convenient to have this kind of minimal typing markup, to
make it as fluid as possible to generate the template notebooks.
Once you've got the markup in mind, you can write these things
quickly.

I can share more if that looks helpful. Specifically, I have a
script setup to generate these notebooks and ship to Github
repositories with associated test files, to give to the students.

Cheers,

Matthew
> To view this discussion visit https://groups.google.com/d/msgid/jupyter-education/23f636b5-6ffc-499c-afdb-e0cace755e01n%40googlegroups.com.

Aidan Feldman

unread,
Mar 7, 2025, 9:12:10 PMMar 7
to Matthew Brett, Jonathan Gutow, Teaching with Jupyter Notebooks
My approach was to write a small nbconvert preprocessor that swaps out cells with a `solution` tag:


# solution.py

from nbconvert.preprocessors import Preprocessor


class RemoveSolutions(Preprocessor):
    def preprocess(self, nb, resources):
        nb.metadata.pop("celltoolbar")
        return super().preprocess(nb, resources)

    def preprocess_cell(self, cell, resources, index):
        if "solution" in cell.metadata.get("tags", []):
            if cell.cell_type == "markdown":
                cell.source = "YOUR RESPONSE HERE"
            else:  # code
                cell.source = "# your code here"

        return cell, resources


$ jupyter nbconvert \
    --to notebook \
    --output-dir=dist/templates \
    --Exporter.preprocessors=solution.RemoveSolutions \
    --ClearOutputPreprocessor.enabled=True \
    --ClearMetadataPreprocessor.enabled=True \
    --ClearMetadataPreprocessor.clear_notebook_metadata=False \
    --ClearMetadataPreprocessor.preserve_cell_metadata_mask=tags \
    --TagRemovePreprocessor.enabled=True \
    --TagRemovePreprocessor.remove_cell_tags remove \
    ./*.ipynb


Hope that's helpful!

On Fri, Mar 7, 2025 at 1:47 PM Matthew Brett <matthe...@gmail.com> wrote:
Hi,

I also wrote myself a standalone markup / processing pipeline, where I
annotate the notebooks like this:


and use the library to process the template notebook to a solution and
an exercise notebook.

I found it convenient to have this kind of minimal typing markup, to
make it as fluid as possible to generate the template notebooks.
Once you've got the markup in mind, you can write these things
quickly.

I can share more if that looks helpful.   Specifically, I have a
script setup to generate these notebooks and ship to Github
repositories with associated test files, to give to the students.

Cheers,

Matthew

On Fri, Mar 7, 2025 at 6:19 PM 'Jonathan Gutow' via Teaching with
Jupyter Notebooks <jupyter-...@googlegroups.com> wrote:
>
> I wrote and use a package that might do part of what you want. It should be completely nbgrader agnostic. I use it to create notebooks for my students that are not coupled to any grading package, but do have locked cells and potential custom highlighting. I primarily use it to provide templates for students doing messy multistep analyses of laboratory data. It helps the analyses to come to me in a consistent format and prevents the students from deleting instructions and examples.
> Some of the features (all menu driven):
>
> The ability to set up data input tables that can create pandas data frames and survive clearing of cell output.
> Adding highlight bars to markdown cells (I don't use this much).
> Ability to protect/deprotect cells and mark them for collapse under selected conditions.
> Ability to make it difficult for students to install the same package and use it on the notebook to deprotect cells.
>

>
> Jonathan
>
>
> On Friday, March 7, 2025 at 11:30:29 AM UTC-6 chol...@gmail.com wrote:
>>
>> The jupyter book team is working on something like this right now actually. Would be very helpful to see +1s or suggestions that can help get that PR merged if you think it'd be helpful. It is not quite the same usecase but I think it might be useful for this. PR link below
>>
>>
>> On Fri, Mar 7, 2025, 8:08 AM Jason Moore <moore...@gmail.com> wrote:
>>>
>>> HI Gary,
>>>
>>> Yes, I think you have to adhere to the file structure for nbgrader.
>>>
>>> Jason
>>> moorepants.info
>>> +01 530-601-9791
>>>
>>>
>>> On Fri, Mar 7, 2025 at 5:05 PM Gary Steele <gste...@gmail.com> wrote:
>>>>
>>>> Hi Jason,
>>>>
>>>> Thanks for the quick response.
>>>>
>>>> The command seems quite rigid, it does assume that you have the "nbgrader filesystem hierarchy" configured. I guess I just need to replicate that in a folder and then collect the file in the default ouput dir ("source/test/test_file.ipynb" => "release/test/test_file.ipynb): I'll give it a try.
>>>>
>>>> Cheers,
>>>> Gary
>>>>
>>>> On Friday, 7 March 2025 at 17:00:47 UTC+1 moore...@gmail.com wrote:
>>>>>
>>>>> Dear Gary,
>>>>>
>>>>>
>>>>> Jason
>>>>> moorepants.info
>>>>> +01 530-601-9791
>>>>>
>>>>>
>>>>> On Fri, Mar 7, 2025 at 4:54 PM Gary Steele <gste...@gmail.com> wrote:
>>>>>>
>>>>>> Dear all,
>>>>>>
>>>>>> Does anyone know if there is a way to generate a "student copy" of a notebook from a "teacher copy" (aka. strip solutions and lock appropriate cells) that operates modularly and separately from a full nbgrader deployment / filesystem configuration?
>>>>>>
>>>>>> eg something like:
>>>>>>
>>>>>> $ nbgrader_convert -i teacher_copy.ipynb -o student_copy.ipynb
>>>>>>
>>>>>> Thanks!
>>>>>> Gary
>>>>>>
>>>>>> --
>>>>>> You received this message because you are subscribed to the Google Groups "Teaching with Jupyter Notebooks" group.
>>>>>> To unsubscribe from this group and stop receiving emails from it, send an email to jupyter-educat...@googlegroups.com.

>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google Groups "Teaching with Jupyter Notebooks" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send an email to jupyter-educat...@googlegroups.com.

>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups "Teaching with Jupyter Notebooks" group.
>>> To unsubscribe from this group and stop receiving emails from it, send an email to jupyter-educat...@googlegroups.com.
>>>

>
> --
> You received this message because you are subscribed to the Google Groups "Teaching with Jupyter Notebooks" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to jupyter-educat...@googlegroups.com.


--
You received this message because you are subscribed to the Google Groups "Teaching with Jupyter Notebooks" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jupyter-educat...@googlegroups.com.

Gary Steele

unread,
Mar 8, 2025, 3:07:38 AMMar 8
to Aidan Feldman, Matthew Brett, Jonathan Gutow, Teaching with Jupyter Notebooks

Thanks for all the replies, nice to see such an active community! I will try the first approach of replicating the folder structure first.

Cheers,
Gary


Nicolas M. Thiéry

unread,
Mar 8, 2025, 3:19:30 AMMar 8
to Teaching with Jupyter Notebooks
Thanks Gary for triggering that discussion!

Context + shameless advertisement: for many of our classes, we are
using GitLab for managing our student assignments, with a lightweight
tool to automate the process and make it easy to use for students and
instructor. It plays the role of nbgrader's exchange + autograding by
continuous integration:

    https://travo-cr.gitlab.io/travo/


I really like nbgrader's approach to authoring notebooks and
grading. But it's currently a pain to integrate in a different
workflow. For generating the student version of a single assignment
file, I have been for years working around nbgrader with the following
command line (+ appropriate configuration file), complemented with
additional commands before and after to support markdown notebooks
(jupytext) and further customization (see PS):

nbgrader generate_assignment Sources/Assignment1 "--db=sqlite:///Assignments/Assignment1/.gradebook.db" --create --force --notebook=notebook.ipynb --CourseDirectory.ignore="['*']"

This was unnecessarily complicated and painful to customize. Thereby,
like many of you, I recently ended up writing a small dedicated script
that does the same and some more (alternative concise metadata for
text notebooks, going beyond notebooks, ...):

    https://gitlab.com/travo-cr/travo-prepare

Reuse and feedback most welcome. I'd be happy as well working on
convergence with other similar attempts.

Cheers,
Nicolas


PS: here is the full Makefile rule I was using:

Assignment/%.md: %.md
mkdir -p `dirname $@`
jupytext --to ipynb $<
nbgrader generate_assignment `dirname $*` "--db=sqlite:///Devoirs/`dirname $*`/.gradebook.db" --create --force --notebook=`basename $*` --CourseDirectory.ignore="['*']"
rm $*.ipynb
jupyter nbconvert --inplace $(NBGRADER_REMOVE_INSTRUCTOR) Devoirs/$*.ipynb
jupytext --to myst Devoirs/$*.ipynb
rm Devoirs/$*.ipynb

Nicolas M. Thiéry

unread,
Mar 8, 2025, 9:51:17 AMMar 8
to Teaching with Jupyter Notebooks

I'll use the occasion for a related advertisement for those of you
using nbgrader's syntax to markup solutions (BEGIN SOLUTION / END
SOLUTION markers) and jupyter-book: I have written a quick and dirty
css/javascript extension that, in the web export, hides the solutions
in a dropdown. One can reveal each solution independently, or all at
once using a slider in the topbar. You can also configure the
extension to not make the solutions visible at all, or only for
certain files. It also handles comments for instructors written in a
MyST admonition with a specific title.

It's been in use form a semester and a half now here, and students and
instructors have found it quite useful. Previously, my web export had
three copies of each page; one for students, one for solutions, and
one for instructors; it was a pain to navigate, slow to compile, and a
pain for crosslinks.


Examples of how it looks like:

https://nicolas.thiery.name/Enseignement/Info111/Semaine1/TD.html
https://nicolas.thiery.name/Enseignement/Info111/Semaine1/2a.html


Usage:

Download the following three files, and drop them in the _static
directory of the sources of your jupyterbook. You may want to edit the
file show-hide-solutions.js to customize the few French strings to
your preferred language.

https://nicolas.thiery.name/Enseignement/Info111/_static/show-hide-solutions.js
https://nicolas.thiery.name/Enseignement/Info111/_static/show-hide-solutions.css
https://nicolas.thiery.name/Enseignement/Info111/_static/jquery-3.7.1.min.js.js

Feedback welcome!

Enjoy,
Nicolas

Gary Steele

unread,
Mar 12, 2025, 8:04:49 AMMar 12
to Teaching with Jupyter Notebooks
Just to share with others and google: the "replicated file hiearchy" did work:

Screenshot 2025-03-12 at 13.03.20.png

Thanks!



Gary Steele

unread,
Mar 12, 2025, 8:49:21 AMMar 12
to Teaching with Jupyter Notebooks
By the way, I did notice that the functionality of locking cells did not work in Jupyterlab after the conversion. It seems that for jupyterlab to work with locking, you need some extra metadata parameters ("deletable" and "editable"), the left is from nbgrader, the right is a different conversion process which did work:

Screenshot 2025-03-12 at 13.45.22.png

I installed things from conda-forge (via micromamba) which gave me nbgrader 0.9.5:

List of packages in environment: "/Users/gsteele/micromamba/envs/nbgrader"

  nbgrader                       0.9.5           pyhd8ed1ab_0          conda-forge


Reply all
Reply to author
Forward
0 new messages