Exemplo n.º 1
0
def remove_step(step):
    """Function to remove a manual evaluation step and perform related tasks"""
    evaluator_key = db.Key.from_path(course_staff.CourseStaff.kind(),
                                     step.evaluator)
    evaluator, summary = entities.get(
        [evaluator_key, step.manual_evaluation_summary_key])
    if summary:
        summary.decrement_count(step.state)
    else:
        manage.COUNTER_DELETE_REVIEWER_SUMMARY_MISS.inc()
    step.removed = True
    if evaluator:
        evaluator.num_assigned -= 1
    entities.put([entity for entity in [step, summary, evaluator] if entity])
Exemplo n.º 2
0
    def _transition_state_to_expired(cls, review_step_key):
        step = entities.get(review_step_key)

        if not step:
            COUNTER_EXPIRE_REVIEW_STEP_MISS.inc()
            raise KeyError('No review step found with key %s' %
                           repr(review_step_key))

        if step.removed:
            COUNTER_EXPIRE_REVIEW_CANNOT_TRANSITION.inc()
            raise domain.RemovedError(
                'Cannot transition step %s' % repr(review_step_key),
                step.removed)

        if step.state in (domain.REVIEW_STATE_COMPLETED,
                          domain.REVIEW_STATE_EXPIRED):
            COUNTER_EXPIRE_REVIEW_CANNOT_TRANSITION.inc()
            raise domain.TransitionError(
                'Cannot transition step %s' % repr(review_step_key),
                step.state, domain.REVIEW_STATE_EXPIRED)

        summary = entities.get(step.review_summary_key)

        if not summary:
            COUNTER_EXPIRE_REVIEW_SUMMARY_MISS.inc()
            raise KeyError('No review summary found with key %s' %
                           repr(step.review_summary_key))

        summary.decrement_count(step.state)
        step.state = domain.REVIEW_STATE_EXPIRED
        summary.increment_count(step.state)
        return entities.put([step, summary])[0]
Exemplo n.º 3
0
    def _add_new_reviewer(cls, unit_id, submission_key, reviewee_key,
                          reviewer_key):
        summary = peer.ReviewSummary(assigned_count=1,
                                     reviewee_key=reviewee_key,
                                     submission_key=submission_key,
                                     unit_id=unit_id)
        # Synthesize summary key to avoid a second synchronous put op.
        summary_key = db.Key.from_path(
            peer.ReviewSummary.kind(),
            peer.ReviewSummary.key_name(submission_key))
        step = peer.ReviewStep(assigner_kind=domain.ASSIGNER_KIND_HUMAN,
                               review_summary_key=summary_key,
                               reviewee_key=reviewee_key,
                               reviewer_key=reviewer_key,
                               state=domain.REVIEW_STATE_ASSIGNED,
                               submission_key=submission_key,
                               unit_id=unit_id)
        # pylint: disable=unbalanced-tuple-unpacking,unpacking-non-sequence
        step_key, written_summary_key = entities.put([step, summary])

        if summary_key != written_summary_key:
            COUNTER_ADD_REVIEWER_BAD_SUMMARY_KEY.inc()
            raise AssertionError('Synthesized invalid review summary key %s' %
                                 repr(summary_key))

        COUNTER_ADD_REVIEWER_CREATE_REVIEW_STEP.inc()
        return step_key
