Repo for lessons, homework, and course dev materials
This repository uses jupyterbook to render Jupyter Notebooks and other Markdown content as HTML, hosted on the repository's GitHub Pages site.
Notebooks can be launched in JupyterHub or downloaded for running locally.
Each lesson in the JupyterBook format has a launch button (rocket icon) in the upper right menu that provides an option to open the notebook in JupyterHub.
- For registered users, this link allows the user to open an executable notebook in LAI's instance of JupyterHub.
- Users who don't have access to LAI's JupyterHub can download the notebooks (from the same menu) for use in other environments: e.g., Jupyter Notebook/Jupyterlab, Google Colab, VS Code, etc.
- Note that the formatted notebooks require the Jupyterlab extension jupyterlab_myst. If this extension is not available, an alternative version of the notebook with less formatting can be obtained by appending
-md
to the name of the notebook in the download URL. For instance, to download the simple Markdown version of this notebook, the URL would behttps://gwu-libraries.github.io/python-camp/_sources/notebooks/homework/HW_1_from_code_to_data-md.ipynb
.
GitHub Classroom supports autograding of assignments submitted by students from a roster.
- Each assignment corresponds to a separate repo on GitHub. Each repo (example) should contain only the assignment notebook, a README, and, in a
course-utils
folder, theautograder.py
script from thecourse-utils
folder in the main Python Camp repo. - When a student accepts the invitation to an assignment, GitHub creates a new repo for that student for that particular assignment. (It's not currently possible to manage all assignments as a single repo with GitHub Classroom.)
- The student uploads their version of the homework notebook, and a GitHub Actions workflow runs the tests in
course-utils/autograder.py
against the committed file. - Pass/fail is recorded both in the student's repo and in the GitHub Classroom site.
- The student uploads their version of the homework notebook, and a GitHub Actions workflow runs the tests in
To manage development in these separate assignment repos, I am experimenting with the following workflow:
- Each homework assignment repo is linked to the main repo as a git submodule.
- These submodule links are housed within the
homework-modules
folder of the main repo. - To clone the repo with the submodules, run
git clone --recurse-submodules
on the main repo. - When running the
publish.sh
script, changes made to the homework notebooks will be copied into the appropriate submodule directory withinhomework-modules
, and changes pushed to the corresponding linked repo on GitHub. - Changes can be pulled from the remote repos using
git submodule update --remote --merge
(orgit submodule update --remote --rebase
).
- All files for processing by JupyterBook reside in the
textbook
directory of this repo. - Notebooks reside in
notebooks/lessons
ornotebooks/homework
and are labeled according to their sequence. - The
textbook/_toc.yml
file defines the Table of Contents for the JupyterBook; it contains the names and filenames (without extensions) of all pages for inclusion in the book. - Parsons Problems for select exercises are linked from the notebooks, using absolute URL's. To make a new Parsons Problem:
- Create a YAML file in the
textbook/parsons-yaml
directory, giving it a name that includes its lesson and sequence number. (homework-1-1.yml
refers to the first Parsons Problem in the notebook calledHW_1
.) - Each YAML file should contain two or three keys:
python_code
andproblem
are required,python_setup
is optional.- Provide a short description of the exercise under the
problem
key. - Provide the Python code (indented appropriately, if using code blocks) under the
python_code
key. - Any code under
python_setup
will be executed but not included in the Parsons Problem itself. This code can be used, for instance, to define a global variable to which the code inpython_code
should refer.
- Provide a short description of the exercise under the
- To link the Parsons Problem from the notebook, provide the full URL:
https://gwu-libraries.github.io/python-camp/parsons-problems/html/homework-1-1.html
.
- Create a YAML file in the
- To publish your changes, from the root of the repo, run the
./publish.sh
script. This script does the following:
- Builds Parsons Problems from the YAML files in
textbook/parsons-yml
. - Builds a clean copy of the book itself (using the
jupyter-book publish
command). This script converts the.ipynb
files to.html
. - Runs a postprocessing script to prepare the downloadable/executable notebooks, applying the following logic:
- MyST
{term}
directives are replaced with hard-coded links to glossary terms. - Cells with the
hide-cell
tag are coded for hidden in the Jupyterlab/Notebook 7 interface. - Cells with the
remove-cell
tag are deleted, and outputs from all code cells are cleared. - Markdown-alternative versions (with the
-md
suffix) are created, replacing MyST directives with regular Markdown or HTML code.
- MyST
- Copies any homework notebooks for autograding (these should be labeled as follows:
HW-1-GR
,HW-2-GR
, etc.) from thetextbook/notebooks/homework
directory to the appropriate subdirectory (these should be labeled as follows:python-camp-hw-1-gr
,python-camp-hw-2-gr
, etc.) in thehomework-modules
directory. These subdirectories are manages as git submodules; upon copying the files over, thepublish.sh
script will commit and push any changes (to the associated repos).
- From the root of the
python-camp
repo, create a new commit and push toorigin main
(to update the reference to the submodule commits).
- The provided
docker-compose.yml
file will build and launch a Jupyterlab/notebook server within a Docker container with the necessary extensions. Thenginx-proxy
container can be used to make the Jupyter server available on an open port (e.g., from an AWS server). Note that this setup does provide the full functionality of JupyterHub; the Docker image is used in production as part of a Kubernetes implementation of JupyterHub; this image provides only the Jupyter server component.