> For the complete documentation index, see [llms.txt](https://docs.nuvolos.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nuvolos.com/how-to-guides/workflows-for-instructors/setting-assignments/programmatical-assignment-handling.md).

# Programmatic assignment handling

<mark style="color:$primary;">**Outcome**</mark>\
You collect, grade, and hand back assignments at the command line using nvcollect, integrated with otter-grader.

{% hint style="warning" %}
This is a new and experimental feature of Nuvolos, please provide us with feedback to make it better!
{% endhint %}

<mark style="color:$primary;">**Before you start**</mark>

* You have access to a JupyterLab + TeX Live application.
* `otter-grader` and `pandoc` are available in the application (TeX Live is available on request from Nuvolos support).
* You have installed `nvcollect` (contact support for the current install command).
* You are working in the Master Instance.

{% hint style="info" %}
To install `nvcollect`, run the following command from the terminal in your JupyterLab application:

```bash
pip install --upgrade git+https://github.com/alphacruncher/nv-collect
```

{% endhint %}

`nvcollect` is a command-line tool available in supported applications. It lets you:

* Collect assignments from all students into a folder in your instance.
* Grade assignments with the `otter-grader` package.
* Hand back assignments to all students in one command.

### Otter Grader integration

Below is a complete pipeline integrating `nvcollect` with `otter-grader`. It assumes you have already set up a JupyterLab application with `otter-grader`, `pandoc`, and `TeX Live`.

{% stepper %}
{% step %}

#### Obtain the Otter tutorial files

In a JupyterLab terminal, download the Otter Grader tutorial files. Refer to the [otter-grader documentation](https://otter-grader.readthedocs.io/) for the current download command.
{% endstep %}

{% step %}

#### Modify `demo.ipynb` for headless use

The Otter Grader `demo.ipynb` assumes a windowed environment, which is not available on Nuvolos. In the second cell, replace the windowed call with the headless equivalent:

```sql
%matplotlib inline
```

Make sure to have:

```sql
import matplotlib
matplotlib.use('Agg')
```

{% endstep %}

{% step %}

#### Run `otter assign`

In the directory where you extracted the tutorial archive, run:

{% code overflow="wrap" %}

```sql
otter assign demo.ipynb dist --v1
```

{% endcode %}

This creates a `dist/` directory containing autograding artefacts and the student-facing assignment file at `dist/student/demo.ipynb`.
{% endstep %}

{% step %}

#### Create the assignment on Nuvolos

Copy `dist/student/demo.ipynb` to a clean folder under `/files`, then stage and distribute it as an Assignment (see [Creating an assignment](/how-to-guides/workflows-for-instructors/setting-assignments.md#creating-an-assignment) above). \
For example, copy from `/files/otter-test/dist/student/demo.ipynb` to `/files/assignment_1/demo.ipynb`, stage `/files/assignment_1/`, and create an assignment named 'assignment\_1'.

{% hint style="info" %}
Keeping the assignment name in Nuvolos the same as the folder name (assignment\_1) is a useful convention - it is not required, but it makes the `nvcollect` command much easier to remember.
{% endhint %}
{% endstep %}

{% step %}

#### Collect hand-ins

Once the deadline has passed, collect submissions:

{% code overflow="wrap" %}

```sql
nvcollect collect \
  --assignment_name "assignment_1" \
  --assignment_folder assignment_1 \
  --target_folder /files/test_collect
```

{% endcode %}

This gathers everything in the *assignment\_1* folder of the *assignment\_1* assignment from all students into `/files/test_collect/`. The directory structure is:

{% code overflow="wrap" %}

```sql
/files/test_collect
+-- nvcollect_manifest.json
+-- single_user_inst_<code1>
|   +-- ...
+-- single_user_inst_<code2>
|   +-- ...
```

{% endcode %}
{% endstep %}

{% step %}

#### Grade hand-ins

Run autograding across all collected submissions:

{% code overflow="wrap" %}

```sql
nvcollect otter-grade \
  --source_folder /files/test_collect \
  --autograder_location /files/otter-test/dist/autograder/autograder.zip \
  --relative_path demo.ipynb
```

{% endcode %}

Three notes:

* `source_folder` is the same as the `target_folder` from the collect command.
* `autograder_location` is the absolute path to the autograder zip from step 3.
* `relative_path` tells the tool where to look inside each student folder for the notebook to grade.

After grading, `source_folder` contains:

* A `grade.csv` file at the top level with the score of each student.
* A `grade.csv` file inside each student folder with that student's score.
  {% endstep %}

{% step %}

#### Hand back the results

Optionally add additional artifacts to each student folder (manually or programmatically), then push results back to students:

{% code overflow="wrap" %}

```sql
nvcollect handback --source_folder /files/test_collect
```

{% endcode %}

`source_folder` here is the same folder where collection and grading happened.
{% endstep %}
{% endstepper %}

### Collecting assignments for download and archival

Starting version `1.0.0` of `nuvolos-collect`, the library provides the `nvcollect archive` command. This command collects submissions grouped by assignment and create a zip file per assignment into a target folder.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.nuvolos.com/how-to-guides/workflows-for-instructors/setting-assignments/programmatical-assignment-handling.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