Exemplo n.º 4
0
    def _transition_state_to_expired(cls, review_step_key):
        step = entities.get(review_step_key)

        if not step:
            COUNTER_EXPIRE_REVIEW_STEP_MISS.inc()
            raise KeyError(
                'No review step found with key %s' % repr(review_step_key))

        if step.removed:
            COUNTER_EXPIRE_REVIEW_CANNOT_TRANSITION.inc()
            raise domain.RemovedError(
                'Cannot transition step %s' % repr(review_step_key),
                step.removed)

        if step.state in (
                domain.REVIEW_STATE_COMPLETED, domain.REVIEW_STATE_EXPIRED):
            COUNTER_EXPIRE_REVIEW_CANNOT_TRANSITION.inc()
            raise domain.TransitionError(
                'Cannot transition step %s' % repr(review_step_key),
                step.state, domain.REVIEW_STATE_EXPIRED)

        summary = entities.get(step.review_summary_key)

        if not summary:
            COUNTER_EXPIRE_REVIEW_SUMMARY_MISS.inc()
            raise KeyError(
                'No review summary found with key %s' % repr(
                    step.review_summary_key))

        summary.decrement_count(step.state)
        step.state = domain.REVIEW_STATE_EXPIRED
        summary.increment_count(step.state)
        return entities.put([step, summary])[0]
Exemplo n.º 5
0
    def bulk_score_by_course(cls, course, csv_list, errors):
        """
        Bulk score assessments by email.

        csv list should be of the following format:
        [
            [email, assessment_id, score],
            .
            .
        ]
        """

        students = []

        student_ids = [entry[0].strip() for entry in csv_list]
        students = models.StudentProfileDAO.bulk_get_student_by_email(
            student_ids)
        modified_students = []

        for i, entry in enumerate(csv_list):

            if len(entry) != 3:
                if len(entry) >= 1:
                    errors.append('Invalid row %s' % ','.join(entry))
                    continue

            assessment_id = entry[1].strip()
            try:
                score = float(entry[2])
            except ValueError:
                errors.append('Invalid row %s' % ','.join(entry))
                continue
            student = students[i]
            if student:
                if not cls.score(student, course, assessment_id, score,
                                 errors):
                    errors.append('Failed to score: %s, %s, %s' %
                                  (student.email, assessment_id, score))
                else:
                    modified_students.append(student)
            else:
                errors.append('Student not found %s' % student_ids[i])

        # Bulk save the students
        entities.put(modified_students)
Exemplo n.º 6
0
def reshare_submission_with_evaluator(step):
    """Function to share the step's submission contents with the course staff"""

    unit_id = step.unit_id
    namespace = namespace_manager.get_namespace()
    if namespace:
        app_context = sites.get_app_context_for_namespace(namespace)
        if app_context:
            course = courses.Course.get(app_context)
            if course:
                unit = course.find_unit_by_id(unit_id)
                if unit:
                    content = (
                        question.SubjectiveAssignmentBaseHandler.get_content(
                            course, unit))
                    if question.SubjectiveAssignmentBaseHandler.BLOB != (
                            content.get(
                                question.SubjectiveAssignmentBaseHandler.
                                OPT_QUESTION_TYPE)):
                        # Not a drive type submission, skip.
                        return

                    if transforms.loads(step.drive_permission_list):
                        # Permission list already present, skip.
                        return

                    evaluator = course_staff.CourseStaff.get_by_key_name(
                        step.evaluator)
                    submission_key = step.submission_key
                    submission_contents = (
                        manage.Manager.get_submission_contents_dict(
                            submission_key))

                    if submission_contents and evaluator:
                        drive_permission_list_dump = transforms.dumps(
                            manage.Manager.share_submission_with_evaluator(
                                submission_contents, evaluator.email))

                        step.drive_permission_list = drive_permission_list_dump
                        entities.put([step])
                        return
                    logging.error('Invalid evaluator or submission for step ' +
                                  step.key().name())
                    return
    logging.error('Could not load unit for step ' + step.key())
