Exemplo n.º 1
0
    def setUp(self):
        super(TestGrading, self).setUp()
        self.setup_course()

        message_dict = {'file_contents': {'backup.py': '1'}, 'analytics': {}}

        self.active_user_ids = [self.user1.id, self.user2.id, self.user3.id]
        self.active_staff = [self.staff1, self.staff2]
        self.active_assignments = [self.assignment, self.assignment2]

        Group.invite(self.user1, self.user2, self.assignment)
        group = Group.lookup(self.user1, self.assignment)
        group.accept(self.user2)

        # Creates 5 submissions for each assignment per user, each spaced two minutes apart

        for assign in self.active_assignments:
            time = assign.due_date - datetime.timedelta(minutes=30)
            for num in range(5):
                for user_id in self.active_user_ids:
                    num += 1
                    time += datetime.timedelta(minutes=2)
                    backup = Backup(submitter_id=user_id,
                        assignment=assign, submit=True)
                    messages = [Message(kind=k, backup=backup,
                        contents=m) for k, m in message_dict.items()]
                    backup.created = time
                    db.session.add_all(messages)
                    db.session.add(backup)
                    # Debugging print if tests fails
                    # print("User {} | Assignment {} | Submission {} | Time {}".format(
                    #     user_id, assign.id, num, time))
        db.session.commit()
Exemplo n.º 2
0
    def test_backup_owners(self):
        backup = Backup(submitter_id=self.user1.id,
                        assignment=self.assignment,
                        submit=True)
        backup2 = Backup(submitter_id=self.user2.id,
                         assignment=self.assignment,
                         submit=True)
        db.session.add(backup)
        db.session.add(backup2)
        db.session.commit()
        assert backup2.owners() == {self.user2.id}

        Group.invite(self.user1, self.user2, self.assignment)
        Group.invite(self.user1, self.user3, self.assignment)
        group = Group.lookup(self.user1, self.assignment)
        group.accept(self.user2)

        assert backup.owners() == {self.user1.id, self.user2.id}
        assert backup2.owners() == {self.user1.id, self.user2.id}
Exemplo n.º 3
0
def gen_backup(user, assignment):
    seconds_offset = random.randrange(-100000, 100)
    messages = gen_messages(assignment, seconds_offset)
    submit = gen_bool(0.3)
    if submit:
        messages['file_contents']['submit'] = ''
    backup = Backup(created=assignment.due_date -
                    datetime.timedelta(seconds=seconds_offset),
                    submitter_id=user.id,
                    assignment_id=assignment.id,
                    submit=submit)
    backup.messages = [
        Message(kind=k, contents=m) for k, m in messages.items()
    ]
    return backup
Exemplo n.º 4
0
    def test_files(self):
        backup = Backup(submitter_id=self.user1.id,
                        assignment=self.assignment,
                        submit=True)
        message = Message(kind='file_contents',
                          backup=backup,
                          contents={
                              'hog.py': 'def foo():\n    return',
                              'submit': True
                          })
        db.session.add(message)
        db.session.add(backup)
        db.session.commit()

        # submit should not show up
        assert backup.files() == {'hog.py': 'def foo():\n    return'}
Exemplo n.º 5
0
 def _make_assignment(self, uids, assignment):
     # create a submission every 15 minutes
     message_dict = {'file_contents': {'backup.py': '1'}, 'analytics': {}}
     time = assignment.due_date
     for _ in range(20):
         for user_id in uids:
             time -= datetime.timedelta(minutes=15)
             backup = Backup(submitter_id=user_id,
                             assignment=assignment,
                             submit=True)
             messages = [
                 Message(kind=k, backup=backup, contents=m)
                 for k, m in message_dict.items()
             ]
             db.session.add_all(messages)
             db.session.add(backup)
     db.session.commit()
