# generated by datamodel-codegen:
#   filename:  schema.yml

from __future__ import annotations

from collections.abc import Mapping, Sequence
from typing import Any, Literal

from typing_extensions import NotRequired, TypedDict


class User(TypedDict):
    pk: int
    username: str
    first_name: str
    last_name: str
    is_superuser: bool


class Course(TypedDict):
    pk: int
    name: str
    semester: Literal['Fall', 'Winter', 'Spring', 'Summer'] | None
    year: int | None
    subtitle: str
    num_late_days: int
    allowed_guest_domain: str
    last_modified: str


class CreateCourse(TypedDict):
    name: str
    semester: NotRequired[Literal['Fall', 'Winter', 'Spring', 'Summer']]
    year: NotRequired[int | None]
    subtitle: NotRequired[str]
    num_late_days: NotRequired[int]
    allowed_guest_domain: NotRequired[str]


class UpdateCourse(TypedDict):
    name: NotRequired[str]
    semester: NotRequired[Literal['Fall', 'Winter', 'Spring', 'Summer']]
    year: NotRequired[int | None]
    subtitle: NotRequired[str]
    num_late_days: NotRequired[int]
    allowed_guest_domain: NotRequired[str]


Semester = Literal['Fall', 'Winter', 'Spring', 'Summer']


class CreateProject(TypedDict):
    name: str
    visible_to_students: NotRequired[bool]
    closing_time: NotRequired[str | None]
    soft_closing_time: NotRequired[str | None]
    disallow_student_submissions: NotRequired[bool]
    disallow_group_registration: NotRequired[bool]
    guests_can_submit: NotRequired[bool]
    min_group_size: NotRequired[int]
    max_group_size: NotRequired[int]
    submission_limit_per_day: NotRequired[int | None]
    allow_submissions_past_limit: NotRequired[bool]
    groups_combine_daily_submissions: NotRequired[bool]
    submission_limit_reset_time: NotRequired[str]
    submission_limit_reset_timezone: NotRequired[str]
    num_bonus_submissions: NotRequired[int]
    total_submission_limit: NotRequired[int | None]
    allow_late_days: NotRequired[bool]
    ultimate_submission_policy: NotRequired[Literal['most_recent', 'best_basic_score', 'best']]
    hide_ultimate_submission_fdbk: NotRequired[bool]
    send_email_on_submission_received: NotRequired[bool]
    send_email_on_non_deferred_tests_finished: NotRequired[bool]
    use_honor_pledge: NotRequired[bool]
    honor_pledge_text: NotRequired[str]


class UpdateProject(TypedDict):
    name: NotRequired[str]
    visible_to_students: NotRequired[bool]
    closing_time: NotRequired[str | None]
    soft_closing_time: NotRequired[str | None]
    disallow_student_submissions: NotRequired[bool]
    disallow_group_registration: NotRequired[bool]
    guests_can_submit: NotRequired[bool]
    min_group_size: NotRequired[int]
    max_group_size: NotRequired[int]
    submission_limit_per_day: NotRequired[int | None]
    allow_submissions_past_limit: NotRequired[bool]
    groups_combine_daily_submissions: NotRequired[bool]
    submission_limit_reset_time: NotRequired[str]
    submission_limit_reset_timezone: NotRequired[str]
    num_bonus_submissions: NotRequired[int]
    total_submission_limit: NotRequired[int | None]
    allow_late_days: NotRequired[bool]
    ultimate_submission_policy: NotRequired[Literal['most_recent', 'best_basic_score', 'best']]
    hide_ultimate_submission_fdbk: NotRequired[bool]
    send_email_on_submission_received: NotRequired[bool]
    send_email_on_non_deferred_tests_finished: NotRequired[bool]
    use_honor_pledge: NotRequired[bool]
    honor_pledge_text: NotRequired[str]


UltimateSubmissionPolicy = Literal['most_recent', 'best_basic_score', 'best']


class ExpectedStudentFile(TypedDict):
    pk: int
    project: int
    pattern: str
    min_num_matches: int
    max_num_matches: int
    last_modified: str


class CreateExpectedStudentFile(TypedDict):
    pattern: str
    min_num_matches: NotRequired[int]
    max_num_matches: NotRequired[int]


class UpdateExpectedStudentFile(TypedDict):
    pattern: NotRequired[str]
    min_num_matches: NotRequired[int]
    max_num_matches: NotRequired[int]


