1
0
Files
csss590-attendance/README.md
Benjamin Mako Hill 5c08dce46e Link the Canvas Roll Call docs in two README mentions
Replace the FIXME placeholder in the opening with the Instructure
Community article that describes the Roll Call (Attendance) LTI tool,
and link the same article from the Requirements bullet so someone
scanning to confirm they have what they need can click through.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 19:36:16 -07:00

9.5 KiB
Raw Blame History

csss590-attendance

A small Python tool for instructors of CSSS 590 (or any similar attend-N-of-M seminar that uses Canvas Roll Call) to keep track of attendance week to week, to warn students at risk of falling below the required count, and to print a final pass/fail summary at the end of the quarter.

CSSS 590 is the course that provides credit to folks attending the weekly CSSS seminar series at the University of Washington. Students must attend a set number of those seminars to get credit.

The script reads the weekly attendance export that the Canvas Roll Call tool emails you, cross-references it against the live Canvas enrollment, and sends warning DMs through the Canvas Conversations API. A small Python script writes a short note to each student—scoped to the course—in the same language you would have written yourself.

This started as a one-quarter, one-instructor tool. It is published in case it is useful to others teaching CSSS 590 or a similar course.

What it does

The single entry point is review_attendance.py. It has three modes:

  • Review (default)—print a students × sessions attendance grid and a sorted X/N totals list. No Canvas writes; no email; just a picture of where the class stands. Useful for the weekly look.

  • --send-warning—same review output, plus a preview of which students are at or past the warning threshold (derived as sessions_expected sessions_required) and the rendered text of the DM each one would receive. Still no Canvas writes. This is the inspect-before-you-commit step.

  • --send-warning -f—actually POSTs each warning to the Canvas Conversations API as a 1:1 DM scoped to the course, and appends each recipient to students_contacted.tsv so subsequent runs skip them. The -f is intentional friction: nothing here can be un-sent.

A separate --final-report mode (mutually exclusive with --send-warning) prints a PASS/FAIL breakdown at the end of the quarter, annotated with the warning dates from the contact log.

Requirements

  • Python 3.11 or newer (the script uses tomllib from the standard library, which appeared in 3.11).
  • The requests library (pip install requests or apt install python3-requests). Everything else is in the stdlib.
  • A Canvas instance with the Roll Call (Attendance) LTI tool and personal API access enabled for you as the instructor.

Setup

  1. Clone this repository:

    git clone https://gitea.communitydata.science/mako/csss590-attendance.git
    cd csss590-attendance
    
  2. Install the one Python dependency:

    pip install requests
    
  3. Get a Canvas API access token. In Canvas: Account → Settings → Approved Integrations → "+ New Access Token". Give it a label so you can find it later. Copy the token immediately—Canvas only shows it once.

  4. Copy the example config and fill it in:

    cp config.toml.example config.toml
    

    Open config.toml in your editor and set canvas_id (the number in your course URL), base_url if you are not at canvas.uw.edu, and the token field. The token can also come from token_command (a shell command that prints the token—handy if you keep it in a password manager) or from the CANVAS_TOKEN environment variable; see comments in config.toml.example for details.

  5. Drop the Roll Call CSV in this directory whenever a new one arrives. The script picks the latest matching attendance_reports_*.csv automatically. You can also pass --csv FILE to point at a specific file.

Weekly workflow