Exemplo n.º 7
0
    def _add_reviewer_update_step(cls, step):
        should_increment_human = False
        should_increment_reassigned = False
        should_increment_unremoved = False
        summary = entities.get(step.review_summary_key)

        if not summary:
            COUNTER_ADD_REVIEWER_BAD_SUMMARY_KEY.inc()
            raise AssertionError(
                'Found invalid review summary key %s' % repr(
                    step.review_summary_key))

        if not step.removed:

            if step.state == domain.REVIEW_STATE_EXPIRED:
                should_increment_reassigned = True
                step.state = domain.REVIEW_STATE_ASSIGNED
                summary.decrement_count(domain.REVIEW_STATE_EXPIRED)
                summary.increment_count(domain.REVIEW_STATE_ASSIGNED)
            elif (step.state == domain.REVIEW_STATE_ASSIGNED or
                  step.state == domain.REVIEW_STATE_COMPLETED):
                COUNTER_ADD_REVIEWER_UNREMOVED_STEP_FAILED.inc()
                raise domain.TransitionError(
                    'Unable to add new reviewer to step %s' % (
                        repr(step.key())),
                    step.state, domain.REVIEW_STATE_ASSIGNED)
        else:
            should_increment_unremoved = True
            step.removed = False

            if step.state != domain.REVIEW_STATE_EXPIRED:
                summary.increment_count(step.state)
            else:
                should_increment_reassigned = True
                step.state = domain.REVIEW_STATE_ASSIGNED
                summary.decrement_count(domain.REVIEW_STATE_EXPIRED)
                summary.increment_count(domain.REVIEW_STATE_ASSIGNED)

        if step.assigner_kind != domain.ASSIGNER_KIND_HUMAN:
            should_increment_human = True
            step.assigner_kind = domain.ASSIGNER_KIND_HUMAN

        step_key = entities.put([step, summary])[0]

        if should_increment_human:
            COUNTER_ADD_REVIEWER_SET_ASSIGNER_KIND_HUMAN.inc()
        if should_increment_reassigned:
            COUNTER_ADD_REVIEWER_EXPIRED_STEP_REASSIGNED.inc()
        if should_increment_unremoved:
            COUNTER_ADD_REVIEWER_REMOVED_STEP_UNREMOVED.inc()

        return step_key
Exemplo n.º 8
0
    def _attempt_review_assignment(cls, review_summary_key, reviewer_key,
                                   last_change_date):
        COUNTER_GET_NEW_REVIEW_ASSIGNMENT_ATTEMPTED.inc()
        summary = entities.get(review_summary_key)
        if not summary:
            raise KeyError('No review summary found with key %s' %
                           repr(review_summary_key))
        if summary.change_date != last_change_date:
            # The summary has changed since we queried it. We cannot know for
            # sure what the edit was, but let's skip to the next one because it
            # was probably a review assignment.
            COUNTER_GET_NEW_REVIEW_SUMMARY_CHANGED.inc()
            return

        step = peer.ReviewStep.get_by_key_name(
            peer.ReviewStep.key_name(summary.submission_key, reviewer_key))

        if not step:
            step = peer.ReviewStep(assigner_kind=domain.ASSIGNER_KIND_AUTO,
                                   review_summary_key=summary.key(),
                                   reviewee_key=summary.reviewee_key,
                                   reviewer_key=reviewer_key,
                                   state=domain.REVIEW_STATE_ASSIGNED,
                                   submission_key=summary.submission_key,
                                   unit_id=summary.unit_id)
        else:
            if step.state == domain.REVIEW_STATE_COMPLETED:
                # Reviewer has previously done this review and the review
                # has been deleted. Skip to the next one.
                COUNTER_GET_NEW_REVIEW_CANNOT_UNREMOVE_COMPLETED.inc()
                return

            if step.removed:
                # We can reassign the existing review step.
                COUNTER_GET_NEW_REVIEW_REASSIGN_EXISTING.inc()
                step.removed = False
                step.assigner_kind = domain.ASSIGNER_KIND_AUTO
                step.state = domain.REVIEW_STATE_ASSIGNED
            else:
                # Reviewee has already reviewed or is already assigned to review
                # this submission, so we cannot reassign the step.
                COUNTER_GET_NEW_REVIEW_ALREADY_ASSIGNED.inc()
                return

        summary.increment_count(domain.REVIEW_STATE_ASSIGNED)
        return entities.put([step, summary])[0]
