Source code for codegrade._api.assignment

"""The endpoints for assignment objects.

SPDX-License-Identifier: AGPL-3.0-only OR BSD-3-Clause-Clear
"""

import os
import typing as t

import cg_request_args as rqa
from cg_maybe import Maybe, Nothing
from cg_maybe.utils import maybe_from_nullable

from .. import parsers, utils
from ..models.ignore_handling import IgnoreHandling

if t.TYPE_CHECKING or os.getenv("CG_EAGERIMPORT", False):
    from .. import client
    from ..models.assignment import Assignment
    from ..models.assignment_feedback import AssignmentFeedback
    from ..models.assignment_grader import AssignmentGrader
    from ..models.assignment_peer_feedback_connection import (
        AssignmentPeerFeedbackConnection,
    )
    from ..models.assignment_peer_feedback_settings import (
        AssignmentPeerFeedbackSettings,
    )
    from ..models.assignment_template import AssignmentTemplate
    from ..models.assignment_timeframes import AssignmentTimeframes
    from ..models.auto_test import AutoTest
    from ..models.comment_base import CommentBase
    from ..models.copy_rubric_assignment_data import CopyRubricAssignmentData
    from ..models.export_assignment_data import ExportAssignmentData
    from ..models.extended_course import ExtendedCourse
    from ..models.extended_work import ExtendedWork
    from ..models.import_into_assignment_data import ImportIntoAssignmentData
    from ..models.job import Job
    from ..models.patch_assignment_data import PatchAssignmentData
    from ..models.patch_rubric_category_type_assignment_data import (
        PatchRubricCategoryTypeAssignmentData,
    )
    from ..models.patch_submit_types_assignment_data import (
        PatchSubmitTypesAssignmentData,
    )
    from ..models.plagiarism_run import PlagiarismRun
    from ..models.put_description_assignment_data import (
        PutDescriptionAssignmentData,
    )
    from ..models.put_rubric_assignment_data import PutRubricAssignmentData
    from ..models.rubric_row_base import RubricRowBase
    from ..models.update_peer_feedback_settings_assignment_data import (
        UpdatePeerFeedbackSettingsAssignmentData,
    )
    from ..models.upload_submission_assignment_data import (
        UploadSubmissionAssignmentData,
    )
    from ..models.webhook_base import WebhookBase
    from ..models.work import Work


_ClientT = t.TypeVar("_ClientT", bound="client._BaseClient")


