Skip to content

GradeScope Data Types

Input Data Types API

The JSON schemas for Gradescope's metadata.

GradescopeAssignmentMetadata dataclass

The JSON schema for Gradescope's assignment settings.

Parameters:

Name Type Description Default
due_date datetime

The assignment's due date.

required
group_size Optional[int]

The maximum group size on a group assignment.

required
group_submission bool

Whether group submission is allowed.

required
id int

The assignment's ID.

required
course_id int

The course's ID.

required
late_due_date Optional[datetime]

The late due date, or None if late submission disallowed.

required
release_date datetime

The assignment's release date.

required
title str

The assignment's title.

required
total_points float

The total point value of the assignment.

required
Source code in src/gapper/gradescope/datatypes/gradescope_meta.py
@dataclass_json
@dataclass(frozen=True)
class GradescopeAssignmentMetadata:
    """The JSON schema for Gradescope's assignment settings.

    :param due_date: The assignment's due date.
    :param group_size: The maximum group size on a group assignment.
    :param group_submission: Whether group submission is allowed.
    :param id: The assignment's ID.
    :param course_id: The course's ID.
    :param late_due_date: The late due date, or None if late submission disallowed.
    :param release_date: The assignment's release date.
    :param title: The assignment's title.
    :param total_points: The total point value of the assignment.
    """

    due_date: datetime = field(
        metadata=config(
            encoder=datetime.isoformat,
            decoder=datetime.fromisoformat,  # type: ignore
            mm_field=fields.DateTime(format="iso"),
        )
    )
    group_size: Optional[int]
    group_submission: bool
    id: int
    course_id: int
    late_due_date: Optional[datetime] = field(
        metadata=config(
            encoder=lambda s: datetime.isoformat(s) if s else None,
            decoder=lambda s: datetime.fromisoformat(s) if s else None,  # type: ignore
            mm_field=fields.DateTime(format="iso"),
        )
    )
    release_date: datetime = field(
        metadata=config(
            encoder=datetime.isoformat,
            decoder=datetime.fromisoformat,  # type: ignore
            mm_field=fields.DateTime(format="iso"),
        )
    )
    title: str
    total_points: float = field(metadata=config(encoder=str, decoder=float))

GradescopeAssignmentUser dataclass

The JSON schema for a 'user' (submitter) of a Gradescope assignment.

Parameters:

Name Type Description Default
email str

The submitter's email.

required
id int

The submitter's ID.

required
name str

The submitter's name.

required
Source code in src/gapper/gradescope/datatypes/gradescope_meta.py
@dataclass_json
@dataclass(frozen=True)
class GradescopeAssignmentUser:
    """The JSON schema for a 'user' (submitter) of a Gradescope assignment.

    :param email: The submitter's email.
    :param id: The submitter's ID.
    :param name: The submitter's name.
    """

    email: str
    id: int
    name: str

GradescopePreviousSubmission dataclass

The JSON schema for a previous submission record.

Parameters:

Name Type Description Default
submission_time datetime

The time of the previous submission.

required
score float

The previous submission's score.

required
results GradescopeJson

The results.json file from the previous submission.

required
Source code in src/gapper/gradescope/datatypes/gradescope_meta.py
@dataclass_json
@dataclass(frozen=True)
class GradescopePreviousSubmission:
    """The JSON schema for a previous submission record.

    :param submission_time: The time of the previous submission.
    :param score: The previous submission's score.
    :param results: The results.json file from the previous submission.
    """

    submission_time: datetime = field(
        metadata=config(
            encoder=datetime.isoformat,
            decoder=datetime.fromisoformat,  # type: ignore
            mm_field=fields.DateTime(format="iso"),
        )
    )
    score: float
    results: GradescopeJson

GradescopeSubmissionMetadata dataclass

The JSON schema for Gradescope's submission metadata.

See Also https://gradescope-autograders.readthedocs.io/en/latest/submission_metadata/

Parameters:

Name Type Description Default
id int

The submission's ID.

required
created_at datetime

The time the submission was created.

required
assignment GradescopeAssignmentMetadata

The assignment's metadata.

required
submission_method Literal['upload', 'GitHub', 'Bitbucket']

The submission method.

required
users List[GradescopeAssignmentUser]

The submitters' metadata.

required
previous_submissions List[GradescopePreviousSubmission]

The previous submissions' metadata.