class InstructorFile(TypedDict):
    pk: int
    project: int
    name: str
    last_modified: str
    size: int


class CreateInstructorFile(TypedDict):
    file_obj: NotRequired[bytes]


class UpdateInstructorFile(TypedDict):
    file_obj: NotRequired[bytes]


class DownloadTask(TypedDict):
    pk: int
    project: int
    download_type: Literal[
        'all_scores',
        'final_graded_submission_scores',
        'all_submission_files',
        'final_graded_submission_files',
    ]
    result_filename: str
    progress: int
    include_pending_extensions: bool
    error_msg: str
    created_at: str


DownloadType = Literal[
    'all_scores',
    'final_graded_submission_scores',
    'all_submission_files',
    'final_graded_submission_files',
]


class Group(TypedDict):
    pk: int
    project: int
    extended_due_date: str | None
    member_names: Sequence[str]
    members: Sequence[User]
    bonus_submissions_remaining: int
    late_days_used: Mapping[str, Any]
    num_submissions: int
    num_submits_towards_limit: int
    created_at: str
    last_modified: str


class CreateGroup(TypedDict):
    member_names: Sequence[str]


class UpdateGroup(TypedDict):
    member_names: NotRequired[Sequence[str]]
    extended_due_date: NotRequired[str | None]
    bonus_submissions_remaining: NotRequired[int]


class GroupInvitation(TypedDict):
    pk: int
    project: int
    sender: User
    recipients: Sequence[User]
    sender_username: str
    recipient_usernames: Sequence[str]
    recipients_who_accepted: Sequence[str]


class CreateGroupInvitation(TypedDict):
    recipients: Sequence[str]


class Submission(TypedDict):
    pk: int
    group: int
    timestamp: str
    submitter: str
    submitted_filenames: Sequence[str]
    discarded_files: Sequence[str]
    missing_files: Mapping[str, Any]
    status: Literal[
        'received',
        'queued',
        'being_graded',
        'waiting_for_deferred',
        'finished_grading',
        'removed_from_queue',
        'rejected',
        'error',
    ]
    is_past_daily_limit: bool
    is_bonus_submission: bool
    count_towards_total_limit: bool
    does_not_count_for: Sequence[str]
    position_in_queue: int
    grading_start_time: str | None
    non_deferred_grading_end_time: str | None
    last_modified: str


class CreateSubmission(TypedDict):
    submitted_files: Sequence[bytes]


class UpdateSubmission(TypedDict):
    count_towards_total_limit: NotRequired[bool]


class Command(TypedDict):
    cmd: str
    name: str
    time_limit: int
    stack_size_limit: int
    use_virtual_memory_limit: bool
    virtual_memory_limit: int
    block_process_spawn: bool
    process_spawn_limit: int


class SandboxDockerImage(TypedDict):
    pk: int
    display_name: str
    course: int | None
    last_modified: str


class UpdateSandboxDockerImage(TypedDict):
    display_name: NotRequired[str]


class BuildSandboxDockerImageTask(TypedDict):
    pk: int
    created_at: str
    status: Literal[
        'queued', 'in_progress', 'done', 'failed', 'image_invalid', 'cancelled', 'internal_error'
    ]
    return_code: int | None
    timed_out: bool
    filenames: Sequence[str]
    course_id: int | None
    image: SandboxDockerImage | None
    validation_error_msg: str
    internal_error_msg: str
    last_modified: str


class BuildSandboxDockerImage(TypedDict):
    files: NotRequired[Sequence[bytes]]


BuildImageStatus = Literal[
    'queued', 'in_progress', 'done', 'failed', 'image_invalid', 'cancelled', 'internal_error'
]


class AGTestSuiteFeedbackConfig(TypedDict):
    visible: bool
    show_individual_tests: bool
    show_setup_return_code: bool
    show_setup_timed_out: bool
    show_setup_stdout: bool
    show_setup_stderr: bool
    show_student_description: bool


class AGTestCaseFeedbackConfig(TypedDict):
    visible: bool
    show_individual_commands: bool
    show_student_description: bool


StdinSource = Literal['none', 'text', 'instructor_file', 'setup_stdout', 'setup_stderr']


ExpectedOutputSource = Literal['none', 'text', 'instructor_file']


ExpectedReturnCode = Literal['none', 'zero', 'nonzero']


ValueFeedbackLevel = Literal['no_feedback', 'correct_or_incorrect', 'expected_and_actual']


