def set_score(submission_uuid, points_earned, points_possible, annotation_creator=None, annotation_type=None, annotation_reason=None): """Set a score for a particular submission. Sets the score for a particular submission. This score is calculated externally to the API. Args: submission_uuid (str): UUID for the submission (must exist). points_earned (int): The earned points for this submission. points_possible (int): The total points possible for this particular student item. annotation_creator (str): An optional field for recording who gave this particular score annotation_type (str): An optional field for recording what type of annotation should be created, e.g. "staff_override". annotation_reason (str): An optional field for recording why this score was set to its value. Returns: None Raises: SubmissionInternalError: Thrown if there was an internal error while attempting to save the score. SubmissionRequestError: Thrown if the given student item or submission are not found. Examples: >>> set_score("a778b933-9fb3-11e3-9c0f-040ccee02800", 11, 12) { 'student_item': 2, 'submission': 1, 'points_earned': 11, 'points_possible': 12, 'created_at': datetime.datetime(2014, 2, 7, 20, 6, 42, 331156, tzinfo=<UTC>) } """ try: submission_model = _get_submission_model(submission_uuid) except Submission.DoesNotExist as error: raise SubmissionNotFoundError( f"No submission matching uuid {submission_uuid}") from error except DatabaseError as error: error_msg = "Could not retrieve submission {}.".format(submission_uuid) logger.exception(error_msg) raise SubmissionRequestError(msg=error_msg) from error score = ScoreSerializer( data={ "student_item": submission_model.student_item.pk, "submission": submission_model.pk, "points_earned": points_earned, "points_possible": points_possible, }) if not score.is_valid(): logger.exception(score.errors) raise SubmissionInternalError(score.errors) # When we save the score, a score summary will be created if # it does not already exist. # When the database's isolation level is set to repeatable-read, # it's possible for a score summary to exist for this student item, # even though we cannot retrieve it. # In this case, we assume that someone else has already created # a score summary and ignore the error. try: with transaction.atomic(): score_model = score.save() _log_score(score_model) if annotation_creator is not None: score_annotation = ScoreAnnotation( score=score_model, creator=annotation_creator, annotation_type=annotation_type, reason=annotation_reason) score_annotation.save() # Send a signal out to any listeners who are waiting for scoring events. score_set.send( sender=None, points_possible=points_possible, points_earned=points_earned, anonymous_user_id=submission_model.student_item.student_id, course_id=submission_model.student_item.course_id, item_id=submission_model.student_item.item_id, created_at=score_model.created_at, ) except IntegrityError: pass
def set_score(submission_uuid, points_earned, points_possible): """Set a score for a particular submission. Sets the score for a particular submission. This score is calculated externally to the API. Args: submission_uuid (str): UUID for the submission (must exist). points_earned (int): The earned points for this submission. points_possible (int): The total points possible for this particular student item. Returns: None Raises: SubmissionInternalError: Thrown if there was an internal error while attempting to save the score. SubmissionRequestError: Thrown if the given student item or submission are not found. Examples: >>> set_score("a778b933-9fb3-11e3-9c0f-040ccee02800", 11, 12) { 'student_item': 2, 'submission': 1, 'points_earned': 11, 'points_possible': 12, 'created_at': datetime.datetime(2014, 2, 7, 20, 6, 42, 331156, tzinfo=<UTC>) } """ try: submission_model = Submission.objects.get(uuid=submission_uuid) except Submission.DoesNotExist: raise SubmissionNotFoundError( u"No submission matching uuid {}".format(submission_uuid) ) except DatabaseError: error_msg = u"Could not retrieve student item: {} or submission {}.".format( submission_uuid ) logger.exception(error_msg) raise SubmissionRequestError(msg=error_msg) score = ScoreSerializer( data={ "student_item": submission_model.student_item.pk, "submission": submission_model.pk, "points_earned": points_earned, "points_possible": points_possible, } ) if not score.is_valid(): logger.exception(score.errors) raise SubmissionInternalError(score.errors) # When we save the score, a score summary will be created if # it does not already exist. # When the database's isolation level is set to repeatable-read, # it's possible for a score summary to exist for this student item, # even though we cannot retrieve it. # In this case, we assume that someone else has already created # a score summary and ignore the error. try: score_model = score.save() _log_score(score_model) # Send a signal out to any listeners who are waiting for scoring events. score_set.send( sender=None, points_possible=points_possible, points_earned=points_earned, anonymous_user_id=submission_model.student_item.student_id, course_id=submission_model.student_item.course_id, item_id=submission_model.student_item.item_id, ) except IntegrityError: pass