[docs]class AssignmentService(t.Generic[_ClientT]): __slots__ = ("__client",) def __init__(self, client: _ClientT) -> None: self.__client = client
[docs] def get_rubric( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Sequence[RubricRowBase]": """Return the rubric corresponding to the given `assignment_id`. :param assignment_id: The id of the assignment. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A list of `RubricRow` items. """ url = "/api/v1/assignments/{assignmentId}/rubrics/".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.rubric_row_base import RubricRowBase return parsers.JsonResponseParser( rqa.List(parsers.ParserFor.make(RubricRowBase)) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def put_rubric( self: "AssignmentService[client.AuthenticatedClient]", json_body: t.Union[dict, list, "PutRubricAssignmentData"], *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Sequence[RubricRowBase]": """Add or update rubric of an assignment. :param json_body: The body of the request. See :class:`.PutRubricAssignmentData` for information about the possible fields. You can provide this data as a :class:`.PutRubricAssignmentData` or as a dictionary. :param assignment_id: The id of the assignment :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The updated or created rubric. """ url = "/api/v1/assignments/{assignmentId}/rubrics/".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.put( url=url, json=utils.to_dict(json_body), params=params ) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.rubric_row_base import RubricRowBase return parsers.JsonResponseParser( rqa.List(parsers.ParserFor.make(RubricRowBase)) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def delete_rubric( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "None": """Delete the rubric for the given assignment. :param assignment_id: The id of the `Assignment` whose rubric should be deleted. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: Nothing. """ url = "/api/v1/assignments/{assignmentId}/rubrics/".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.delete(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 204): return parsers.ConstantlyParser(None).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def patch_rubric_category_type( self: "AssignmentService[client.AuthenticatedClient]", json_body: t.Union[ dict, list, "PatchRubricCategoryTypeAssignmentData" ], *, assignment_id: "int", rubric_category_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "RubricRowBase": """Change the type of a rubric category. :param json_body: The body of the request. See :class:`.PatchRubricCategoryTypeAssignmentData` for information about the possible fields. You can provide this data as a :class:`.PatchRubricCategoryTypeAssignmentData` or as a dictionary. :param assignment_id: The assignment of the rubric category. :param rubric_category_id: The rubric category you want to change the type of. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The updated rubric row. """ url = "/api/v1/assignments/{assignmentId}/rubrics/{rubricCategoryId}/type".format( assignmentId=assignment_id, rubricCategoryId=rubric_category_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.patch( url=url, json=utils.to_dict(json_body), params=params ) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.rubric_row_base import RubricRowBase return parsers.JsonResponseParser( parsers.ParserFor.make(RubricRowBase) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "Assignment": """Get a single assignment by id. :param assignment_id: The id of the assignment you want to get. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The requested assignment. """ url = "/api/v1/assignments/{assignmentId}".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment import Assignment return parsers.JsonResponseParser( parsers.ParserFor.make(Assignment) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def delete( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "None": """Delete a given `Assignment`. :param assignment_id: The id of the assignment :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: Nothing. """ url = "/api/v1/assignments/{assignmentId}".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.delete(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 204): return parsers.ConstantlyParser(None).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def patch( self: "AssignmentService[client.AuthenticatedClient]", json_body: t.Union[dict, list, "PatchAssignmentData"], *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "Assignment": """Update the given assignment with new values. :param json_body: The body of the request. See :class:`.PatchAssignmentData` for information about the possible fields. You can provide this data as a :class:`.PatchAssignmentData` or as a dictionary. :param assignment_id: The id of the assignment you want to update. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The updated assignment. """ url = "/api/v1/assignments/{assignmentId}".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.patch( url=url, json=utils.to_dict(json_body), params=params ) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment import Assignment return parsers.JsonResponseParser( parsers.ParserFor.make(Assignment) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_description( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "bytes": """Get the description for this assignment. :param assignment_id: The id of the assignment; :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A public link that allows users to download the file or the file itself as a stream of octets """ url = "/api/v1/assignments/{assignmentId}/description".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): return parsers.ResponsePropertyParser("content", bytes).try_parse( resp ) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def put_description( self: "AssignmentService[client.AuthenticatedClient]", multipart_data: t.Union[dict, list, "PutDescriptionAssignmentData"], *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "None": """Stores a file containing the new description for a given `Assignment`. :param multipart_data: The data that should form the body of the request. See :class:`.PutDescriptionAssignmentData` for information about the possible fields. :param assignment_id: The id of the assignment :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: An empty response. """ url = "/api/v1/assignments/{assignmentId}/description".format( assignmentId=assignment_id ) params = extra_parameters or {} data, files = utils.to_multipart(utils.to_dict(multipart_data)) with self.__client as client: resp = client.http.put( url=url, files=files, data=data, params=params ) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 204): return parsers.ConstantlyParser(None).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def delete_description( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "None": """Deletes the description for a given `Assignment`. :param assignment_id: The id of the assignment. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: An empty response. """ url = "/api/v1/assignments/{assignmentId}/description".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.delete(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 204): return parsers.ConstantlyParser(None).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_template( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "AssignmentTemplate": """Return the template corresponding to the given `assignment_id`. :param assignment_id: The id of the assignment. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The template for this assignment. """ url = "/api/v1/assignments/{assignmentId}/template".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment_template import AssignmentTemplate return parsers.JsonResponseParser( parsers.ParserFor.make(AssignmentTemplate) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def delete_template( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "None": """Delete the template corresponding to the given `assignment_id`. :param assignment_id: The id of the assignment. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: Nothing. """ url = "/api/v1/assignments/{assignmentId}/template".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.delete(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 204): return parsers.ConstantlyParser(None).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def update_peer_feedback_settings( self: "AssignmentService[client.AuthenticatedClient]", json_body: t.Union[ dict, list, "UpdatePeerFeedbackSettingsAssignmentData" ], *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "AssignmentPeerFeedbackSettings": """Enable peer feedback for an assignment. :param json_body: The body of the request. See :class:`.UpdatePeerFeedbackSettingsAssignmentData` for information about the possible fields. You can provide this data as a :class:`.UpdatePeerFeedbackSettingsAssignmentData` or as a dictionary. :param assignment_id: The id of the assignment for which you want to enable peer feedback. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The just created peer feedback settings. """ url = ( "/api/v1/assignments/{assignmentId}/peer_feedback_settings".format( assignmentId=assignment_id ) ) params = extra_parameters or {} with self.__client as client: resp = client.http.put( url=url, json=utils.to_dict(json_body), params=params ) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment_peer_feedback_settings import ( AssignmentPeerFeedbackSettings, ) return parsers.JsonResponseParser( parsers.ParserFor.make(AssignmentPeerFeedbackSettings) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def disable_peer_feedback( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "None": """Disabled peer feedback for an assignment. :param assignment_id: The id of the assignment for which you want to disable peer feedback. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: Nothing; an empty response. """ url = ( "/api/v1/assignments/{assignmentId}/peer_feedback_settings".format( assignmentId=assignment_id ) ) params = extra_parameters or {} with self.__client as client: resp = client.http.delete(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 204): return parsers.ConstantlyParser(None).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def export( self: "AssignmentService[client.AuthenticatedClient]", json_body: t.Union[dict, list, "ExportAssignmentData"], *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "Job": """Generate a CSV report for this assignment. :param json_body: The body of the request. See :class:`.ExportAssignmentData` for information about the possible fields. You can provide this data as a :class:`.ExportAssignmentData` or as a dictionary. :param assignment_id: The id of the assignment :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A CSV report for this assignment. """ url = "/api/v1/assignments/{assignmentId}/export".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.post( url=url, json=utils.to_dict(json_body), params=params ) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.job import Job return parsers.JsonResponseParser( parsers.ParserFor.make(Job) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_all( self: "AssignmentService[client.AuthenticatedClient]", *, only_with_rubric: "bool" = False, extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Sequence[Assignment]": """Get all the assignments that the current user can see. :param only_with_rubric: When `True` only assignments that have a rubric will be returned. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: All assignments (with a rubric if specified) that the current user can see. """ url = "/api/v1/assignments/" params: t.Dict[str, t.Any] = { **(extra_parameters or {}), "only_with_rubric": utils.to_dict(only_with_rubric), } with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment import Assignment return parsers.JsonResponseParser( rqa.List(parsers.ParserFor.make(Assignment)) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_all_graders( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Sequence[AssignmentGrader]": """Gets a list of all users that can grade in the given assignment. :param assignment_id: The id of the assignment :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A response containing the JSON serialized graders. """ url = "/api/v1/assignments/{assignmentId}/graders/".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment_grader import AssignmentGrader return parsers.JsonResponseParser( rqa.List(parsers.ParserFor.make(AssignmentGrader)) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_submissions_by_user( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", user_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Sequence[ExtendedWork]": """Return all submissions by the given user in the given assignment. This always returns extended version of the submissions. :param assignment_id: The id of the assignment :param user_id: The user of which you want to get the submissions. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A response containing the JSON serialized submissions. """ url = "/api/v1/assignments/{assignmentId}/users/{userId}/submissions/".format( assignmentId=assignment_id, userId=user_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.extended_work import ExtendedWork return parsers.JsonResponseParser( rqa.List(parsers.ParserFor.make(ExtendedWork)) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_all_submissions( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extended: "bool" = False, latest_only: "bool" = True, extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Union[t.Sequence[ExtendedWork], t.Sequence[Work]]": """Return all submissions for the given assignment. :param assignment_id: The id of the assignment :param extended: Whether to get extended or normal submissions. :param latest_only: Only get the latest submission of a user. Please use this option if at all possible, as students have a tendency to submit many attempts and that can make this route quite slow. The default value was changed to `True` in version "O". :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A response containing the JSON serialized submissions. """ url = "/api/v1/assignments/{assignmentId}/submissions/".format( assignmentId=assignment_id ) params: t.Dict[str, t.Any] = { **(extra_parameters or {}), "extended": utils.to_dict(extended), "latest_only": utils.to_dict(latest_only), } with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.extended_work import ExtendedWork from ..models.work import Work return parsers.JsonResponseParser( parsers.make_union( rqa.List(parsers.ParserFor.make(ExtendedWork)), rqa.List(parsers.ParserFor.make(Work)), ) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_template_file( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", file_id: "str", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "bytes": """Get the content of a single file of an assignment template. :param assignment_id: The id of the assignment. :param file_id: The id of the file. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The contents of the requested file. """ url = "/api/v1/assignments/{assignmentId}/template/{fileId}".format( assignmentId=assignment_id, fileId=file_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): return parsers.ResponsePropertyParser("content", bytes).try_parse( resp ) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_timeframes( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "AssignmentTimeframes": """Get the schedule for the specified `Assignment`. :param assignment_id: The id of the assignment; :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The assignment schedule. """ url = "/api/v1/assignments/{assignmentId}/timeframes/".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment_timeframes import AssignmentTimeframes return parsers.JsonResponseParser( parsers.ParserFor.make(AssignmentTimeframes) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def put_timeframes( self: "AssignmentService[client.AuthenticatedClient]", json_body: t.Union[dict, list, "AssignmentTimeframes"], *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "AssignmentTimeframes": """Updates the schedule for the specified `Assignment`. :param json_body: The body of the request. See :class:`.AssignmentTimeframes` for information about the possible fields. You can provide this data as a :class:`.AssignmentTimeframes` or as a dictionary. :param assignment_id: The id of the assignment; :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The updated assignment schedule. """ url = "/api/v1/assignments/{assignmentId}/timeframes/".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.put( url=url, json=utils.to_dict(json_body), params=params ) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment_timeframes import AssignmentTimeframes return parsers.JsonResponseParser( parsers.ParserFor.make(AssignmentTimeframes) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_all_feedback( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Mapping[str, AssignmentFeedback]": """Get all feedbacks for all the latest submissions for a given assignment. :param assignment_id: The assignment to query for. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A mapping between the id of the submission and a `AssignmentFeeback` object. """ url = "/api/v1/assignments/{assignmentId}/feedbacks/".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment_feedback import AssignmentFeedback return parsers.JsonResponseParser( rqa.LookupMapping(parsers.ParserFor.make(AssignmentFeedback)) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_auto_test( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "AutoTest": """Get the `AutoTest` for this assignment. :param assignment_id: The id of the assignment from which you want to get the `AutoTest`. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The `AutoTest` for the given assignment, if it has an `AutoTest`. """ url = "/api/v1/assignments/{assignmentId}/auto_test".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.auto_test import AutoTest return parsers.JsonResponseParser( parsers.ParserFor.make(AutoTest) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_comments_by_user( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", user_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Sequence[CommentBase]": """Get all the comments threads that a user replied on. This route is especially useful in the context of peer feedback. With this route you can get all the comments placed by the student, so you don't have to get all the submissions (including old ones) by the peer feedback subjects. :param assignment_id: The assignment from which you want to get the threads. :param user_id: The id of the user from which you want to get the threads. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A list of comments that all have at least one reply by the given user. There might be replies missing from these bases if these replies where not given by the user with id `user_id`, however no guarantee is made that all replies are by the user with id `user_id`. """ url = "/api/v1/assignments/{assignmentId}/users/{userId}/comments/".format( assignmentId=assignment_id, userId=user_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.comment_base import CommentBaseParser return parsers.JsonResponseParser( rqa.List(CommentBaseParser) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_course( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "ExtendedCourse": """Get the course connected to an assignment. :param assignment_id: The id of the assignment from which you want to get the course. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A response containing the JSON serialized course. """ url = "/api/v1/assignments/{assignmentId}/course".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.extended_course import ExtendedCourse return parsers.JsonResponseParser( parsers.ParserFor.make(ExtendedCourse) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_webhook_settings( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", webhook_type: "t.Literal['git']", author_id: Maybe["int"] = Nothing, is_test_submission: "bool" = False, extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "WebhookBase": """Create or get the webhook settings to hand-in submissions. You can select the user for which the webhook should hand-in using the exact same query parameters as the route to upload a submission. :param assignment_id: The assignment for which the webhook should hand-in submissions. :param webhook_type: The webhook type, currently only `git` is supported, which works for both GitLab and GitHub. :param author_id: The id of the user for which we should get the webhook settings. If not given defaults to the current user. :param is_test_submission: Should we get the webhook settings for the test student. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A serialized form of a webhook, which contains all data needed to add the webhook to your provider. """ url = "/api/v1/assignments/{assignmentId}/webhook_settings".format( assignmentId=assignment_id ) params: t.Dict[str, t.Any] = { **(extra_parameters or {}), "webhook_type": utils.to_dict(webhook_type), "is_test_submission": utils.to_dict(is_test_submission), } maybe_from_nullable(t.cast(t.Any, author_id)).if_just( lambda val: params.__setitem__("author_id", val) ) with self.__client as client: resp = client.http.post(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.webhook_base import WebhookBase return parsers.JsonResponseParser( parsers.ParserFor.make(WebhookBase) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_member_states( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", group_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Mapping[str, bool]": """Get the LTI states for the members of a group for the given assignment. :param assignment_id: The assignment for which the LTI states should be given. :param group_id: The group for which the states should be returned. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A mapping between user id and a boolean indicating if we can already passback grades for this user. If the assignment is any LTI assignment and any of the values in this mapping is `False` trying to submit anyway will result in a failure. """ url = "/api/v1/assignments/{assignmentId}/groups/{groupId}/member_states/".format( assignmentId=assignment_id, groupId=group_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): return parsers.JsonResponseParser( rqa.LookupMapping(rqa.SimpleValue.bool) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_peer_feedback_subjects( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", user_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Sequence[AssignmentPeerFeedbackConnection]": """Get the peer feedback subjects for a given user. :param assignment_id: The id of the assignment in which you want to get the peer feedback subjects. :param user_id: The id of the user from which you want to retrieve the peer feedback subjects. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The peer feedback subjects. If the deadline has not expired, or if the assignment is not a peer feedback assignment an empty list will be returned. """ url = "/api/v1/assignments/{assignmentId}/users/{userId}/peer_feedback_subjects/".format( assignmentId=assignment_id, userId=user_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment_peer_feedback_connection import ( AssignmentPeerFeedbackConnection, ) return parsers.JsonResponseParser( rqa.List( parsers.ParserFor.make(AssignmentPeerFeedbackConnection) ) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def get_all_plagiarism_runs( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Sequence[PlagiarismRun]": """Get all plagiarism runs for the given assignment. :param assignment_id: The id of the assignment :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: A response containing the JSON serialized list of plagiarism runs. """ url = "/api/v1/assignments/{assignmentId}/plagiarism/".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.get(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.plagiarism_run import PlagiarismRun return parsers.JsonResponseParser( rqa.List(parsers.ParserFor.make(PlagiarismRun)) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def import_into( self: "AssignmentService[client.AuthenticatedClient]", json_body: t.Union[dict, list, "ImportIntoAssignmentData"], *, into_assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "Assignment": """Import an assignment into another assignment. :param json_body: The body of the request. See :class:`.ImportIntoAssignmentData` for information about the possible fields. You can provide this data as a :class:`.ImportIntoAssignmentData` or as a dictionary. :param into_assignment_id: The assignment you want to import into. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The updated assignment, so the assignment which was imported into. """ url = "/api/v1/assignments/{intoAssignmentId}/import".format( intoAssignmentId=into_assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.post( url=url, json=utils.to_dict(json_body), params=params ) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment import Assignment return parsers.JsonResponseParser( parsers.ParserFor.make(Assignment) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def copy_rubric( self: "AssignmentService[client.AuthenticatedClient]", json_body: t.Union[dict, list, "CopyRubricAssignmentData"], *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "t.Sequence[RubricRowBase]": """Import a rubric from a different assignment. :param json_body: The body of the request. See :class:`.CopyRubricAssignmentData` for information about the possible fields. You can provide this data as a :class:`.CopyRubricAssignmentData` or as a dictionary. :param assignment_id: The id of the assignment in which you want to import the rubric. This assignment shouldn't have a rubric. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The rubric rows of the assignment in which the rubric was imported, so the assignment with id `assignment_id` and not `old_assignment_id`. """ url = "/api/v1/assignments/{assignmentId}/rubric".format( assignmentId=assignment_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.post( url=url, json=utils.to_dict(json_body), params=params ) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.rubric_row_base import RubricRowBase return parsers.JsonResponseParser( rqa.List(parsers.ParserFor.make(RubricRowBase)) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def mark_grader_as_done( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", grader_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "None": """Indicate that the given grader is done grading the given assignment. :param assignment_id: The id of the assignment the grader is done grading. :param grader_id: The id of the `User` that is done grading. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: An empty response with return code 204 """ url = "/api/v1/assignments/{assignmentId}/graders/{graderId}/done".format( assignmentId=assignment_id, graderId=grader_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.post(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 204): return parsers.ConstantlyParser(None).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def mark_grader_as_not_done( self: "AssignmentService[client.AuthenticatedClient]", *, assignment_id: "int", grader_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "None": """Indicate that the given grader is not yet done grading the given assignment. :param assignment_id: The id of the assignment the grader is not yet done grading. :param grader_id: The id of the `User` that is not yet done grading. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: An empty response with return code 204 """ url = "/api/v1/assignments/{assignmentId}/graders/{graderId}/done".format( assignmentId=assignment_id, graderId=grader_id ) params = extra_parameters or {} with self.__client as client: resp = client.http.delete(url=url, params=params) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 204): return parsers.ConstantlyParser(None).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def patch_submit_types( self: "AssignmentService[client.AuthenticatedClient]", multipart_data: t.Union[dict, list, "PatchSubmitTypesAssignmentData"], *, assignment_id: "int", extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "Assignment": """Update the given assignment editor template with new files. How this route deals with existing editor templates when submitting is still experimental and might change in an upcoming release. :param multipart_data: The data that should form the body of the request. See :class:`.PatchSubmitTypesAssignmentData` for information about the possible fields. :param assignment_id: The id of the assignment for which you want to update the editor template. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The updated assignment. """ url = "/api/v1/assignments/{assignmentId}/submit_types".format( assignmentId=assignment_id ) params = extra_parameters or {} data, files = utils.to_multipart(utils.to_dict(multipart_data)) with self.__client as client: resp = client.http.patch( url=url, files=files, data=data, params=params ) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 200): from ..models.assignment import Assignment return parsers.JsonResponseParser( parsers.ParserFor.make(Assignment) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )
[docs] def upload_submission( self: "AssignmentService[client.AuthenticatedClient]", multipart_data: t.Union[dict, list, "UploadSubmissionAssignmentData"], *, assignment_id: "int", author_id: Maybe["int"] = Nothing, is_test_submission: "bool" = False, ignored_files: "IgnoreHandling" = IgnoreHandling.keep, extra_parameters: t.Optional[ t.Mapping[str, t.Union[str, bool, int, float]] ] = None, ) -> "ExtendedWork": """Upload one or more files as `Work` to the given `Assignment`. :param multipart_data: The data that should form the body of the request. See :class:`.UploadSubmissionAssignmentData` for information about the possible fields. :param assignment_id: The id of the assignment :param author_id: The id of the user for which we should get the webhook settings. If not given defaults to the current user. :param is_test_submission: Should we get the webhook settings for the test student. :param ignored_files: How to handle ignored files. The options are: `keep`: this the default, sipmly do nothing about ignored files. `delete`: delete the ignored files. `error`: return an error when there are ignored files in the archive. :param extra_parameters: The extra query parameters you might want to add. By default no extra query parameters are added. :returns: The created work. """ url = "/api/v1/assignments/{assignmentId}/submission".format( assignmentId=assignment_id ) params: t.Dict[str, t.Any] = { **(extra_parameters or {}), "is_test_submission": utils.to_dict(is_test_submission), "ignored_files": utils.to_dict(ignored_files), } maybe_from_nullable(t.cast(t.Any, author_id)).if_just( lambda val: params.__setitem__("author_id", val) ) data, files = utils.to_multipart(utils.to_dict(multipart_data)) with self.__client as client: resp = client.http.post( url=url, files=files, data=data, params=params ) utils.log_warnings(resp) if utils.response_code_matches(resp.status_code, 201): from ..models.extended_work import ExtendedWork return parsers.JsonResponseParser( parsers.ParserFor.make(ExtendedWork) ).try_parse(resp) from ..models.any_error import AnyError raise utils.get_error( resp, ( ( (400, 409, 401, 403, 404, 429, 500), utils.unpack_union(AnyError), ), ), )