class AGTestCommandResultFeedback(TypedDict):
    pk: int
    ag_test_command_pk: int
    ag_test_command_name: str
    fdbk_settings: Mapping[str, Any]
    student_description: str | None
    student_on_fail_description: str | None
    timed_out: bool | None
    return_code_correct: bool | None
    expected_return_code: ExpectedReturnCode | None
    actual_return_code: int | None
    return_code_points: int
    return_code_points_possible: int
    stdout_correct: bool | None
    stdout_points: int
    stdout_points_possible: int
    stderr_correct: bool | None
    stderr_points: int
    stderr_points_possible: int
    total_points: int
    total_points_possible: int


FeedbackCategory = Literal[
    'normal', 'ultimate_submission', 'past_limit_submission', 'staff_viewer', 'max'
]


BugsExposedFeedbackLevel = Literal[
    'no_feedback', 'num_bugs_exposed', 'exposed_bug_names', 'all_bug_names'
]


class MutationTestSuiteResultFeedback(TypedDict):
    pk: int
    mutation_test_suite_name: str
    mutation_test_suite_pk: int
    fdbk_settings: Mapping[str, Any]
    has_setup_command: bool
    setup_command_name: str | None
    setup_return_code: int | None
    setup_timed_out: bool | None
    get_student_test_names_return_code: int | None
    get_student_test_names_timed_out: bool | None
    student_tests: Sequence[str]
    discarded_tests: Sequence[str]
    invalid_tests: Sequence[str] | None
    timed_out_tests: Sequence[str] | None
    num_bugs_exposed: int | None
    bugs_exposed: Sequence[str] | None
    all_bug_names: Sequence[str] | None
    total_points: str
    total_points_possible: str


class RerunSubmissionsTask(TypedDict):
    pk: int
    progress: int
    is_cancelled: bool
    error_msg: str
    creator: int | None
    created_at: str
    has_error: bool
    project: int
    rerun_all_submissions: bool
    submission_pks: Sequence[int]
    rerun_all_ag_test_suites: bool
    ag_test_suite_data: Mapping[str, Any]
    rerun_all_mutation_test_suites: bool
    mutation_suite_pks: Sequence[int]


class CreateRerunSubmissionsTask(TypedDict):
    rerun_all_submissions: NotRequired[bool]
    submission_pks: NotRequired[Sequence[int]]
    rerun_all_ag_test_suites: NotRequired[bool]
    ag_test_suite_data: NotRequired[Mapping[str, Any]]
    rerun_all_mutation_test_suites: NotRequired[bool]
    mutation_suite_pks: NotRequired[Sequence[int]]


class CreateHandgradingRubric(TypedDict):
    points_style: NotRequired[Literal['start_at_zero_and_add', 'start_at_max_and_subtract']]
    max_points: NotRequired[float | None]
    show_grades_and_rubric_to_students: NotRequired[bool]
    show_only_applied_rubric_to_students: NotRequired[bool]
    handgraders_can_leave_comments: NotRequired[bool]
    handgraders_can_adjust_points: NotRequired[bool]


class UpdateHandgradingRubric(TypedDict):
    points_style: NotRequired[Literal['start_at_zero_and_add', 'start_at_max_and_subtract']]
    max_points: NotRequired[float | None]
    show_grades_and_rubric_to_students: NotRequired[bool]
    show_only_applied_rubric_to_students: NotRequired[bool]
    handgraders_can_leave_comments: NotRequired[bool]
    handgraders_can_adjust_points: NotRequired[bool]


PointsStyle = Literal['start_at_zero_and_add', 'start_at_max_and_subtract']


class Criterion(TypedDict):
    pk: int
    handgrading_rubric: int
    last_modified: str
    short_description: str
    long_description: str
    points: float


class CreateCriterion(TypedDict):
    short_description: NotRequired[str]
    long_description: NotRequired[str]
    points: NotRequired[float]


class UpdateCriterion(TypedDict):
    short_description: NotRequired[str]
    long_description: NotRequired[str]
    points: NotRequired[float]


class Annotation(TypedDict):
    pk: int
    handgrading_rubric: int
    short_description: str
    long_description: str
    deduction: float
    max_deduction: float | None
    last_modified: str


class CreateAnnotation(TypedDict):
    short_description: NotRequired[str]
    long_description: NotRequired[str]
    deduction: NotRequired[float]
    max_deduction: NotRequired[float | None]


class UpdateAnnotation(TypedDict):
    short_description: NotRequired[str]
    long_description: NotRequired[str]
    deduction: NotRequired[float]
    max_deduction: NotRequired[float | None]