Exemplo n.º 6
0
def submit_assignment(name):
    assign = get_assignment(name)
    group = Group.lookup(current_user, assign)
    user_ids = assign.active_user_ids(current_user.id)
    fs = assign.final_submission(user_ids)

    if not assign.uploads_enabled:
        flash("This assignment cannot be submitted online", 'warning')
        return redirect(url_for('.assignment', name=assign.name))
    if not assign.active:
        flash("It's too late to submit this assignment", 'warning')
        return redirect(url_for('.assignment', name=assign.name))

    form = UploadSubmissionForm()
    if form.validate_on_submit():
        backup = Backup(
            submitter=current_user,
            assignment=assign,
            submit=True,
        )
        if form.upload_files.upload_backup_files(backup):
            db.session.add(backup)
            db.session.commit()
            if assign.autograding_key:
                try:
                    submit_continous(backup)
                except ValueError as e:
                    logger.warning('Web submission did not autograde',
                                   exc_info=True)
                    flash('Did not send to autograder: {}'.format(e),
                          'warning')
            flash('Uploaded submission', 'success')
            return redirect(
                url_for(
                    '.code',
                    name=assign.name,
                    submit=backup.submit,
                    bid=backup.id,
                ))

    return render_template('student/assignment/submit.html',
                           assignment=assign,
                           group=group,
                           course=assign.course,
                           form=form)
Exemplo n.º 7
0
def gen_backup(user, assignment):
    messages = {
        'file_contents': {
            'fizzbuzz.py': modified_file,
            'moby_dick': 'Call me Ishmael.'
        },
        'analytics': {}
    }
    submit = gen_bool(0.1)
    if submit:
        messages['file_contents']['submit'] = ''
    backup = Backup(created=assignment.due_date -
                    datetime.timedelta(seconds=random.randrange(-100000, 100)),
                    submitter_id=user.id,
                    assignment_id=assignment.id,
                    submit=submit)
    backup.messages = [
        Message(kind=k, contents=m) for k, m in messages.items()
    ]
    return backup
Exemplo n.º 8
0
    def _add_file(self, filename, contents):
        self.setup_course()

        email = '*****@*****.**'
        self.login(email)
        self.user = User.lookup(email)

        self.backup = Backup(submitter=self.user,
                             assignment=self.assignment,
                             submit=True)

        self.message = Message(backup=self.backup,
                               contents={
                                   filename: contents,
                                   'submit': True
                               },
                               kind='file_contents')

        db.session.add(self.backup)
        db.session.add(self.message)
        db.session.commit()
Exemplo n.º 9
0
def staff_submit_backup(cid, email, aid):
    courses, current_course = get_courses(cid)
    assign = Assignment.query.filter_by(id=aid, course_id=cid).one_or_none()
    if not assign or not Assignment.can(assign, current_user, 'grade'):
        return abort(404)
    student = User.lookup(email)
    if not student:
        abort(404)
    user_ids = assign.active_user_ids(student.id)
    # TODO: DRY - Unify with student upload code - should just be a function
    form = forms.StaffUploadSubmissionForm()
    if form.validate_on_submit():
        backup = Backup(
            submitter=student,
            creator=current_user,
            assignment=assign,
            submit=True,
            custom_submission_time=form.get_submission_time(assign),
        )
        if form.upload_files.upload_backup_files(backup):
            db.session.add(backup)
            db.session.commit()
            if assign.autograding_key:
                try:
                    autograder.submit_continous(backup)
                except ValueError as e:
                    flash('Did not send to autograder: {}'.format(e),
                          'warning')
            flash('Uploaded submission'.format(backup.hashid), 'success')
            return redirect(url_for('.grading', bid=backup.id))
    return render_template(
        'staff/student/submit.html',
        current_course=current_course,
        courses=courses,
        student=student,
        assignment=assign,
        upload_form=form,
    )
Exemplo n.º 10
0
    def setUp(self):
        """ Add submissions for 3 users. """
        super(TestRevision, self).setUp()
        self.setup_course()

        message_dict = {'file_contents': {'backup.py': '1'}, 'analytics': {}}

        self.active_user_ids = [self.user1.id, self.user2.id, self.user3.id]

        self.assignment.revisions_allowed = True

        time = self.assignment.due_date  # Set to dt.now(), so future subms are late
        for user_id in self.active_user_ids:
            time -= datetime.timedelta(minutes=15)
            backup = Backup(submitter_id=user_id,
                            assignment=self.assignment,
                            submit=True)
            # Revisions are submitted on time.
            backup.created = time
            messages = [
                Message(kind=k, backup=backup, contents=m)
                for k, m in message_dict.items()
            ]
            db.session.add_all(messages)
            db.session.add(backup)

        # Put user 3 in a group with user 4
        Group.invite(self.user3, self.user4, self.assignment)
        group = Group.lookup(self.user3, self.assignment)
        group.accept(self.user4)

        okversion = Version(name="ok-client",
                            current_version="v1.5.0",
                            download_link="http://localhost/ok")
        db.session.add(okversion)

        db.session.commit()
