Beispiel #1
0
    def test_get_teammates_with_submissions_from_other_teams__cancelled(self):
        # Make a team submission with default users, under TEAM_1
        team_submission = self._make_team_submission(
            attempt_number=1,
            course_id=COURSE_ID,
            item_id=ITEM_1_ID,
            team_id=TEAM_1_ID,
            status=None,
            create_submissions=True
        )

        # Simulate resetting student state for the team, which causes the submissions to be deleted
        team_api.reset_scores(team_submission.uuid, clear_state=True)

        team_submission.refresh_from_db()
        self.assertEqual(team_submission.status, DELETED)
        for individual_submission in team_submission.submissions.all():
            self.assertEqual(individual_submission.status, DELETED)

        # Now, everyone has moved to a new team, but their old submission was deleted, so no one should be listed
        with self.assertNumQueries(1):
            external_submissions = team_api.get_teammates_with_submissions_from_other_teams(
                COURSE_ID,
                ITEM_1_ID,
                TEAM_2_ID,
                self.student_ids
            )

        # Returns no one, since the submission was cancelled
        self.assertEqual(external_submissions, [])
    def clear_team_state(self, user_id, course_id, item_id, requesting_user_id,
                         submissions):
        """
        This is called from clear_student_state (which is called from the LMS runtime) when the xblock is a team
        assignment, to clear student state for an entire team for a given problem. It will cancel the workflow
        to remove it from the grading pools, and pass through to the submissions team API to orphan the team
        submission and individual submissions so that the team can create a new submission.
        """
        student_item_string = "course {} item {} user {}".format(
            course_id, item_id, user_id)

        if not submissions:
            logger.warning(
                'Attempted to reset team state for %s but no submission was found',
                student_item_string)
            return
        if len(submissions) != 1:
            logger.warning(
                'Unexpected multiple individual submissions for team assignment. %s',
                student_item_string)

        submission = submissions[0]
        team_submission_uuid = str(submission.get('team_submission_uuid',
                                                  None))
        if not team_submission_uuid:
            logger.warning(
                'Attempted to reset team state for %s but submission %s has no team_submission_uuid',
                student_item_string, submission['uuid'])
            return
        # Remove the submission from grading pool
        self._cancel_team_workflow(team_submission_uuid,
                                   "Student and team state cleared",
                                   requesting_user_id)

        from submissions import team_api as team_submissions_api

        # Clean up shared files for the team
        team_id = team_submissions_api.get_team_submission(
            team_submission_uuid).get('team_id', None)
        delete_shared_files_for_team(course_id, item_id, team_id)

        # Tell the submissions API to orphan the submissions to prevent them from being accessed
        team_submissions_api.reset_scores(team_submission_uuid,
                                          clear_state=True)
Beispiel #3
0
    def test_reset_scores(self, set_scores, clear_state):
        """
        Test for resetting scores.
        """
        team_submission = self._make_team_submission(create_submissions=True)
        if set_scores:
            team_api.set_score(team_submission.uuid, 6, 10)

        team_submission.refresh_from_db()

        self.assertEqual(team_submission.status, ACTIVE)
        student_items = []
        for submission in team_submission.submissions.all():
            self.assertEqual(submission.status, ACTIVE)
            student_items.append(submission.student_item)

        # We have no / some scores, and no resets.
        self.assertEqual(
            Score.objects.filter(student_item__in=student_items, reset=False).count(),
            0 if not set_scores else len(student_items)
        )
        self.assertEqual(
            Score.objects.filter(student_item__in=student_items, reset=True).count(),
            0
        )

        # Reset
        team_api.reset_scores(team_submission.uuid, clear_state=clear_state)

        expected_state = DELETED if clear_state else ACTIVE
        # If we've cleared the state, the team submission status should be DELETED,
        # as should all of the individual submissions
        team_submission.refresh_from_db()
        self.assertEqual(team_submission.status, expected_state)
        for submission in team_submission.submissions.all():
            self.assertEqual(submission.status, expected_state)

        # We have created reset scores
        self.assertEqual(
            Score.objects.filter(student_item__in=student_items, reset=True).count(),
            len(student_items)
        )
Beispiel #4
0
    def clear_team_state(self, user_id, course_id, item_id,
                         requesting_user_id):
        """
        This is called from clear_student_state (which is called from the LMS runtime) when the xblock is a team
        assignment, to clear student state for an entire team for a given problem. It will cancel the workflow
        to remove it from the grading pools, and pass through to the submissions team API to orphan the team
        submission and individual submissions so that the team can create a new submission.
        """
        error_msg_base = 'Attempted to clear team state for anonymous user {} '.format(
            user_id)
        try:
            user_team = self.get_team_for_anonymous_user(user_id)
        except ObjectDoesNotExist:
            warning_msg = error_msg_base + 'but was unable to resolve to a real user'
            logger.warning(warning_msg)
            return

        if user_team is None:
            warning_msg = error_msg_base + 'but they are not on a team for course {} item {}.'.format(
                course_id, item_id)
            logger.warning(warning_msg)
            return

        from submissions import team_api as team_submissions_api

        try:
            team_submission = team_submissions_api.get_team_submission_for_team(
                course_id, item_id, user_team.team_id)
        except TeamSubmissionNotFoundError:
            warning_msg = error_msg_base + "course {} item {} but no team submission was found for team {}".format(
                course_id, item_id, user_team.team_id)
            logger.warning(warning_msg)

        # Remove the submission from grading pool
        self._cancel_team_workflow(team_submission['team_submission_uuid'],
                                   "Student and team state cleared",
                                   requesting_user_id)
        # Tell the submissions API to orphan the submissions to prevent them from being accessed
        team_submissions_api.reset_scores(
            team_submission['team_submission_uuid'])
Beispiel #5
0
 def test_reset_scores_error(self, mock_individual_reset):
     mock_individual_reset.side_effect = DatabaseError()
     team_submission = self._make_team_submission(create_submissions=True)
     with self.assertRaises(TeamSubmissionInternalError):
         team_api.reset_scores(team_submission.uuid)