CourseLink CSV grading helper
Project description
CourseLink CSV Grading Helper
If your use-case includes grading on CourseLink this tool may save you time entering grades into CourseLink. It supports entering a numeric grade for 1 deliverable at a time. It would mainly be useful for grading physical assignments.
First export a csv for the particular Assignment being graded, for the class section you intend to grade. Then run the program in the dir where the csv lives... Thats it! The program will act as a harness to speed up entering the grades, and it can format the csv for you so that it is ready to be imported back into CourseLink once your done entering grades.
This project is a Typer CLI for CourseLink CSV exports. It can easily be installed as a PyPi package or built from source. The program will prefer FZF if installed, but has fallback functionality in pure-python as well.
The source lives under src/, and the packaged CLI command is courselink-grader.
Install
Install from PyPI
After publishing, the simplest global installs are:
uv tool install courselink-grader
# or
pipx install courselink-grader
That puts courselink-grader on your PATH, so you can run it from any directory.
Install from this repo during development
uv tool install .
# or, for a project-local environment:
uv sync
Usage
Run courselink-grader from the directory that contains your grading files, or pass --root to browse somewhere else.
CSV files can live directly in the current directory or in nested folders such as ./grading/assignments/assignment1.csv.
Run menu mode (choose a workflow from the prompt):
courselink-grader
Direct command usage:
# Import helper: ready-to-import CSV
courselink-grader import-helper
courselink-grader import-helper --csv "grading/assignments/assignment1.csv" --out "ready_import.csv"
courselink-grader import-helper --csv "grading/assignments/assignment1__progress.csv"
courselink-grader import-helper --csv "grading/assignments/assignment1__progress.csv" --fresh-csv "grading/assignments/assignment1_fresh_export.csv"
courselink-grader import-helper --root "~/Courses/CS101"
# Grading harness: interactive grading
courselink-grader grading-harness
courselink-grader grading-harness --csv "grading/assignments/assignment1.csv"
courselink-grader grading-harness --csv "grading/assignments/assignment1.csv" --progress-out "my_progress.csv"
courselink-grader grading-harness --root "~/Courses/CS101"
What it does
Import helper (import-helper)
- Loads a CourseLink export CSV.
- If
fzfis installed, prompts whether to usefzffor CSV selection. - Detects the assignment grade column by matching
"Points Grade"in the header. - For a plain CourseLink export, creates a new CSV that is ready to import by removing rows where the grade cell is empty.
- For a
__progress.csv, compares it against the original export byOrgDefinedIdand only keeps rows whose normalized grade changed. - Optional
--fresh-csvlets you merge those changed grades onto a fresh CourseLink export before writing the import-ready CSV. - Keeps all columns and headers unchanged for remaining rows, including
End-of-Line Indicator. - Keeps valid
0grades. - Refuses to merge when the original export and fresh export cannot be proven compatible.
Grading harness (grading-harness)
- Opens a CSV and runs an interactive grading harness.
- If
fzfis installed, prompts whether to usefzffor CSV and student selection. - Without
fzf, the built-in CSV picker starts at the current working directory by default and behaves like a simple directory tree:- arrow keys move the selection
EnterorRightopens a directory or selects a CSVLeftorBackspacemoves to the parent directory
--root PATHlets you override where CSV browsing starts.- In
fzfmode, student matching uses case-insensitive fuzzy matching against a hidden search key (name, username, IDs) while showing a clean display column for stable selection. - Uses ranked fuzzy search (live filter, arrow keys, Enter) to find students by:
Last NameFirst NameUsernameOrgDefinedId
- Prioritizes stronger matches (for example,
Coleshould rank above weaker partial matches). - If you press Enter after typing a close match (even without explicitly accepting completion text), it resolves to the best student match.
- Displays
UsernameandOrgDefinedIdwithout the leading#for readability (the saved CSV still keeps original values). - If
fzfselection is cancelled or fails, it falls back to the built-in picker. - Lets you enter decimal grades and validates:
- grade is not empty
- grade is numeric
- grade is not negative
- grade is
<= MaxPointsparsed from header text like:Homework 6 Points Grade <Numeric MaxPoints:12 Weight:1>
- Autosaves after every entered grade into a progress CSV in the current directory.
- Writes a sidecar metadata file next to the progress CSV so import prep can find the original export safely later.
- Supports resume by reopening that progress CSV.
- Keyboard controls:
Ctrl-Q: open the post-grading menuCtrl-B: jump to previously graded studentF2: open the same post-grading menu without leaving the session
- Post-grading menu options:
- resume grading
- prep import immediately from changed rows only
- prep import using a fresh CourseLink export
- exit
Notes
- When
--csvis not provided, CSV selection starts at the current working directory by default. - The built-in picker shows only directories that contain at least one CSV somewhere below them, plus CSV files in the current directory.
fzfmode searches recursively across CSV paths under the active browse root.fzfis optional and not a Python dependency; install separately if desired.- Progress files use
__progress.csvsuffix by default. - Progress metadata uses
__progress.meta.jsonsuffix by default. - Output from
import-helperuses__ready_to_import.csvsuffix by default. - When exporting the CSV from CourseLink, I use these options. Results may vary with other export settings:
- Key Field:
Both - Grade Values:
Points grade- no weighted grade or grade scheme
- User Details:
- Last Name
- First Name
- Section Membership
- Key Field:
Release Workflow
- For local publishing, use a PyPI token with
UV_PUBLISH_TOKENinstead of entering credentials interactively. - For CI/CD publishing, this repo includes GitHub Actions workflows for pull-request CI and tagged PyPI releases.
- The recommended flow is feature branch -> pull request -> merge to
main-> version bump ->vX.Y.Ztag -> publish workflow. - Detailed setup and release steps are in
RELEASING.md.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file courselink_grader-0.2.0.tar.gz.
File metadata
- Download URL: courselink_grader-0.2.0.tar.gz
- Upload date:
- Size: 18.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
210b476e01df73f15da98726fe0cdaaefab622e2d86dc2338eff0f940674e8bb
|
|
| MD5 |
5cd249219d3a9be2f20dcef58e34ee57
|
|
| BLAKE2b-256 |
b7357564f617c92f8da29f587f4b4e1e982b04a0b2bd8fa5a81ca649a8a15682
|
File details
Details for the file courselink_grader-0.2.0-py3-none-any.whl.
File metadata
- Download URL: courselink_grader-0.2.0-py3-none-any.whl
- Upload date:
- Size: 16.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
760da95bd09912ccf0b90375a85914f5199caf048d788b41a7001f53792117d8
|
|
| MD5 |
e148304dba3ebc63f98224dd731d9035
|
|
| BLAKE2b-256 |
a12df0fdc28b64fd52b1fb208d7ccb1ad3cc2cedeb939251fb444a709fd7ed10
|