Exemplo n.º 9
0
    def _attempt_review_assignment(
        cls, review_summary_key, reviewer_key, last_change_date):
        COUNTER_GET_NEW_REVIEW_ASSIGNMENT_ATTEMPTED.inc()
        summary = entities.get(review_summary_key)
        if not summary:
            raise KeyError('No review summary found with key %s' % repr(
                review_summary_key))
        if summary.change_date != last_change_date:
            # The summary has changed since we queried it. We cannot know for
            # sure what the edit was, but let's skip to the next one because it
            # was probably a review assignment.
            COUNTER_GET_NEW_REVIEW_SUMMARY_CHANGED.inc()
            return

        step = peer.ReviewStep.get_by_key_name(
            peer.ReviewStep.key_name(summary.submission_key, reviewer_key))

        if not step:
            step = peer.ReviewStep(
                assigner_kind=domain.ASSIGNER_KIND_AUTO,
                review_summary_key=summary.key(),
                reviewee_key=summary.reviewee_key, reviewer_key=reviewer_key,
                state=domain.REVIEW_STATE_ASSIGNED,
                submission_key=summary.submission_key, unit_id=summary.unit_id)
        else:
            if step.state == domain.REVIEW_STATE_COMPLETED:
                # Reviewer has previously done this review and the review
                # has been deleted. Skip to the next one.
                COUNTER_GET_NEW_REVIEW_CANNOT_UNREMOVE_COMPLETED.inc()
                return

            if step.removed:
                # We can reassign the existing review step.
                COUNTER_GET_NEW_REVIEW_REASSIGN_EXISTING.inc()
                step.removed = False
                step.assigner_kind = domain.ASSIGNER_KIND_AUTO
                step.state = domain.REVIEW_STATE_ASSIGNED
            else:
                # Reviewee has already reviewed or is already assigned to review
                # this submission, so we cannot reassign the step.
                COUNTER_GET_NEW_REVIEW_ALREADY_ASSIGNED.inc()
                return

        summary.increment_count(domain.REVIEW_STATE_ASSIGNED)
        return entities.put([step, summary])[0]
Exemplo n.º 10
0
    def _mark_review_step_removed(cls, review_step_key):
        step = entities.get(review_step_key)
        if not step:
            COUNTER_DELETE_REVIEWER_STEP_MISS.inc()
            raise KeyError('No review step found with key %s' %
                           repr(review_step_key))
        if step.removed:
            COUNTER_DELETE_REVIEWER_ALREADY_REMOVED.inc()
            raise domain.RemovedError(
                'Cannot remove step %s' % repr(review_step_key), step.removed)
        summary = entities.get(step.review_summary_key)

        if not summary:
            COUNTER_DELETE_REVIEWER_SUMMARY_MISS.inc()
            raise KeyError('No review summary found with key %s' %
                           repr(step.review_summary_key))

        step.removed = True
        summary.decrement_count(step.state)
        return entities.put([step, summary])[0]
Exemplo n.º 11
0
    def _mark_review_step_removed(cls, review_step_key):
        step = entities.get(review_step_key)
        if not step:
            COUNTER_DELETE_REVIEWER_STEP_MISS.inc()
            raise KeyError(
                'No review step found with key %s' % repr(review_step_key))
        if step.removed:
            COUNTER_DELETE_REVIEWER_ALREADY_REMOVED.inc()
            raise domain.RemovedError(
                'Cannot remove step %s' % repr(review_step_key), step.removed)
        summary = entities.get(step.review_summary_key)

        if not summary:
            COUNTER_DELETE_REVIEWER_SUMMARY_MISS.inc()
            raise KeyError(
                'No review summary found with key %s' % repr(
                    step.review_summary_key))

        step.removed = True
        summary.decrement_count(step.state)
        return entities.put([step, summary])[0]