required
Source code in src/gapper/gradescope/datatypes/gradescope_meta.py
@dataclass_json
@dataclass(frozen=True)
class GradescopeSubmissionMetadata:
    """The JSON schema for Gradescope's submission metadata.

    See Also https://gradescope-autograders.readthedocs.io/en/latest/submission_metadata/
    :param id: The submission's ID.
    :param created_at: The time the submission was created.
    :param assignment: The assignment's metadata.
    :param submission_method: The submission method.
    :param users: The submitters' metadata.
    :param previous_submissions: The previous submissions' metadata.
    """

    id: int
    created_at: datetime = field(
        metadata=config(
            encoder=datetime.isoformat,
            decoder=datetime.fromisoformat,  # type: ignore
            mm_field=fields.DateTime(format="iso"),
        )
    )
    assignment: GradescopeAssignmentMetadata
    submission_method: Literal["upload", "GitHub", "Bitbucket"]
    users: List[GradescopeAssignmentUser]
    previous_submissions: List[GradescopePreviousSubmission]

    @classmethod
    def from_file(cls, path: Path) -> GradescopeSubmissionMetadata:
        """Load the submission metadata from a file.

        :param path: The path to load the submission metadata from.
        """
        obj = cls.from_json(path.read_text())  # type: ignore
        _gradescope_meta_logger.debug(
            f"Submission metadata loaded from {path.absolute()}"
        )
        return obj

from_file classmethod

from_file(path: Path) -> GradescopeSubmissionMetadata

Load the submission metadata from a file.

Parameters:

Name Type Description Default
path Path

The path to load the submission metadata from.

required
Source code in src/gapper/gradescope/datatypes/gradescope_meta.py
@classmethod
def from_file(cls, path: Path) -> GradescopeSubmissionMetadata:
    """Load the submission metadata from a file.

    :param path: The path to load the submission metadata from.
    """
    obj = cls.from_json(path.read_text())  # type: ignore
    _gradescope_meta_logger.debug(
        f"Submission metadata loaded from {path.absolute()}"
    )
    return obj

Output Data Types API

The Gradescope grading output JSON schema.

GradescopeJson dataclass

The JSON schema for Gradescope.

We currently don't support the leaderboard and extra_data features of the gradescope schema. Those are documented on the autograder documentation, here: https://gradescope-autograders.readthedocs.io/en/latest/specs/.

Parameters:

Name Type Description Default
tests list[GradescopeTestJson]

The tests for the problem. Required if no global score provided.

list()
score Optional[float]

The overall score. Required if any test has no set score.

None
execution_time Optional[int]

The execution time of all the tests, in seconds.

None
output Optional[str]

The top-level, human-readable text output for all the problems.

None
visibility VisibilityType

The default visibility for each test. Overridden by test-specific settings.

'visible'
stdout_visibility Optional[str]

Whether to show stdout for the tests. Same options as for visibility.

None
Source code in src/gapper/gradescope/datatypes/gradescope_output.py
@dataclass_json
@dataclass
class GradescopeJson:
    """The JSON schema for Gradescope.

    We currently don't support the leaderboard and extra_data features of the gradescope
    schema. Those are documented on the autograder documentation, here:
    <https://gradescope-autograders.readthedocs.io/en/latest/specs/>.

    :param tests: The tests for the problem. Required if no global score provided.
    :param score: The overall score. Required if any test has no set score.
    :param execution_time: The execution time of all the tests, in seconds.
    :param output: The top-level, human-readable text output for all the problems.
    :param visibility: The default visibility for each test. Overridden by test-specific settings.
    :param stdout_visibility: Whether to show stdout for the tests. Same options as for visibility.
    """

    score: Optional[float] = None
    tests: list[GradescopeTestJson] = field(default_factory=list)
    execution_time: Optional[int] = None
    output: Optional[str] = None
    visibility: VisibilityType = "visible"
    stdout_visibility: Optional[str] = None

    @classmethod
    def from_test_results(
        cls,
        results: List[TestResult],
        score: float,
        save_path: Path | None = None,
        **kwargs,
    ) -> GradescopeJson:
        """Convert a list of test results to Gradescope JSON.

        :param results: The test results.
        :param score: The score obtained from the submission.
        :param save_path: The path to save the Gradescope JSON to.
        :param kwargs: The keyword arguments to pass to the constructor.
        :return: The Gradescope JSON.
        """
        gs_json = cls(
            score=score,
            tests=[GradescopeTestJson.from_test_result(result) for result in results],
            **kwargs,
        )

        if save_path is not None:
            with open(save_path, "w") as f:
                f.write(gs_json.to_json())  # type: ignore

        return gs_json

    @classmethod
    def from_error(
        cls, error: InternalError | StudentError, save_path: Path | None = None
    ) -> GradescopeJson:
        """Convert an error to Gradescope JSON.

        :param error: The error to convert.
        :param save_path: The path to save the Gradescope JSON to.
        :return: The Gradescope JSON.
        """
        gs_json = cls(
            score=0,
            tests=[],
            output=error.format(),
        )

        if save_path is not None:
            with open(save_path, "w") as f:
                f.write(gs_json.to_json())  # type: ignore

        return gs_json

from_error classmethod

from_error(error: InternalError | StudentError, save_path: Path | None = None) -> GradescopeJson

Convert an error to Gradescope JSON.

Parameters:

Name Type Description Default
error InternalError | StudentError

The error to convert.

required
save_path Path | None

The path to save the Gradescope JSON to.

None

Returns:

Type Description
GradescopeJson

