Automated grading CLI for student programming assignments
Project description
ScriptMark
Automated grading CLI for student programming assignments. Rust core, TOML test specifications, no pytest dependency.
Features
- Custom test engine -- runs student code in subprocess, no pytest/unittest required
- TOML-based specs -- declarative test cases with expected values, checkers, and parametrization
- 8 built-in checkers -- exact, approx, sorted, set_eq, contains, regex, text, plus Rhai expressions and external Python checkers
- Parallel execution -- tokio-based orchestrator grades all students concurrently
- Sandboxed execution -- env isolation, import allowlist, resource limits (setrlimit), timeout with process kill
- Parametrize + oracle -- auto-generate test cases with random inputs and teacher reference implementations
- Canvas LMS integration -- pull rosters, push grades
- Similarity detection -- style + structural code similarity scoring
- Interactive TUI -- browse students, sessions, and similarity in the terminal
- HTML reports -- standalone dashboard with per-student breakdowns
- SQLite storage -- persist grading history across sessions
Installation
From source (recommended for now)
git clone https://github.com/Acture/scriptmark.git
cd scriptmark
cargo install --path crates/scriptmark-cli
From crates.io (once published)
cargo install scriptmark-cli
Requires python3 on PATH for running student Python code.
Quick Start
- Write a TOML test spec:
[meta]
name = "find_max"
file = "lab5.py"
function = "find_max"
language = "python"
[[cases]]
name = "basic"
args = [[3, 1, 5, 2]]
expect = 5
[[cases]]
name = "negative"
args = [[-3, -1, -5]]
expect = -1
[[cases]]
name = "random inputs"
[cases.parametrize]
count = 20
seed = 42
[cases.parametrize.args]
nums = "list(int(-100, 100), 5, 20)"
[cases.parametrize.oracle]
rhai = "nums.sort(); nums[nums.len() - 1]"
- Grade submissions:
scriptmark grade submissions/ -t tests/
TOML Spec Format
Each .toml file defines tests for one function/file:
| Section | Purpose |
|---|---|
[meta] |
Target file, function, language, teacher imports |
[vars] |
Constants injected as Python globals |
[[setup]] |
Call functions, store results as $ref for later cases |
[[cases]] |
Scored test cases with expect, check, or expect_error |
[cases.parametrize] |
Auto-generate cases with random args + oracle |
[lint] |
Optional style scoring via pylint/ruff |
Checkers
| Checker | Usage |
|---|---|
exact (default) |
expect = 42 |
approx |
expect = 3.14 with tolerance = 0.01 |
text |
Normalized multiline comparison (strips trailing whitespace + blank lines) |
sorted |
Validates array is sorted |
set_eq |
Unordered array comparison |
contains |
Substring match |
regex |
check = { regex = "^\\d+$" } |
| Rhai expression | check = { rhai = "result > 0 && result < 100" } |
| Python script | check = { python = "verifiers/check.py" } |
CLI Commands
scriptmark grade Run tests + summarize + display grades
scriptmark run Run tests only, output JSON
scriptmark summarize Re-analyze existing results
scriptmark similarity Detect code similarity between submissions
scriptmark report Generate HTML report
scriptmark db Database management (init, import-roster, sessions, history)
scriptmark tui Interactive terminal UI
scriptmark roster-pull Pull roster from Canvas LMS
scriptmark grades-push Push grades to Canvas LMS
Architecture
8-crate Rust workspace:
scriptmark-core Models, TOML parsing, discovery, grading, similarity
scriptmark-runner PythonExecutor, Checker trait, orchestrator, parametrize, oracle
scriptmark-cli clap CLI with 9 commands + HTML report template
scriptmark-db SQLite persistence (rusqlite, bundled)
scriptmark-canvas Canvas LMS API client (reqwest)
scriptmark-tui ratatui terminal UI
scriptmark-py PyO3 Python bindings (in development)
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
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 scriptmark-0.2.0-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: scriptmark-0.2.0-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 2.3 MB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8422b8e8b294fd29728038753e876a6aa2d987c909f9cce3119a93e00e0d8b09
|
|
| MD5 |
4c5b549bd8e4738becf6a7f8783df3b2
|
|
| BLAKE2b-256 |
21afc76bd369fc1428525841284ea5b0079cd959968bcaded7af0c38f11d9873
|
Provenance
The following attestation bundles were made for scriptmark-0.2.0-cp312-cp312-win_amd64.whl:
Publisher:
release.yml on Acture/scriptmark
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scriptmark-0.2.0-cp312-cp312-win_amd64.whl -
Subject digest:
8422b8e8b294fd29728038753e876a6aa2d987c909f9cce3119a93e00e0d8b09 - Sigstore transparency entry: 1225853384
- Sigstore integration time:
-
Permalink:
Acture/scriptmark@525151f1eedcd5e30d47f49f0987b5af5706e431 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Acture
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@525151f1eedcd5e30d47f49f0987b5af5706e431 -
Trigger Event:
push
-
Statement type:
File details
Details for the file scriptmark-0.2.0-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: scriptmark-0.2.0-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 2.3 MB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d7db563aa921fc9ddbad9bfb2c330524ff4f1d9caf8032001593aa3c604ade7
|
|
| MD5 |
ac7b16e999cc2349cc3d5efcd4b708c1
|
|
| BLAKE2b-256 |
9c38a7caa521b92511bbebc024c7b1b4643da9f4f1acbbe5cfb552ddd0d835c8
|
Provenance
The following attestation bundles were made for scriptmark-0.2.0-cp312-cp312-macosx_11_0_arm64.whl:
Publisher:
release.yml on Acture/scriptmark
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scriptmark-0.2.0-cp312-cp312-macosx_11_0_arm64.whl -
Subject digest:
3d7db563aa921fc9ddbad9bfb2c330524ff4f1d9caf8032001593aa3c604ade7 - Sigstore transparency entry: 1225853197
- Sigstore integration time:
-
Permalink:
Acture/scriptmark@525151f1eedcd5e30d47f49f0987b5af5706e431 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Acture
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@525151f1eedcd5e30d47f49f0987b5af5706e431 -
Trigger Event:
push
-
Statement type:
File details
Details for the file scriptmark-0.2.0-cp312-cp312-macosx_10_12_x86_64.whl.
File metadata
- Download URL: scriptmark-0.2.0-cp312-cp312-macosx_10_12_x86_64.whl
- Upload date:
- Size: 2.5 MB
- Tags: CPython 3.12, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64e4e4df0e4c6d6fda7ee816b9493494788ca28a6f7e796658622a7c619cffe1
|
|
| MD5 |
886df3fc3f2fd9e681df2354b9306d10
|
|
| BLAKE2b-256 |
336ab2c542db559644cb96ca0c9ec43cb12156fb7bb891ef8a3f650b99e2afd4
|
Provenance
The following attestation bundles were made for scriptmark-0.2.0-cp312-cp312-macosx_10_12_x86_64.whl:
Publisher:
release.yml on Acture/scriptmark
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scriptmark-0.2.0-cp312-cp312-macosx_10_12_x86_64.whl -
Subject digest:
64e4e4df0e4c6d6fda7ee816b9493494788ca28a6f7e796658622a7c619cffe1 - Sigstore transparency entry: 1225853281
- Sigstore integration time:
-
Permalink:
Acture/scriptmark@525151f1eedcd5e30d47f49f0987b5af5706e431 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Acture
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@525151f1eedcd5e30d47f49f0987b5af5706e431 -
Trigger Event:
push
-
Statement type:
File details
Details for the file scriptmark-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: scriptmark-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 2.7 MB
- Tags: CPython 3.8, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7ef3e08f3226a8da05ff58e2cfaabe6828f24d0dd0f14369b01aa622541a566
|
|
| MD5 |
270f684a253fb9d31a9c017df290fd06
|
|
| BLAKE2b-256 |
b3d9d0a6f4782e9664592a9ba5574d10d8e601ceb59ff4bdf903d32af5367de4
|
Provenance
The following attestation bundles were made for scriptmark-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on Acture/scriptmark
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scriptmark-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
c7ef3e08f3226a8da05ff58e2cfaabe6828f24d0dd0f14369b01aa622541a566 - Sigstore transparency entry: 1225853126
- Sigstore integration time:
-
Permalink:
Acture/scriptmark@525151f1eedcd5e30d47f49f0987b5af5706e431 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Acture
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@525151f1eedcd5e30d47f49f0987b5af5706e431 -
Trigger Event:
push
-
Statement type: