Skip to main content

finalgrade

Final grades from a Gradescope or Canvas csv export — category weights, dropped lowests, best-n-of-m, late penalties, per-student waivers.

matthigger.github.io/finalgrade

Build your grading policy in the browser. Drop in your gradebook, click through the policy, watch every grade move as you change it, and download the results. Nothing to install.

Your grades never leave your computer. The page downloads a Python interpreter and runs this package inside the tab — there is no server to send anything to. Once it has loaded you can disconnect from the network and it keeps working.

The policy you build downloads as a policy.yaml. Keep it: drop it back in next time to pick up where you left off, hand it to a TA, or run it from the command line. Nothing is stored between visits, so that file is the thing to save.

What it does

  • Category weights — homework 50%, exams 50%. Assignments match categories by substring, so hw1hw9 land in hw without listing them.
  • Drop lowest — the n worst scores in a category, never the extra credit.
  • Keep highest — only the n best count, however many were attempted: six puzzles where any two count, and a student short of two averaged over zeros. One rule or the other per category, never both.
  • Late penalties — a rate per day, a bank of excused days per student, and a grace period so nobody emails you about 90 seconds. Per-student adjustments for DRC accommodations. Only the scores that count charge late days — work that isn't in the grade can't be late.
  • Waivers — click a score to waive the assignment, click a late submission to forgive just the penalty. Computed as if the work was never assigned.
  • Extra credit — points that count towards what a student earned but not towards what was available.
  • Makeups and retakes — drag one score onto another to take the better of the two, for the makeup only one student sat, without inventing a course-wide rule for it.
  • Work you haven't set yet — write a whole term's policy in one sitting; planned assignments count for nobody until the real column arrives.
  • Letter grades — editable cutoffs, sensible defaults.
  • Per-student breakdowns — a csv per student that ends with how the grade was reached: what was waived, which scores counted and which didn't, what was late and what that cost, how the categories combined. It's the attachment for the email asking why a grade is what it is.
  • Notes — free text on a student, stored beside the waiver it explains, so the reason outlives the email thread.
  • Inspect — the distribution of any category or assignment, before and after your policy, where hovering a bar names the students in it. Not "what is the shape of the class" but "who is sitting just under the A− line?"
  • Exportsgrade_full.csv, a Canvas upload merged by SIS id, and a Banner .xlsx.

It refuses to guess. Grades are hard to eyeball, so a policy that can't mean what you intended is an error rather than plausible-looking numbers: a category matching no assignment, a misspelled setting nothing reads, a threshold written 93 where .93 was meant, a waiver on an email nobody has. The error names the closest real setting or student.

Command line

The same code, same policy file, same results.

pip install finalgrade
finalgrade grade scope.csv                        # grades, and seeds a policy.yaml
$EDITOR policy.yaml                               # weights, score rules, late
finalgrade check scope.csv --policy policy.yaml   # what will that policy do?
finalgrade grade scope.csv --policy policy.yaml   # grade with it

The seeded policy.yaml lists your assignments by the names a policy has to use and suggests a category split, commented out. Editing it is the middle step — until you do, every assignment counts in proportion to its own points.

check answers "what will this do?" without computing any grades, reports every problem at once, and exits non-zero when grading would fail — so it works in a script. It wants the policy named outright and will not write one for you: a report on a file finalgrade just seeded tells you only what finalgrade guessed.

$ finalgrade check scope.csv --policy policy.yaml
grade source : scope.csv (gradescope)
students     : 5
assignments  : 4 graded, 0 excluded

assignment  points  submitted  category
----------  ------  ---------  ------------------------------------
hw1         1       1/5        hw
hw2         2       2/5        hw
hw3         3       5/5        hw
quiz1       4       5/5        (none) <- not graded in any category

category  weight  drop/keep  late                assignments
--------  ------  ---------  ------------------  -------------------------------
hw        50.0%   drop 1     15%/day, 3 excused  hw1, hw2, hw3
exam      50.0%   -          -                   (none) <- matches no assignment

error: category matches no assignment: exam (assignments are: hw1, hw2, hw3, quiz1)

policy has an error, grading would stop here

Other flags: -o output path, --late_csv late days per student-assignment, --per_student a csv each, --new-policy a fresh one, -q quiet. Run finalgrade grade --help for the full list.

Grading from Canvas

grade also takes a Canvas export (Grades > Export), told apart by its columns. Two differences are forced by what Canvas puts in the file: there are no submission times, so late penalties are refused rather than silently computing to zero; and students may be keyed by SIS ID rather than email. Excused (EX) becomes a waiver. In exchange, a policy seeded from a Canvas export takes its suggested categories from your Canvas assignment groups rather than guessing from names.

Uploading grades

finalgrade canvas grade_full.csv canvas.csv --scale100
finalgrade banner grade_full.csv 202310 -c 12345 -c 67890

See doc/upload_canvas.md and doc/upload_banner.md.

Policy reference

doc/policy.md — every setting a policy.yaml can hold, and everything that gets checked.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

finalgrade-0.2.2.tar.gz (61.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

finalgrade-0.2.2-py3-none-any.whl (68.8 kB view details)

Uploaded Python 3

File details

Details for the file finalgrade-0.2.2.tar.gz.

File metadata

  • Download URL: finalgrade-0.2.2.tar.gz
  • Upload date:
  • Size: 61.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for finalgrade-0.2.2.tar.gz
Algorithm Hash digest
SHA256 be27a87a9e384033855e1e779ce2c5d3cfeb03d36b5f0983b0d03f9e0eadc4f9
MD5 160f9d974e9138704c0529b24662a48f
BLAKE2b-256 b81370a70b86ea5f24484c60359bfc4ff9932069026ff28a3d733e8968b1cde1

See more details on using hashes here.

File details

Details for the file finalgrade-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: finalgrade-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 68.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for finalgrade-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4c36b1ca00263192458841ed7e92547e437f76b327ba49bf75d0b5b2d47e721c
MD5 9dec536fe2718ee0c0db9f3c8fc5e251
BLAKE2b-256 898f65e9296eb6120ee9925b7b69c28604ec6d428a45628da86460914f7f79d0

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.4

2 files

0.2.3

2 files

This release

0.2.2 This release

2 files

0.2.1

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page