class CreateHandgradingResult(TypedDict):
    points_adjustment: NotRequired[float]
    finished_grading: NotRequired[bool]


class UpdateHandgradingResult(TypedDict):
    points_adjustment: NotRequired[float]
    finished_grading: NotRequired[bool]


class CriterionResult(TypedDict):
    pk: int
    last_modified: str
    selected: bool
    criterion: Criterion
    handgrading_result: int


class CreateCriterionResult(TypedDict):
    selected: bool


class UpdateCriterionResult(TypedDict):
    selected: NotRequired[bool]


class UpdateComment(TypedDict):
    text: NotRequired[str]


class Location(TypedDict):
    filename: str
    first_line: int
    last_line: int


class MutationTestSuiteHintConfig(TypedDict):
    pk: int
    mutation_test_suite: int
    hints_by_mutant_name: Mapping[str, Any]
    num_hints_per_day: int | None
    hint_limit_reset_time: str
    hint_limit_reset_timezone: str
    num_hints_per_submission: int | None
    obfuscate_mutant_names: Literal['none', 'sequential', 'hash']
    obfuscated_mutant_name_prefix: str
    created_at: str
    last_modified: str


class CreateMutationTestSuiteHintConfig(TypedDict):
    hints_by_mutant_name: NotRequired[Mapping[str, Any]]
    num_hints_per_day: NotRequired[int | None]
    hint_limit_reset_time: NotRequired[str]
    hint_limit_reset_timezone: NotRequired[str]
    num_hints_per_submission: NotRequired[int | None]
    obfuscate_mutant_names: NotRequired[Literal['none', 'sequential', 'hash']]
    obfuscated_mutant_name_prefix: NotRequired[str]


class UpdateMutationTestSuiteHintConfig(TypedDict):
    hints_by_mutant_name: NotRequired[Mapping[str, Any]]
    num_hints_per_day: NotRequired[int | None]
    hint_limit_reset_time: NotRequired[str]
    hint_limit_reset_timezone: NotRequired[str]
    num_hints_per_submission: NotRequired[int | None]
    obfuscate_mutant_names: NotRequired[Literal['none', 'sequential', 'hash']]
    obfuscated_mutant_name_prefix: NotRequired[str]


MutantNameObfuscationChoices = Literal['none', 'sequential', 'hash']


class UnlockedHint(TypedDict):
    pk: int
    created_at: str
    mutation_test_suite_result: int
    mutation_test_suite_hint_config: int
    mutant_name: str
    hint_number: int
    hint_text: str
    hint_rating: int | None
    user_comment: str


class UserRoles(TypedDict):
    is_admin: bool
    is_staff: bool
    is_student: bool
    is_handgrader: bool


class Project(TypedDict):
    pk: int
    name: str
    last_modified: str
    course: int
    visible_to_students: bool
    closing_time: NotRequired[str | None]
    soft_closing_time: str | None
    disallow_student_submissions: bool
    disallow_group_registration: bool
    guests_can_submit: bool
    min_group_size: int
    max_group_size: int
    submission_limit_per_day: int | None
    allow_submissions_past_limit: bool
    groups_combine_daily_submissions: bool
    submission_limit_reset_time: str
    submission_limit_reset_timezone: str
    num_bonus_submissions: int
    total_submission_limit: int | None
    allow_late_days: bool
    ultimate_submission_policy: Literal['most_recent', 'best_basic_score', 'best']
    hide_ultimate_submission_fdbk: bool
    instructor_files: Sequence[InstructorFile]
    expected_student_files: Sequence[ExpectedStudentFile]
    has_handgrading_rubric: bool
    send_email_on_submission_received: bool
    send_email_on_non_deferred_tests_finished: bool
    use_honor_pledge: bool
    honor_pledge_text: str


class CreateAGTestSuite(TypedDict):
    name: str
    internal_admin_notes: NotRequired[str]
    staff_description: NotRequired[str]
    student_description: NotRequired[str]
    instructor_files_needed: NotRequired[Sequence[InstructorFile]]
    read_only_instructor_files: NotRequired[bool]
    student_files_needed: NotRequired[Sequence[ExpectedStudentFile]]
    setup_suite_cmd: NotRequired[str]
    setup_suite_cmd_name: NotRequired[str]
    reject_submission_if_setup_fails: NotRequired[bool]
    allow_network_access: NotRequired[bool]
    deferred: NotRequired[bool]
    sandbox_docker_image: NotRequired[SandboxDockerImage]
    normal_fdbk_config: NotRequired[AGTestSuiteFeedbackConfig]
    ultimate_submission_fdbk_config: NotRequired[AGTestSuiteFeedbackConfig]
    past_limit_submission_fdbk_config: NotRequired[AGTestSuiteFeedbackConfig]
    staff_viewer_fdbk_config: NotRequired[AGTestSuiteFeedbackConfig]