Exemplo n.º 11
0
 def restore_object(self, attrs, instance=None):
     attrs[u'user'] = self.context.get('request').user
     backup = Backup(**attrs)
     if backup.file:
         backup.file.name = backup.name
     return backup
Exemplo n.º 12
0
def submit_assignment(name):
    # TODO: Unify student & staff upload.
    assign = get_assignment(name)
    group = Group.lookup(current_user, assign)
    user_ids = assign.active_user_ids(current_user.id)
    fs = assign.final_submission(user_ids)
    if not assign.uploads_enabled:
        flash("This assignment cannot be submitted online", 'warning')
        return redirect(url_for('.assignment', name=assign.name))

    extension = None  # No need for an extension
    if not assign.active:
        extension = Extension.get_extension(current_user, assign)
        if not extension:
            flash("It's too late to submit this assignment", 'warning')
            return redirect(url_for('.assignment', name=assign.name))

    if request.method == "POST":
        backup = Backup(
            submitter=current_user,
            assignment=assign,
            submit=True,
        )
        assignment = backup.assignment
        if extension:
            backup.custom_submission_time = extension.custom_submission_time

        templates = assignment.files or []
        files = {}

        def extract_file_index(file_ind):
            """ Get the index of of file objects. Used because
            request.files.getlist() does not handle uniquely indexed
            lists.
            >>> extract_file_index('file[12'])
            12
            """
            brace_loc = file_ind.find('[')
            index_str = file_ind[brace_loc + 1:-1]
            return int(index_str)

        # A list of one element lists
        sorted_uploads = sorted(list(request.files.items()),
                                key=lambda x: extract_file_index(x[0]))
        uploads = [v[1] for v in sorted_uploads]
        full_path_names = list(request.form.listvalues())[0]

        template_files = assign.files or []
        file_names = [os.path.split(f)[1] for f in full_path_names]
        missing = [t for t in template_files if t not in file_names]
        if missing:
            return jsonify({
                'error':
                ('Missing files: {}. The following files are required: {}'.
                 format(', '.join(missing), ', '.join(template_files)))
            }), 400

        backup_folder_postfix = time.time()

        for full_path, upload in zip(full_path_names, uploads):
            data = upload.read()
            if len(data
                   ) > MAX_UPLOAD_FILE_SIZE:  # file is too large (over 25 MB)
                return jsonify({
                    'error':
                    ('{} is larger than the maximum file size of {} MB'.format(
                        full_path, MAX_UPLOAD_FILE_SIZE / 1024 / 1024))
                }), 400
            try:
                files[full_path] = str(data, 'utf-8')
            except UnicodeDecodeError:
                upload.stream.seek(
                    0)  # We've already read data, so reset before uploading
                dest_folder = "uploads/{}/{}/{}/".format(
                    assign.name, current_user.id, backup_folder_postfix)
                bin_file = ExternalFile.upload(upload.stream,
                                               current_user.id,
                                               full_path,
                                               staff_file=False,
                                               prefix=dest_folder,
                                               course_id=assign.course.id,
                                               backup=backup,
                                               assignment_id=assign.id)
                db.session.add(bin_file)

        message = Message(kind='file_contents', contents=files)
        backup.messages.append(message)

        db.session.add(backup)
        db.session.commit()

        # Send to continuous autograder
        if assign.autograding_key and assign.continuous_autograding:
            try:
                submit_continuous(backup)
            except ValueError as e:
                flash('Did not send to autograder: {}'.format(e), 'warning')

        return jsonify({
            'backup':
            backup.hashid,
            'url':
            url_for('.code',
                    name=assign.name,
                    submit=backup.submit,
                    bid=backup.id)
        })

    return render_template('student/assignment/submit.html',
                           assignment=assign,
                           group=group,
                           course=assign.course)