Пример #1
0
    def test_time(self):
        self.setup_course()
        # UTC Time
        time = dt.datetime(month=1, day=20, year=2016, hour=12, minute=1)
        self.assertEquals(utils.local_time(time, self.course), 'Wed 01/20 04:01 AM')

        # DT Aware
        pacific = pytz.timezone('US/Pacific')
        localized = pacific.localize(time)
        self.assertEquals(utils.local_time(localized, self.course), 'Wed 01/20 12:01 PM')

        eastern = pytz.timezone('US/Eastern')
        localized = eastern.localize(time)
        self.assertEquals(utils.local_time(localized, self.course), 'Wed 01/20 09:01 AM')
Пример #2
0
    def test_time(self):
        self.setup_course()
        # UTC Time
        time = dt.datetime(month=1, day=20, year=2016, hour=12, minute=1)
        self.assertEquals(utils.local_time(time, self.course), 'Wed 01/20 04:01 AM')

        # DT Aware
        pacific = pytz.timezone('US/Pacific')
        localized = pacific.localize(time)
        self.assertEquals(utils.local_time(localized, self.course), 'Wed 01/20 12:01 PM')

        eastern = pytz.timezone('US/Eastern')
        localized = eastern.localize(time)
        self.assertEquals(utils.local_time(localized, self.course), 'Wed 01/20 09:01 AM')
Пример #3
0
def write_final_submission(zf, logger, assignment, student, seen, anonymize):
    """ Get the final submission STUDENT and write it into the zipfile ZF. """
    student_user = student.user
    stats = assignment.user_status(student_user)
    backup = stats.final_subm
    if not backup:
        return
    if stats.group:
        group_emails = [User.email_by_id(m.user_id) for m in stats.group.members]
    else:
        group_emails = [student_user.email]

    group_str = '-'.join(sorted(group_emails))
    if group_str in seen:
        return
    seen.add(group_str)

    course = assignment.course
    files = backup.files()

    if anonymize:
        for email in group_emails:
            if pii_present(files, email, assignment.course, logger):
                return
        identifier = '-'.join(sorted([student_hash(e) for e in group_emails]))
        folder = "{}/{}/".format(assignment.name.replace('/', '-'), identifier)
    else:
        folder = "{}/{}/{}".format(assignment.name.replace('/', '-'),
                                   group_str, backup.hashid)
        dump_info = {
            'group': group_emails,
            'scores': [s.export for s in stats.scores],
            'submitter': User.email_by_id(backup.submitter_id),
            'subm_time_local': local_time(stats.subm_time, course)
        }
        if backup.custom_submission_time:
            dump_info['custom_time_local'] = local_time(backup.custom_submission_time,
                                                        course)

        zf.writestr("{}/info.json".format(folder), json.dumps(dump_info))

    for name, contents in files.items():
        # Write the file to the in-memory zip
        zf.writestr("{}/{}".format(folder, name), contents)
Пример #4
0
def export_grades():
    logger = jobs.get_job_logger()
    current_user = jobs.get_current_job().user
    course = Course.query.get(jobs.get_current_job().course_id)
    assignments = course.assignments
    students = (Enrollment.query.options(db.joinedload('user')).filter(
        Enrollment.role == STUDENT_ROLE, Enrollment.course == course).all())

    headers, assignments = get_headers(assignments)
    logger.info("Using these headers:")
    for header in headers:
        logger.info('\t' + header)
    logger.info('')

    total_students = len(students)

    users = [student.user for student in students]
    user_ids = [user.id for user in users]

    all_scores = collect_all_scores(assignments, user_ids)

    with io.StringIO() as f:
        writer = csv.writer(f)
        writer.writerow(headers)  # write headers

        for i, student in enumerate(students, start=1):
            row = export_student_grades(student, assignments, all_scores)
            writer.writerow(row)
            if i % 50 == 0:
                logger.info('Exported {}/{}'.format(i, total_students))
        f.seek(0)
        created_time = local_time(dt.datetime.now(),
                                  course,
                                  fmt='%b-%-d %Y at %I-%M%p')
        csv_filename = '{course_name} Grades ({date}).csv'.format(
            course_name=course.display_name, date=created_time)
        # convert to bytes for csv upload
        csv_bytes = io.BytesIO(bytearray(f.read(), 'utf-8'))
        upload = ExternalFile.upload(csv_bytes,
                                     user_id=current_user.id,
                                     name=csv_filename,
                                     course_id=course.id,
                                     prefix='jobs/exports/{}/'.format(
                                         course.offering))

    logger.info('\nDone!\n')
    logger.info("Saved as: {0}".format(upload.object_name))
    return "/files/{0}".format(encode_id(upload.id))