Exemplo n.º 12
0
    def _add_new_reviewer(
        cls, unit_id, submission_key, reviewee_key, reviewer_key):
        summary = peer.ReviewSummary(
            assigned_count=1, reviewee_key=reviewee_key,
            submission_key=submission_key, unit_id=unit_id)
        # Synthesize summary key to avoid a second synchronous put op.
        summary_key = db.Key.from_path(
            peer.ReviewSummary.kind(),
            peer.ReviewSummary.key_name(submission_key))
        step = peer.ReviewStep(
            assigner_kind=domain.ASSIGNER_KIND_HUMAN,
            review_summary_key=summary_key, reviewee_key=reviewee_key,
            reviewer_key=reviewer_key, state=domain.REVIEW_STATE_ASSIGNED,
            submission_key=submission_key, unit_id=unit_id)
        step_key, written_summary_key = entities.put([step, summary])

        if summary_key != written_summary_key:
            COUNTER_ADD_REVIEWER_BAD_SUMMARY_KEY.inc()
            raise AssertionError(
                'Synthesized invalid review summary key %s' % repr(summary_key))

        COUNTER_ADD_REVIEWER_CREATE_REVIEW_STEP.inc()
        return step_key
Exemplo n.º 13
0
    def _update_review_contents_and_change_state(cls, review_step_key,
                                                 review_payload,
                                                 mark_completed):
        should_increment_created_new_review = False
        should_increment_updated_existing_review = False
        should_increment_assigned_to_completed = False
        should_increment_expired_to_completed = False

        step = entities.get(review_step_key)
        if not step:
            COUNTER_WRITE_REVIEW_STEP_MISS.inc()
            raise KeyError('No review step found with key %s' %
                           repr(review_step_key))
        elif step.removed:
            raise domain.RemovedError(
                'Unable to process step %s' % repr(step.key()), step.removed)
        elif mark_completed and step.state == domain.REVIEW_STATE_COMPLETED:
            raise domain.TransitionError(
                'Unable to transition step %s' % repr(step.key()), step.state,
                domain.REVIEW_STATE_COMPLETED)

        if step.review_key:
            review_to_update = entities.get(step.review_key)
            if review_to_update:
                should_increment_updated_existing_review = True
        else:
            review_to_update = student_work.Review(
                contents=review_payload,
                reviewee_key=step.reviewee_key,
                reviewer_key=step.reviewer_key,
                unit_id=step.unit_id)
            step.review_key = db.Key.from_path(
                student_work.Review.kind(),
                student_work.Review.key_name(step.unit_id, step.reviewee_key,
                                             step.reviewer_key))
            should_increment_created_new_review = True

        if not review_to_update:
            COUNTER_WRITE_REVIEW_REVIEW_MISS.inc()
            raise domain.ConstraintError('No review found with key %s' %
                                         repr(step.review_key))

        summary = entities.get(step.review_summary_key)
        if not summary:
            COUNTER_WRITE_REVIEW_SUMMARY_MISS.inc()
            raise domain.ConstraintError(
                'No review summary found with key %s' %
                repr(step.review_summary_key))

        review_to_update.contents = review_payload
        updated_step_key = None
        if not mark_completed:
            # pylint: disable=unbalanced-tuple-unpacking,unpacking-non-sequence
            _, updated_step_key = entities.put([review_to_update, step])
        else:
            if step.state == domain.REVIEW_STATE_ASSIGNED:
                should_increment_assigned_to_completed = True
            elif step.state == domain.REVIEW_STATE_EXPIRED:
                should_increment_expired_to_completed = True

            summary.decrement_count(step.state)
            step.state = domain.REVIEW_STATE_COMPLETED
            summary.increment_count(step.state)

            # pylint: disable=unbalanced-tuple-unpacking,unpacking-non-sequence
            _, updated_step_key, _ = entities.put(
                [review_to_update, step, summary])

        if should_increment_created_new_review:
            COUNTER_WRITE_REVIEW_CREATED_NEW_REVIEW.inc()
        elif should_increment_updated_existing_review:
            COUNTER_WRITE_REVIEW_UPDATED_EXISTING_REVIEW.inc()

        if should_increment_assigned_to_completed:
            COUNTER_WRITE_REVIEW_COMPLETED_ASSIGNED_STEP.inc()
        elif should_increment_expired_to_completed:
            COUNTER_WRITE_REVIEW_COMPLETED_EXPIRED_STEP.inc()

        return updated_step_key