class UpdateAGTestSuite(TypedDict):
    name: NotRequired[str]
    internal_admin_notes: NotRequired[str]
    staff_description: NotRequired[str]
    student_description: NotRequired[str]
    instructor_files_needed: NotRequired[Sequence[InstructorFile]]
    read_only_instructor_files: NotRequired[bool]
    student_files_needed: NotRequired[Sequence[ExpectedStudentFile]]
    setup_suite_cmd: NotRequired[str]
    setup_suite_cmd_name: NotRequired[str]
    reject_submission_if_setup_fails: NotRequired[bool]
    allow_network_access: NotRequired[bool]
    deferred: NotRequired[bool]
    sandbox_docker_image: NotRequired[SandboxDockerImage]
    normal_fdbk_config: NotRequired[AGTestSuiteFeedbackConfig]
    ultimate_submission_fdbk_config: NotRequired[AGTestSuiteFeedbackConfig]
    past_limit_submission_fdbk_config: NotRequired[AGTestSuiteFeedbackConfig]
    staff_viewer_fdbk_config: NotRequired[AGTestSuiteFeedbackConfig]


class CreateAGTestCase(TypedDict):
    name: str
    ag_test_suite: NotRequired[int]
    internal_admin_notes: NotRequired[str]
    staff_description: NotRequired[str]
    student_description: NotRequired[str]
    normal_fdbk_config: NotRequired[AGTestCaseFeedbackConfig]
    ultimate_submission_fdbk_config: NotRequired[AGTestCaseFeedbackConfig]
    past_limit_submission_fdbk_config: NotRequired[AGTestCaseFeedbackConfig]
    staff_viewer_fdbk_config: NotRequired[AGTestCaseFeedbackConfig]


class UpdateAGTestCase(TypedDict):
    name: NotRequired[str]
    ag_test_suite: NotRequired[int]
    internal_admin_notes: NotRequired[str]
    staff_description: NotRequired[str]
    student_description: NotRequired[str]
    normal_fdbk_config: NotRequired[AGTestCaseFeedbackConfig]
    ultimate_submission_fdbk_config: NotRequired[AGTestCaseFeedbackConfig]
    past_limit_submission_fdbk_config: NotRequired[AGTestCaseFeedbackConfig]
    staff_viewer_fdbk_config: NotRequired[AGTestCaseFeedbackConfig]


class AGTestCommandFeedbackConfig(TypedDict):
    visible: bool
    return_code_fdbk_level: ValueFeedbackLevel
    stdout_fdbk_level: ValueFeedbackLevel
    stderr_fdbk_level: ValueFeedbackLevel
    show_points: bool
    show_actual_return_code: bool
    show_actual_stdout: bool
    show_actual_stderr: bool
    show_whether_timed_out: bool
    show_student_description: bool


class AGTestCaseResultFeedback(TypedDict):
    pk: int
    ag_test_case_name: str
    ag_test_case_pk: int
    fdbk_settings: Mapping[str, Any]
    student_description: str | None
    total_points: int
    total_points_possible: int
    ag_test_command_results: Sequence[AGTestCommandResultFeedback]


class MutationTestSuiteFeedbackConfig(TypedDict):
    visible: bool
    show_setup_return_code: bool
    show_setup_stdout: bool
    show_setup_stderr: bool
    show_get_test_names_return_code: bool
    show_get_test_names_stdout: bool
    show_get_test_names_stderr: bool
    show_validity_check_stdout: bool
    show_validity_check_stderr: bool
    show_grade_buggy_impls_stdout: bool
    show_grade_buggy_impls_stderr: bool
    show_invalid_test_names: bool
    show_points: bool
    bugs_exposed_fdbk_level: BugsExposedFeedbackLevel


class HandgradingRubric(TypedDict):
    pk: int
    project: int
    last_modified: str
    points_style: Literal['start_at_zero_and_add', 'start_at_max_and_subtract']
    max_points: float | None
    show_grades_and_rubric_to_students: bool
    show_only_applied_rubric_to_students: bool
    handgraders_can_leave_comments: bool
    handgraders_can_adjust_points: bool
    criteria: Sequence[Criterion]
    annotations: Sequence[Annotation]