The Gradescope JSON.

Source code in src/gapper/gradescope/datatypes/gradescope_output.py
@classmethod
def from_error(
    cls, error: InternalError | StudentError, save_path: Path | None = None
) -> GradescopeJson:
    """Convert an error to Gradescope JSON.

    :param error: The error to convert.
    :param save_path: The path to save the Gradescope JSON to.
    :return: The Gradescope JSON.
    """
    gs_json = cls(
        score=0,
        tests=[],
        output=error.format(),
    )

    if save_path is not None:
        with open(save_path, "w") as f:
            f.write(gs_json.to_json())  # type: ignore

    return gs_json

from_test_results classmethod

from_test_results(results: List[TestResult], score: float, save_path: Path | None = None, **kwargs) -> GradescopeJson

Convert a list of test results to Gradescope JSON.

Parameters:

Name Type Description Default
results List[TestResult]

The test results.

required
score float

The score obtained from the submission.

required
save_path Path | None

The path to save the Gradescope JSON to.

None
kwargs

The keyword arguments to pass to the constructor.

{}

Returns:

Type Description
GradescopeJson

The Gradescope JSON.

Source code in src/gapper/gradescope/datatypes/gradescope_output.py
@classmethod
def from_test_results(
    cls,
    results: List[TestResult],
    score: float,
    save_path: Path | None = None,
    **kwargs,
) -> GradescopeJson:
    """Convert a list of test results to Gradescope JSON.

    :param results: The test results.
    :param score: The score obtained from the submission.
    :param save_path: The path to save the Gradescope JSON to.
    :param kwargs: The keyword arguments to pass to the constructor.
    :return: The Gradescope JSON.
    """
    gs_json = cls(
        score=score,
        tests=[GradescopeTestJson.from_test_result(result) for result in results],
        **kwargs,
    )

    if save_path is not None:
        with open(save_path, "w") as f:
            f.write(gs_json.to_json())  # type: ignore

    return gs_json

GradescopeTestJson dataclass

The JSON schema for a single Test.

Parameters:

Name Type Description Default
score Optional[float]

The test's score. Required if no top-level score is set.

None
max_score Optional[float]

The max score for the test.

None
name Optional[str]

The test's name.

None
output Optional[str]

Human-readable text output of the test.

None
tags Optional[str]

Tags for the test.

None
visibility VisibilityType

The test's visibility. "hidden", "visible", "after_due_date", "after_published"

'visible'
Source code in src/gapper/gradescope/datatypes/gradescope_output.py
@dataclass_json
@dataclass
class GradescopeTestJson:
    """The JSON schema for a single Test.

    :param score: The test's score. Required if no top-level score is set.
    :param max_score: The max score for the test.
    :param name: The test's name.
    :param output: Human-readable text output of the test.
    :param tags: Tags for the test.
    :param visibility: The test's visibility. "hidden", "visible", "after_due_date", "after_published"
    """

    score: Optional[float] = field(default=None)
    max_score: Optional[float] = field(default=None)
    status: Optional[PassStateType] = field(default=None)
    name: Optional[str] = field(default=None)
    name_format: FormatType = field(default="text")
    number: Optional[float] = field(default=None)
    output: Optional[str] = field(default=None)
    output_format: FormatType = field(default="text")
    tags: Optional[str] = field(default=None)
    visibility: VisibilityType = field(default="visible")

    @classmethod
    def from_test_result(cls, result: TestResult) -> GradescopeTestJson:
        """Convert a test result to Gradescope JSON.

        :param result: The test result to convert.
        :return: The Gradescope Test JSON.
        """
        if result.pass_status is None:
            # even though gradescope says status is optional, setting it to None
            # will cause an error.
            raise InternalError("pass_status of a test result cannot be None.")

        return cls(
            score=result.score,
            max_score=result.max_score,
            status=result.pass_status,
            name=result.rich_test_name,
            output=result.rich_test_output,
            visibility="hidden" if result.hidden else "visible",
        )

from_test_result classmethod

from_test_result(result: TestResult) -> GradescopeTestJson

Convert a test result to Gradescope JSON.

Parameters:

Name Type Description Default
result TestResult

The test result to convert.

required

Returns:

Type Description
GradescopeTestJson

The Gradescope Test JSON.

Source code in src/gapper/gradescope/datatypes/gradescope_output.py
@classmethod
def from_test_result(cls, result: TestResult) -> GradescopeTestJson:
    """Convert a test result to Gradescope JSON.

    :param result: The test result to convert.
    :return: The Gradescope Test JSON.
    """
    if result.pass_status is None:
        # even though gradescope says status is optional, setting it to None
        # will cause an error.
        raise InternalError("pass_status of a test result cannot be None.")

    return cls(
        score=result.score,
        max_score=result.max_score,
        status=result.pass_status,
        name=result.rich_test_name,
        output=result.rich_test_output,
        visibility="hidden" if result.hidden else "visible",
    )