Exemplo n.º 14
0
    def _update_review_contents_and_change_state(
        cls, review_step_key, review_payload, mark_completed):
        should_increment_created_new_review = False
        should_increment_updated_existing_review = False
        should_increment_assigned_to_completed = False
        should_increment_expired_to_completed = False

        step = entities.get(review_step_key)
        if not step:
            COUNTER_WRITE_REVIEW_STEP_MISS.inc()
            raise KeyError(
                'No review step found with key %s' % repr(review_step_key))
        elif step.removed:
            raise domain.RemovedError(
                'Unable to process step %s' % repr(step.key()), step.removed)
        elif mark_completed and step.state == domain.REVIEW_STATE_COMPLETED:
            raise domain.TransitionError(
                'Unable to transition step %s' % repr(step.key()),
                step.state, domain.REVIEW_STATE_COMPLETED)

        if step.review_key:
            review_to_update = entities.get(step.review_key)
            if review_to_update:
                should_increment_updated_existing_review = True
        else:
            review_to_update = student_work.Review(
                contents=review_payload, reviewee_key=step.reviewee_key,
                reviewer_key=step.reviewer_key, unit_id=step.unit_id)
            step.review_key = db.Key.from_path(
                student_work.Review.kind(),
                student_work.Review.key_name(
                    step.unit_id, step.reviewee_key, step.reviewer_key))
            should_increment_created_new_review = True

        if not review_to_update:
            COUNTER_WRITE_REVIEW_REVIEW_MISS.inc()
            raise domain.ConstraintError(
                'No review found with key %s' % repr(step.review_key))

        summary = entities.get(step.review_summary_key)
        if not summary:
            COUNTER_WRITE_REVIEW_SUMMARY_MISS.inc()
            raise domain.ConstraintError(
                'No review summary found with key %s' % repr(
                    step.review_summary_key))

        review_to_update.contents = review_payload
        updated_step_key = None
        if not mark_completed:
            # pylint: disable=unbalanced-tuple-unpacking,unpacking-non-sequence
            _, updated_step_key = entities.put([review_to_update, step])
        else:
            if step.state == domain.REVIEW_STATE_ASSIGNED:
                should_increment_assigned_to_completed = True
            elif step.state == domain.REVIEW_STATE_EXPIRED:
                should_increment_expired_to_completed = True

            summary.decrement_count(step.state)
            step.state = domain.REVIEW_STATE_COMPLETED
            summary.increment_count(step.state)

            # pylint: disable=unbalanced-tuple-unpacking,unpacking-non-sequence
            _, updated_step_key, _ = entities.put(
                [review_to_update, step, summary])

        if should_increment_created_new_review:
            COUNTER_WRITE_REVIEW_CREATED_NEW_REVIEW.inc()
        elif should_increment_updated_existing_review:
            COUNTER_WRITE_REVIEW_UPDATED_EXISTING_REVIEW.inc()

        if should_increment_assigned_to_completed:
            COUNTER_WRITE_REVIEW_COMPLETED_ASSIGNED_STEP.inc()
        elif should_increment_expired_to_completed:
            COUNTER_WRITE_REVIEW_COMPLETED_EXPIRED_STEP.inc()

        return updated_step_key