The script is one piece of a wider weekly rhythm. The full process:

  1. Collect attendance on paper during class. A printed sign-in sheet beats fumbling with a laptop and is what students see you doing.

  2. Transcribe to Roll Call in Canvas after class. Open the Roll Call (Attendance) tool and mark each student present or absent for that day's session.

  3. Request the attendance report in Canvas. Roll Call's "Settings" gear has an "Attendance Report" link; leave all the options at their defaults. Canvas will email the CSV to you, usually within a few minutes.

  4. Save the emailed CSV into this directory. The script picks the lexicographically last attendance_reports_*.csv it finds, so renaming the file to start with a date (e.g. attendance_reports_20260520-<uuid>.csv) ensures the newest week's file is the one the script reads. If you have a reason to use a different file for a given run, pass --csv FILE.

  5. Review the week:

    python3 review_attendance.py
    

    Look at the grid and the X/N totals. Confirm the new column matches your records and that nobody's count is surprising. If a student is at the warning threshold, preview what the warning DM would say:

    python3 review_attendance.py --send-warning
    

    This still does not write to Canvas—it renders the message each at-risk student would receive so you can read them before they leave your machine.

  6. Send the warnings when the preview looks right:

    python3 review_attendance.py --send-warning -f
    

    Each warning becomes a 1:1 Canvas conversation tagged with the course, and the student is appended to students_contacted.tsv so subsequent runs skip them.

End of quarter

python3 review_attendance.py --final-report

Prints PASS/FAIL groupings against sessions_required. Students who were warned earlier in the quarter still carry their warning date in the output so you can see the full story at a glance.

For students who finished below the line, failed_message.txt is a hand-substituted template you can use to write each of them a note explaining their options. It is not wired into the script; see "Templates" below.

Templates

email_template.txt is rendered as a Python f-string for each warned student. The template author has the following names in scope:

name meaning
name the student's full name from Canvas
first_name first whitespace-separated token of the name
attended how many sessions the student has attended
sessions_held how many sessions have been held so far
sessions_remaining sessions still to come this quarter
sessions_required from config
sessions_expected from config

Because the template is evaluated as an f-string, any expression that references these names is valid. The shipped template uses one conditional to render either "all" or a number depending on how many of the remaining sessions a student still needs to attend.

failed_message.txt is a separate template intended for hand-use at the end of the quarter when a student has missed too many sessions to pass. It uses {{double-brace}} markers (not f-string syntax) and is not wired into the script—substitute by hand and send through the Canvas inbox or by re-using the small POST snippet at the bottom of review_attendance.py.

Roll Call quirks

A few things worth knowing if you start poking at the data yourself:

  • The Roll Call CSV has a trailing empty field on every data row but not on the header—15 columns of data versus a 14-column header. Naive csv.DictReader (or R's read.csv) gets confused. The script supplies explicit field names with an extra "Extra" column to work around this.

  • Sessions where a student wasn't marked at all have no row in the CSV—they are not silently recorded as "absent". The script derives absences as sessions_held attended, which counts an unmarked session the same as an explicit absence. This is the right behavior for grading purposes but can surprise you if you trust the row count.

  • Per-session attendance is not reachable through the Canvas API using a personal access token. Roll Call's own backend (at rollcall.instructure.com) requires an LTI launch JWT, not the Canvas token. The Canvas Submissions API can give you the cumulative attendance percentage for the Roll Call assignment, but not the per-day breakdown. The emailed CSV remains the only easy source of per-session detail.

Source and contributing

The repository lives at gitea.communitydata.science/mako/csss590-attendance. Issues and pull requests are welcome there—a tweak to a template, a better config field, a wrinkle in a different Canvas instance. If you are adapting this for a different course, a PR that generalizes a class-specific assumption (instead of forking quietly) helps everyone who comes after you.

Please don't publish any student records in git! To help prevent this, .gitignore keeps config.toml, the Roll Call CSVs, the contact log, the final summary CSV, and incidental archival material (screenshots, PDFs, SVGs) out of git. The intent is that nothing you commit could identify a student. Before pushing, run git status to confirm only the script, templates, and example config are tracked.

Credit

Written by Benjamin Mako Hill for CSSS 590 at the University of Washington in spring 2026, with substantial help from Claude. The Roll Call API exploration was constrained by what a personal Canvas access token can reach. If Instructure ever opens the Roll Call backend up to instructor tokens, the workflow could be tightened considerably.