class AppliedAnnotation(TypedDict):
    pk: int
    last_modified: str
    location: Location
    annotation: Annotation
    handgrading_result: int


class CreateAppliedAnnotation(TypedDict):
    annotation: Annotation
    location: Location


class Comment(TypedDict):
    pk: int
    last_modified: str
    location: Location | None
    text: str
    handgrading_result: int


class CreateComment(TypedDict):
    text: str
    location: NotRequired[Location]


class AGTestCommand(TypedDict):
    pk: int
    name: str
    ag_test_case: int
    last_modified: str
    cmd: str
    internal_admin_notes: str
    staff_description: str
    student_description: str
    student_on_fail_description: str
    stdin_source: Literal['none', 'text', 'instructor_file', 'setup_stdout', 'setup_stderr']
    stdin_text: str
    stdin_instructor_file: InstructorFile | None
    expected_return_code: Literal['none', 'zero', 'nonzero']
    expected_stdout_source: Literal['none', 'text', 'instructor_file']
    expected_stdout_text: str
    expected_stdout_instructor_file: InstructorFile | None
    expected_stderr_source: Literal['none', 'text', 'instructor_file']
    expected_stderr_text: str
    expected_stderr_instructor_file: InstructorFile | None
    ignore_case: bool
    ignore_whitespace: bool
    ignore_whitespace_changes: bool
    ignore_blank_lines: bool
    points_for_correct_return_code: int
    points_for_correct_stdout: int
    points_for_correct_stderr: int
    deduction_for_wrong_return_code: int
    deduction_for_wrong_stdout: int
    deduction_for_wrong_stderr: int
    normal_fdbk_config: AGTestCommandFeedbackConfig
    first_failed_test_normal_fdbk_config: AGTestCommandFeedbackConfig | None
    ultimate_submission_fdbk_config: AGTestCommandFeedbackConfig
    past_limit_submission_fdbk_config: AGTestCommandFeedbackConfig
    staff_viewer_fdbk_config: AGTestCommandFeedbackConfig
    time_limit: int
    use_virtual_memory_limit: bool
    virtual_memory_limit: int
    block_process_spawn: bool


class CreateAGTestCommand(TypedDict):
    name: str
    cmd: str
    internal_admin_notes: NotRequired[str]
    staff_description: NotRequired[str]
    student_description: NotRequired[str]
    student_on_fail_description: NotRequired[str]
    stdin_source: NotRequired[
        Literal['none', 'text', 'instructor_file', 'setup_stdout', 'setup_stderr']
    ]
    stdin_text: NotRequired[str]
    stdin_instructor_file: NotRequired[InstructorFile]
    expected_return_code: NotRequired[Literal['none', 'zero', 'nonzero']]
    expected_stdout_source: NotRequired[Literal['none', 'text', 'instructor_file']]
    expected_stdout_text: NotRequired[str]
    expected_stdout_instructor_file: NotRequired[InstructorFile]
    expected_stderr_source: NotRequired[Literal['none', 'text', 'instructor_file']]
    expected_stderr_text: NotRequired[str]
    expected_stderr_instructor_file: NotRequired[InstructorFile]
    ignore_case: NotRequired[bool]
    ignore_whitespace: NotRequired[bool]
    ignore_whitespace_changes: NotRequired[bool]
    ignore_blank_lines: NotRequired[bool]
    points_for_correct_return_code: NotRequired[int]
    points_for_correct_stdout: NotRequired[int]
    points_for_correct_stderr: NotRequired[int]
    deduction_for_wrong_return_code: NotRequired[int]
    deduction_for_wrong_stdout: NotRequired[int]
    deduction_for_wrong_stderr: NotRequired[int]
    normal_fdbk_config: NotRequired[AGTestCommandFeedbackConfig]
    first_failed_test_normal_fdbk_config: NotRequired[AGTestCommandFeedbackConfig]
    ultimate_submission_fdbk_config: NotRequired[AGTestCommandFeedbackConfig]
    past_limit_submission_fdbk_config: NotRequired[AGTestCommandFeedbackConfig]
    staff_viewer_fdbk_config: NotRequired[AGTestCommandFeedbackConfig]
    time_limit: NotRequired[int]
    use_virtual_memory_limit: NotRequired[bool]
    virtual_memory_limit: NotRequired[int]
    block_process_spawn: NotRequired[bool]