Пример #5
0
def export_assignment(assignment_id, anonymized):
    """ Generate a zip file of submissions from enrolled students.

    Final Submission: One submission per student/group
        Zip Strucutre: cal-cs61a../[email protected]@b.com/abc12d/hog.py
    Anonymized: Submission without identifying info
        Zip Strucutre: cal-cs61a../{hash}/hog.py
    """
    logger = jobs.get_job_logger()

    assignment = Assignment.query.get(assignment_id)
    requesting_user = jobs.get_current_job().user

    if not assignment:
        logger.warning("No assignment found")
        raise Exception("No Assignment")

    if not Assignment.can(assignment, requesting_user, "download"):
        raise Exception("{} does not have enough permission"
                        .format(requesting_user.email))
    if anonymized:
        logger.info("Starting anonymized submission export")
    else:
        logger.info("Starting final submission export")
    course = assignment.course
    with io.BytesIO() as bio:
        # Get a handle to the in-memory zip in append mode
        with zipfile.ZipFile(bio, "w", zipfile.ZIP_DEFLATED, False) as zf:
            zf.external_attr = 0o655 << 16
            export_loop(bio, zf, logger, assignment, anonymized)
            created_time = local_time(dt.datetime.now(), course, fmt='%m-%d-%I-%M-%p')
            zip_name = '{}_{}.zip'.format(assignment.name.replace('/', '-'), created_time)

        bio.seek(0)
        # Close zf handle to finish writing zipfile
        logger.info("Uploading...")
        upload = ExternalFile.upload(bio, user_id=requesting_user.id, name=zip_name,
                                     course_id=course.id,
                                     prefix='jobs/exports/{}/'.format(course.offering))

    logger.info("Saved as: {0}".format(upload.object_name))
    msg = "/files/{0}".format(encode_id(upload.id))
    return msg
Пример #6
0
 def generate_csv():
     """ Generate csv export of scores for assignment.
     Num Queries: ~2N queries for N scores.
     """
     # Yield Column Info as first row
     yield ','.join(items) + '\n'
     for score in query:
         csv_file = StringIO()
         csv_writer = csv.DictWriter(csv_file, fieldnames=items)
         submitters = score.backup.enrollment_info()
         group = [s.user.email for s in submitters]
         time_str = utils.local_time(score.backup.created, current_course)
         for submitter in submitters:
             data = {'email': submitter.user.email,
                     'time': time_str,
                     'is_late': score.backup.is_late,
                     'group': group}
             data.update(submitter.export)
             data.update(score.export)
             csv_writer.writerow(data)
         yield csv_file.getvalue()
Пример #7
0
 def generate_csv():
     """ Generate csv export of scores for assignment.
     Num Queries: ~2N queries for N scores.
     """
     # Yield Column Info as first row
     yield ','.join(items) + '\n'
     for score in query:
         csv_file = StringIO()
         csv_writer = csv.DictWriter(csv_file, fieldnames=items)
         submitters = score.backup.enrollment_info()
         group = [s.user.email for s in submitters]
         time_str = utils.local_time(score.backup.created, course)
         for submitter in submitters:
             data = {'email': submitter.user.email,
                     'time': time_str,
                     'is_late': score.backup.is_late,
                     'group': group}
             data.update(submitter.export)
             data.update(score.export)
             csv_writer.writerow(data)
         yield csv_file.getvalue()
Пример #8
0
def export_grades():
    logger = jobs.get_job_logger()
    current_user = jobs.get_current_job().user
    course = Course.query.get(jobs.get_current_job().course_id)
    assignments = course.assignments
    students = (Enrollment.query
      .options(db.joinedload('user'))
      .filter(Enrollment.role == STUDENT_ROLE, Enrollment.course == course)
      .all())

    headers, assignments = get_headers(assignments)
    logger.info("Using these headers:")
    for header in headers:
        logger.info('\t' + header)
    logger.info('')

    total_students = len(students)
    with io.StringIO() as f:
        writer = csv.writer(f)
        writer.writerow(headers) # write headers

        for i, student in enumerate(students, start=1):
            row = export_student_grades(student, assignments)
            writer.writerow(row)
            if i % 50 == 0:
                logger.info('Exported {}/{}'.format(i, total_students))
        f.seek(0)
        created_time = local_time(dt.datetime.now(), course, fmt='%b-%-d %Y at %I-%M%p')
        csv_filename = '{course_name} Grades ({date}).csv'.format(
                course_name=course.display_name, date=created_time)
        # convert to bytes for csv upload
        csv_bytes = io.BytesIO(bytearray(f.read(), 'utf-8'))
        upload = ExternalFile.upload(csv_bytes, user_id=current_user.id, name=csv_filename,
                         course_id=course.id,
                         prefix='jobs/exports/{}/'.format(course.offering))

    logger.info('\nDone!\n')
    logger.info("Saved as: {0}".format(upload.object_name))
    return "/files/{0}".format(encode_id(upload.id))