Distributing assignments to students and collecting them can be a logistical nightmare. If you are running nbgrader on a server, some of this pain can be relieved by relying on nbgrader's built-in functionality for releasing and collecting assignments on the instructor's side, and fetching and submitting assignments on the student's side.
After an assignment has been created using nbgrader assign
, the instructor must actually release that assignment to students. If the class is being taught on a single filesystem, then the instructor may use nbgrader release
to copy the assignment files to a shared location on the filesystem for students to then download.
First, we must specify a few configuration options. We'll need to use these a few times, so we'll create a nbgrader_config.py
file that will get automatically loaded when we run nbgrader
:
In [1]:
%%file nbgrader_config.py
c = get_config()
c.NbGrader.course_id = "example_course"
c.TransferApp.exchange_directory = "/tmp/exchange"
In the config file, we've specified the "exchange" directory to be /tmp/exchange
. This directory must exist before running nbgrader
, and it must be readable and writable by all users, so we'll first create it and configure the appropriate permissions:
In [2]:
%%bash
# remove existing directory, so we can start fresh for demo purposes
rm -rf /tmp/exchange
# create the exchange directory, with write permissions for everyone
mkdir /tmp/exchange
chmod ugo+rw /tmp/exchange
Now that we have the directory created, we can actually run nbgrader release
(and as with the other nbgrader commands for instructors, this must be run from the root of the course directory):
In [3]:
%%bash
nbgrader release "ps1"
Finally, you can verify that the assignment has been appropriately released by running the nbgrader list
command:
In [4]:
%%bash
nbgrader list
Note that there should only ever be one instructor who runs the nbgrader release
and nbgrader collect
commands (and there should probably only be one instructor -- the same instructor -- who runs nbgrader assign
, nbgrader autograde
and nbgrader formgrade
as well). However this does not mean that only one instructor can do the grading, it just means that only one instructor manages the assignment files. Other instructors can still perform grading by accessing the formgrader URL.
From the student's perspective, they can list what assignments have been released, and then fetch a copy of the assignment to work on. First, we'll create a temporary directory to represent the student's home directory:
In [5]:
%%bash
# remove the fake student home directory if it exists, for demo purposes
rm -rf /tmp/student_home
# create the fake student home directory and switch to it
mkdir /tmp/student_home
If you are not using the default exchange directory (as is the case here), you will additionally need to provide your students with a configuration file that sets the appropriate directory for them:
In [6]:
%%file /tmp/student_home/nbgrader_config.py
c = get_config()
c.TransferApp.exchange_directory = '/tmp/exchange'
c.NbGrader.course_id = "example_course"
From the student's perspective, they can see what assignments have been released using nbgrader list
, and passing the name of the class:
In [7]:
%%bash
export HOME=/tmp/student_home && cd $HOME
nbgrader list
They can then fetch an assignment for that class using nbgrader fetch
and passing the name of the class and the name of the assignment:
In [8]:
%%bash
export HOME=/tmp/student_home && cd $HOME
nbgrader fetch "ps1"
Note that running nbgrader fetch
copies the assignment files from the exchange directory to the local directory, and therefore can be used from any directory:
In [9]:
%%bash
ls -l "/tmp/student_home/ps1"
Additionally, the nbgrader fetch
(as well as nbgrader submit
) command also does not rely on having access to the nbgrader database -- the database is only used by instructors.
The image above shows that there has been one assignment released ("ps0") for the class "cogsci131". To get this assignment, students can click the "Fetch" button (analogous to running nbgrader fetch ps0 --course cogsci131
. Note: this assumes nbgrader is always run from the root of the notebook server, which on JupyterHub is most likely the root of the user's home directory.
After the assignment is fetched, it will appear in the list of "Downloaded assignments":
Students can click on the name of the assignment to expand it and see all the notebooks in the assignment:
Clicking on a particular notebook will open it in a new tab in the browser.
First, as a reminder, here is what the student's nbgrader_config.py
file looks like:
In [10]:
%%bash
cat /tmp/student_home/nbgrader_config.py
After working on an assignment, the student can submit their version for grading using nbgrader submit
and passing the name of the assignment and the name of the class:
In [11]:
%%bash
export HOME=/tmp/student_home && cd $HOME
nbgrader submit "ps1"
Note that "the name of the assignment" really corresponds to "the name of a folder". It just happens that, in our current directory, there is a folder called "ps1":
In [12]:
%%bash
export HOME=/tmp/student_home && cd $HOME
ls -l "/tmp/student_home"
Students can see what assignments they have submitted using nbgrader list --inbound
:
In [13]:
%%bash
export HOME=/tmp/student_home && cd $HOME
nbgrader list --inbound
Importantly, students can run nbgrader submit
as many times as they want, and all submitted copies of the assignment will be preserved:
In [14]:
%%bash
export HOME=/tmp/student_home && cd $HOME
nbgrader submit "ps1"
We can see all versions that have been submitted by again running nbgrader list --inbound
:
In [15]:
%%bash
export HOME=/tmp/student_home && cd $HOME
nbgrader list --inbound
Note that the nbgrader submit
(as well as nbgrader fetch
) command also does not rely on having access to the nbgrader database -- the database is only used by instructors.
After students have worked on the assignment for a while, but before submitting, they can validate that their notebooks pass the tests by clicking the "Validate" button (analogous to running nbgrader validate
). If any tests fail, they will see a warning:
If there are no errors, they will see that the validation passes:
Once students have validated all the notebooks, they can click the "Submit" button to submit the assignment (analogous to running nbgrader submit ps0 --course cogsci131
). Afterwards, it will show up in the list of submitted assignments (and also still in the list of downloaded assignments):
Students may submit an assignment as many times as they'd like. All copies of a submission will show up in the submitted assignments list, and when the instructor collects the assignments, they will get the most recent version of the assignment:
First, as a reminder, here is what the instructor's nbgrader_config.py
file looks like:
In [16]:
%%bash
cat nbgrader_config.py
After students have submitted their assignments, the instructor can view what has been submitted with nbgrader list --inbound
:
In [17]:
%%bash
nbgrader list --inbound
The instructor can then collect all submitted assignments with nbgrader collect
and passing the name of the assignment (and as with the other nbgrader commands for instructors, this must be run from the root of the course directory):
In [18]:
%%bash
nbgrader collect "ps1"
This will copy the student submissions to the submitted
folder in a way that is automatically compatible with nbgrader autograde
:
In [19]:
%%bash
ls -l submitted
Note that there should only ever be one instructor who runs the nbgrader release
and nbgrader collect
commands (and there should probably only be one instructor -- the same instructor -- who runs nbgrader assign
, nbgrader autograde
and nbgrader formgrade
as well). However this does not mean that only one instructor can do the grading, it just means that only one instructor manages the assignment files. Other instructors can still perform grading by accessing the formgrader URL.