class UpdateAGTestCommand(TypedDict):
    name: NotRequired[str]
    cmd: NotRequired[str]
    internal_admin_notes: NotRequired[str]
    staff_description: NotRequired[str]
    student_description: NotRequired[str]
    student_on_fail_description: NotRequired[str]
    stdin_source: NotRequired[
        Literal['none', 'text', 'instructor_file', 'setup_stdout', 'setup_stderr']
    ]
    stdin_text: NotRequired[str]
    stdin_instructor_file: NotRequired[InstructorFile]
    expected_return_code: NotRequired[Literal['none', 'zero', 'nonzero']]
    expected_stdout_source: NotRequired[Literal['none', 'text', 'instructor_file']]
    expected_stdout_text: NotRequired[str]
    expected_stdout_instructor_file: NotRequired[InstructorFile]
    expected_stderr_source: NotRequired[Literal['none', 'text', 'instructor_file']]
    expected_stderr_text: NotRequired[str]
    expected_stderr_instructor_file: NotRequired[InstructorFile]
    ignore_case: NotRequired[bool]
    ignore_whitespace: NotRequired[bool]
    ignore_whitespace_changes: NotRequired[bool]
    ignore_blank_lines: NotRequired[bool]
    points_for_correct_return_code: NotRequired[int]
    points_for_correct_stdout: NotRequired[int]
    points_for_correct_stderr: NotRequired[int]
    deduction_for_wrong_return_code: NotRequired[int]
    deduction_for_wrong_stdout: NotRequired[int]
    deduction_for_wrong_stderr: NotRequired[int]
    normal_fdbk_config: NotRequired[AGTestCommandFeedbackConfig]
    first_failed_test_normal_fdbk_config: NotRequired[AGTestCommandFeedbackConfig]
    ultimate_submission_fdbk_config: NotRequired[AGTestCommandFeedbackConfig]
    past_limit_submission_fdbk_config: NotRequired[AGTestCommandFeedbackConfig]
    staff_viewer_fdbk_config: NotRequired[AGTestCommandFeedbackConfig]
    time_limit: NotRequired[int]
    use_virtual_memory_limit: NotRequired[bool]
    virtual_memory_limit: NotRequired[int]
    block_process_spawn: NotRequired[bool]


class AGTestSuiteResultFeedback(TypedDict):
    pk: int
    ag_test_suite_name: str
    ag_test_suite_pk: int
    fdbk_settings: Mapping[str, Any]
    student_description: str | None
    total_points: int
    total_points_possible: int
    setup_name: str | None
    setup_return_code: int | None
    setup_timed_out: bool | None
    ag_test_case_results: Sequence[AGTestCaseResultFeedback]


class MutationTestSuite(TypedDict):
    pk: int
    name: str
    project: int
    instructor_files_needed: Sequence[InstructorFile]
    read_only_instructor_files: bool
    student_files_needed: Sequence[ExpectedStudentFile]
    buggy_impl_names: Sequence[str]
    use_setup_command: bool
    setup_command: Command
    get_student_test_names_command: Command
    test_name_discovery_whitespace_handling: Literal['newline', 'any_whitespace']
    max_num_student_tests: int
    student_test_validity_check_command: Command
    grade_buggy_impl_command: Command
    points_per_exposed_bug: str
    max_points: int | None
    deferred: bool
    sandbox_docker_image: SandboxDockerImage
    allow_network_access: bool
    normal_fdbk_config: MutationTestSuiteFeedbackConfig
    ultimate_submission_fdbk_config: MutationTestSuiteFeedbackConfig
    past_limit_submission_fdbk_config: MutationTestSuiteFeedbackConfig
    staff_viewer_fdbk_config: MutationTestSuiteFeedbackConfig
    last_modified: str


