Skip to main content

A general-purpose autograder written primarily in Python 3.

Project description

lograder

This repository contains the source code for a general-purpose autograder. The idea from a high-level view is everything belongs to a pipeline, which can be found in src/lograder/pipeline/pipeline.py. The main type that is of note is Step, found in src/lograder/pipeline/step.py. The steps that make up the pipeline have a __call__ which is a generator. The generator may yield values (both errors and info) which are non-fatal, while return values are either fatal errors or the data to pass onto the next step.

The central mantra to this library is validation, validation, validation (because repetition legitimizes). All calls to processes should be through a TypedExecutable, which contains validated input models via CLIArgs. Additionally, any output needs to be a validated model and needs to be parsed programmatically and completely. Either the program must have an API, or the text parser must be bullet-proof.

Additionally, passing errors as values rather than exception based programming (except for developer bugs, staff errors, or validation errors) is preferred.

Finally, all the output is generated by the steps and will be handled by the loggers, which are responsible for producing logging output (obviously), but also the .json or .html or whatever is used by the underlying application.

With that out of the way, we can get a little more into the details.


Installation

pip install -e ".[dev]"

Run tests with pytest.


"The Pipeline"

The autograder must be able to take student files of any type, such as source files for C, C++, Python, Rust, Assembly, and so forth; build the project in as configurable manner (with a natural default, ONLY IF there is an intuitive default); create any sort of artifact, whether that be text output, file output, etc.; and then "test" the artifacts whatever that may mean.

The primary subpackage for this is located in src/lograder/pipeline.

Step generics

Every concrete Step subclass must declare exactly five type parameters:

class MyStep(Step[InputT, OkOutputT, ErrOutputT, OkDisplayT, ErrDisplayT]): ...

OkOutputT becomes the input for the next step. ErrOutputT and ErrDisplayT are fatal and non-fatal error types respectively, sent to the packet logger. __init_subclass__ enforces this at class definition time.

Result type

Result[T, E] (see src/lograder/common/result.py) is a Rust-inspired error-as-value container. Use Ok(value) and Err(value) constructors. danger_ok / danger_err are assertion-guarded unwrappers. Do not raise exceptions for expected failure modes — return Err(...) instead. DeveloperException and StaffException are reserved for internal bugs and course staff configuration errors respectively.

Manifest

Manifest (see src/lograder/pipeline/types/parcels.py) represents a project's file/directory tree and is the primary type flowing between Input and Check steps. It can be constructed from a directory scan (from_directory), a TOML file (from_toml), or a flat list of paths (from_flat). == checks exact equality; <= checks subset (received contains at least the expected files).

Input

These will be the very beginning of the pipeline, taking "no input" and producing some output (if no error, of course)! For example, the Gradescope autograder puts uploaded files into a fixed directory, so a natural input is to enumerate a local directory into a Manifest. However, there are other examples of inputs, such as a single file upload.

Check

These are mostly validation that happens before build. An example could be to make sure the project matches a specified manifest. Another example is to do a source file parse to ensure that an illegal library or operator is not used or is used under a certain number of times. The input and output type of these should be able to be chained together.

The simple_project.py check module generates named manifest-check classes (CMakeManifestCheck, MakefileManifestCheck, PyProjectManifestCheck) at import time, so they can be used directly.

Mixin

These will be used to inject staff code (such as specified header files) into the students code, or if the student is expected to write some file but not the surrounding build system, then it will inject the necessary files.

Build

These steps actually build the library, such as via cmake or make or pip install and produce artifacts that are testable or usable in the next steps.

Implemented builders: CMakeBuild (configure + build + File API artifact parsing), MakefileBuild (runs make; artifact parsing is not yet implemented).

Test

These are mostly post-build testing. Examples could be running a number of instances of the student's executable, passing different arguments and seeing if the output matches. Another example is checking the bytes of a binary file to see if they match or running valgrind to check for memory leaks.


Ideas / Future Work

  • Implement Mixin.__call__ (currently a stub).
  • Add Makefile artifact parsing in MakefileBuild (returns empty list today).
  • Create Layout for lograder.pipeline.build.makefile.MakefileBuildOutput.
  • Implement Pipeline.validate_step_types() call and validation in Pipeline.__call__.

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

lograder-0.2.0.tar.gz (78.3 kB view details)

Uploaded Source

Built Distribution

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

lograder-0.2.0-py3-none-any.whl (110.1 kB view details)

Uploaded Python 3

File details

Details for the file lograder-0.2.0.tar.gz.

File metadata

  • Download URL: lograder-0.2.0.tar.gz
  • Upload date:
  • Size: 78.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for lograder-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5f838c76bd20482bbeea8ed1ccbd4ecdffe2f0e70bb1f6ded2dfdf53d2fad3c4
MD5 dbd8b317cc56668b9b843bd364f12f05
BLAKE2b-256 ce476f03a9812f2a0e4a8dde2c79d2231d94cb338fe256ea106455d657166538

See more details on using hashes here.

File details

Details for the file lograder-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: lograder-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 110.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for lograder-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 50e6926678b56ebf23d68a95f5a4e0c6b3d392cca11366b8a5dafb0a87b8e725
MD5 6ca353ffbb04c964258795306c34c564
BLAKE2b-256 30243c99c2c336ab3082dff9923a250e3224bd10a9f56d4542fc2e08f3d2e8e3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page