Features

Everything PyAutoGrader can do for your Python classroom.

Build

Assignment Creation

Create, configure, and distribute assignments from a single desktop application

๐Ÿ”’

Encrypted .agr Files

Assignments export as encrypted files that students cannot reverse-engineer. Solutions, expected values, and SMTP credentials are never visible to students.

๐Ÿ“

Multi-File Support

Target tests to specific files within an assignment. The student app auto-detects related files in the same directory when a student selects one.

๐Ÿ“Ž

Bundled Data Files

Include CSV, TXT, JSON, or other data files your students' code needs. Bundled files are extracted alongside student code at grading time.

๐Ÿงช

Solution Files

Upload your solution .py files for solution-comparison tests. Compare student variables, function outputs, or plot properties against your reference implementation.

๐Ÿ“Š

Partial Credit

Award proportional points when sub-checks partially pass. A test with 10 points and 5 sub-checks awards 2 points per passing sub-check.

๐Ÿ’ฌ

Custom Feedback

Configure pass/fail messages and hints for each test. Students see targeted guidance on failure, helping them learn from mistakes without seeing the answer.

Test

60+ Built-In Test Types

From basic variable checks to cyclomatic complexity analysis - test what matters

Variables & Data

10 types
variable_valueCheck a variable equals an expected value with optional float tolerance
variable_typeVerify variable type (int, float, str, list, dict, tuple, etc.)
list_equalsCompare lists with optional order checking and float tolerance
array_equalsNumPy array comparison with element-wise tolerance
array_sizeCheck array dimensions (min, max, or exact size)
array_values_in_rangeVerify all array values fall within numeric bounds
dict_equalsDictionary comparison with float tolerance
compare_solutionCompare student variables against your solution file
check_relationshipVerify mathematical relationships between variables (e.g., y > 2*x)
dataframe_columnsCheck a pandas DataFrame has expected columns

Functions

6 types
function_existsVerify a function is defined in student code
function_calledCheck a function was called during execution
function_not_calledVerify a function was NOT called (detect unauthorized helpers)
test_function_solutionTest student function against your solution with specific inputs
function_signatureCheck function parameters, parameter count, and defaults
return_typeVerify a function returns the expected type

Classes

3 types
class_existsVerify a class is defined
class_has_methodCheck a class has a specific method
class_has_attributeCheck a class has a specific attribute

Control Flow

5 types
for_loop_usedDetect presence of for loops
while_loop_usedDetect presence of while loops
if_statement_usedDetect presence of if statements
loop_iterationsVerify exact loop iteration count via a tracked variable
exception_raisedCheck that code raises a specific exception type

Code Patterns

5 types
code_containsSearch for a phrase in source code (case-sensitive option)
code_not_containsVerify a phrase is absent from source code
operator_usedDetect specific operators (+=, **, //, etc.)
stdout_containsVerify printed output contains expected text
import_usedVerify a specific module was imported

Matplotlib Plots

13 types
plot_createdVerify a matplotlib plot was generated
plot_propertiesCheck title, xlabel, ylabel, legend, and grid at once
plot_has_xlabel / plot_has_ylabel / plot_has_titleIndividual label and title checks
plot_data_lengthVerify number of data points per line (min, max, or exact)
plot_line_styleCheck line style by index (solid, dashed, dotted, dashdot)
plot_has_line_styleCheck if any line uses a given style
plot_line_widthCheck line width with tolerance
plot_marker_sizeCheck marker size with tolerance
compare_plot_solutionCompare against your solution plot (color, style, width, markers)
check_multiple_linesVerify a plot has at least N lines
check_exact_linesVerify a plot has exactly N lines
check_function_any_lineCheck if any line matches a mathematical function

Code Quality

15 types
naming_conventionEnforce snake_case, camelCase, PascalCase, or custom regex
no_single_letter_varsBlock single-character names (with exceptions like i, j, k)
line_lengthMaximum characters per line with optional tolerance
code_spacingWhitespace around operators, after commas/colons, no trailing spaces
has_docstringsRequire docstrings on all functions, public-only, or specific functions
has_module_docstringRequire a file-level docstring
min_comment_densityMinimum percentage of commented lines
max_function_lengthMaximum lines per function (optionally including docstrings)
max_nesting_depthMaximum nesting level for control structures
cyclomatic_complexityMcCabe complexity threshold per function
no_wildcard_importsBlock from x import *
imports_at_topRequire all imports at the top of the file
no_global_variablesDisallow global-scope variable assignments (constants exempted)

Performance

4 types
performanceFunction must complete within a time limit
performance_scriptFull script must complete within a time limit
performance_compare_functionCompare function speed to your solution (averaged over multiple runs)
performance_compare_scriptCompare full script speed to your solution

File Naming

2 types
file_nameCheck submission filename (exact match, prefix, suffix, contains)
file_naming_conventionEnforce filename conventions (snake_case, kebab-case, etc.)
Collect

Collect Results Your Way

Five channels, any combination. Use what fits your workflow.

๐Ÿ“„ PDF Export

Students export a formatted PDF with scores, per-test results, and their code. They upload it to your LMS like any other assignment.

Can be required by instructor

๐Ÿ“ฌ Submission Server

Full results and student code sent to your self-hosted server. Dashboard with analytics, plagiarism detection, code search, and Canvas export.

Can be required by instructor

๐Ÿ“ง Email

Results emailed to you automatically on each submission. Includes student info, scores, per-test results, and the .py file as an attachment.

Silent notification - cannot be required

๐Ÿ“Š Google Sheets

Scores posted to your Google Sheet via an Apps Script webhook. Each submission adds a row with student info, scores, and per-test pass/fail.

Silent notification - cannot be required

๐Ÿ”— Webhook

POST a JSON payload to any URL on each submission. Build custom integrations with your existing infrastructure.

Silent notification - cannot be required

All channels operate independently. If one fails (no internet), submissions are queued locally and retried automatically.

Grade

Batch Grading

Grade a folder of student submissions and export a CSV gradebook

๐Ÿ“ฅ

1. Download

Collect .py files from your LMS

โšก

2. Grade

Load the folder in the instructor app and run batch grading

๐Ÿ“‹

3. Export

Get a CSV with per-test scores, totals, and percentages

Student names are extracted automatically from file comments (# Name: John Smith), filename patterns (Smith_John_hw1.py), or the filename itself. Export as standard CSV or Canvas-compatible format for direct LMS import.

๐Ÿ›ก๏ธ

Import Safety Scanning

Before executing each file, the grader uses Python AST analysis to scan for dangerous imports across 15 blocked modules - including subprocess, socket, shutil, and more. If one is detected, a modal lets you allow or deny execution before proceeding.

Identity

Roster Management

Optional student identity validation with three roster sources

๐Ÿ“‹

Bundled CSV

Embed a roster directly in the .agr file. Best for small classes and offline-only environments. Students select their name from a validated list.

โ˜๏ธ

Google Sheets

Fetch the roster live from a published Google Sheet. Late adds take effect immediately - no .agr redistribution needed.

๐Ÿ–ฅ๏ธ

Server API

Fetch from your submission server's REST endpoint. Manage rosters through the dashboard with CSV upload, manual add, and duplicate detection.

Combine a remote source with a bundled CSV for offline fallback. Three name modes: freeform entry (default), strict username validation, or flexible username-or-name.

Manage

Self-Hosted Submission Server

A full-featured Flask server you run on your own infrastructure

๐Ÿ“Š

Analytics Dashboard

Score distributions, submission trends, assignment difficulty analysis, student progress tracking, and at-risk student identification. Filter by course, section, or semester.

๐Ÿ”

Plagiarism Detection

Pairwise code similarity analysis with four metrics: code similarity, comment similarity, combined score, and comment-to-code ratio. Side-by-side diff view with syntax highlighting.

๐Ÿ”Ž

Code Search

Search across all submitted code for specific patterns or keywords. Detect AI-generated code patterns, verify required constructs, or investigate academic integrity concerns.

๐Ÿ“…

Assignment Deadlines

Set per-assignment cutoff dates with per-student overrides for accommodations. Late submissions flagged with badges. Exports include an option to exclude late work.

๐Ÿ“ค

Canvas Export

Export grades as Canvas-compatible CSV for direct LMS import. One row per student, one column per assignment. Respects view mode and filter settings.

โš™๏ธ

Zero-Config Setup

SQLite database requires no setup. Download the executable, set a password, and run. Optional PostgreSQL for high-concurrency deployments. HTTPS via Caddy reverse proxy.

Learn more about the server
Trust

FERPA-Friendly by Design

Your data stays on your infrastructure. Always.

๐Ÿ–ฅ๏ธ

Local Grading

Student code executes on the student's own machine. No cloud servers process student work.

๐Ÿ”’

Encrypted Distribution

Solutions, expected values, and SMTP credentials are encrypted inside .agr files. Students cannot extract them.

๐Ÿ›๏ธ

Self-Hosted Infrastructure

The submission server runs on your machines. Student data never passes through PyAutoGrader's infrastructure.

๐Ÿ“

No Third-Party Agreements

No data processing agreements, no vendor contracts, no per-student fees. You control the entire pipeline.

Missing a test type?

We actively add new test types based on instructor feedback.

Request a Test Type Download PyAutoGrader