class CreateMutationTestSuite(TypedDict):
    name: str
    instructor_files_needed: NotRequired[Sequence[InstructorFile]]
    read_only_instructor_files: NotRequired[bool]
    student_files_needed: NotRequired[Sequence[ExpectedStudentFile]]
    buggy_impl_names: NotRequired[Sequence[str]]
    use_setup_command: NotRequired[bool]
    setup_command: NotRequired[Command]
    get_student_test_names_command: NotRequired[Command]
    test_name_discovery_whitespace_handling: NotRequired[Literal['newline', 'any_whitespace']]
    max_num_student_tests: NotRequired[int]
    student_test_validity_check_command: NotRequired[Command]
    grade_buggy_impl_command: NotRequired[Command]
    points_per_exposed_bug: NotRequired[str]
    max_points: NotRequired[int | None]
    deferred: NotRequired[bool]
    sandbox_docker_image: NotRequired[SandboxDockerImage]
    allow_network_access: NotRequired[bool]
    normal_fdbk_config: NotRequired[MutationTestSuiteFeedbackConfig]
    ultimate_submission_fdbk_config: NotRequired[MutationTestSuiteFeedbackConfig]
    past_limit_submission_fdbk_config: NotRequired[MutationTestSuiteFeedbackConfig]
    staff_viewer_fdbk_config: NotRequired[MutationTestSuiteFeedbackConfig]


class UpdateMutationTestSuite(TypedDict):
    name: NotRequired[str]
    instructor_files_needed: NotRequired[Sequence[InstructorFile]]
    read_only_instructor_files: NotRequired[bool]
    student_files_needed: NotRequired[Sequence[ExpectedStudentFile]]
    buggy_impl_names: NotRequired[Sequence[str]]
    use_setup_command: NotRequired[bool]
    setup_command: NotRequired[Command]
    get_student_test_names_command: NotRequired[Command]
    test_name_discovery_whitespace_handling: NotRequired[Literal['newline', 'any_whitespace']]
    max_num_student_tests: NotRequired[int]
    student_test_validity_check_command: NotRequired[Command]
    grade_buggy_impl_command: NotRequired[Command]
    points_per_exposed_bug: NotRequired[str]
    max_points: NotRequired[int | None]
    deferred: NotRequired[bool]
    sandbox_docker_image: NotRequired[SandboxDockerImage]
    allow_network_access: NotRequired[bool]
    normal_fdbk_config: NotRequired[MutationTestSuiteFeedbackConfig]
    ultimate_submission_fdbk_config: NotRequired[MutationTestSuiteFeedbackConfig]
    past_limit_submission_fdbk_config: NotRequired[MutationTestSuiteFeedbackConfig]
    staff_viewer_fdbk_config: NotRequired[MutationTestSuiteFeedbackConfig]


class HandgradingResult(TypedDict):
    pk: int
    last_modified: str
    submission: int
    handgrading_rubric: HandgradingRubric
    group: int
    applied_annotations: Sequence[AppliedAnnotation]
    comments: Sequence[Comment]
    criterion_results: Sequence[CriterionResult]
    finished_grading: bool
    points_adjustment: float
    submitted_filenames: Sequence[str]
    total_points: float
    total_points_possible: float


class AGTestCase(TypedDict):
    pk: int
    name: str
    last_modified: str
    internal_admin_notes: str
    staff_description: str
    student_description: str
    ag_test_suite: int
    ag_test_commands: Sequence[AGTestCommand]
    normal_fdbk_config: AGTestCaseFeedbackConfig
    ultimate_submission_fdbk_config: AGTestCaseFeedbackConfig
    past_limit_submission_fdbk_config: AGTestCaseFeedbackConfig
    staff_viewer_fdbk_config: AGTestCaseFeedbackConfig


class SubmissionResultFeedback(TypedDict):
    pk: int
    total_points: int | str
    total_points_possible: int | str
    ag_test_suite_results: NotRequired[Sequence[AGTestSuiteResultFeedback]]
    mutation_test_suite_results: NotRequired[Sequence[MutationTestSuiteResultFeedback]]


class SubmissionWithResults(Submission):
    results: SubmissionResultFeedback


class AGTestSuite(TypedDict):
    pk: int
    name: str
    project: int
    last_modified: str
    internal_admin_notes: str
    staff_description: str
    student_description: str
    instructor_files_needed: Sequence[InstructorFile]
    read_only_instructor_files: bool
    student_files_needed: Sequence[ExpectedStudentFile]
    ag_test_cases: Sequence[AGTestCase]
    setup_suite_cmd: str
    setup_suite_cmd_name: str
    reject_submission_if_setup_fails: bool
    sandbox_docker_image: SandboxDockerImage
    allow_network_access: bool
    deferred: bool
    normal_fdbk_config: AGTestSuiteFeedbackConfig
    ultimate_submission_fdbk_config: AGTestSuiteFeedbackConfig
    past_limit_submission_fdbk_config: AGTestSuiteFeedbackConfig
    staff_viewer_fdbk_config: AGTestSuiteFeedbackConfig
