-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Slip Calculator Jobs for Assignment and Course #1148
base: master
Are you sure you want to change the base?
Changes from 1 commit
b7d01a5
9f0fe75
d6cbe8c
5d5e6a9
82c50fa
a10376a
8ef25c9
28d916d
4073666
ddd9e40
0fab8ba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,8 @@ | |
import csv | ||
|
||
from server import jobs | ||
from server.models import Assignment | ||
from server.models import Assignment, ExternalFile | ||
from server.utils import encode_id, local_time, output_csv_iterable | ||
from server.constants import TIMESCALES | ||
|
||
timescales = {'days':86400, 'hours':3600, 'minutes':60} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should go in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did this originally, but realized if I would then have to use the dictionary keys to fill in the form options, which wouldn't have a guaranteed ordering. Now that I've thought about it, I think I'll just use an OrderedDict to preserve the ordering of the keys for display on the form. |
||
|
@@ -13,21 +14,15 @@ def timediff(created, deadline, timescale): | |
secs_over = (created - deadline).total_seconds() | ||
return math.ceil(secs_over / timescales[timescale.lower()]) | ||
|
||
def csv_data(header, rows): | ||
output = io.StringIO() | ||
writer = csv.writer(output, quoting=csv.QUOTE_NONNUMERIC) | ||
writer.writerow(header) | ||
[writer.writerow(row) for row in rows] | ||
return output.getvalue() | ||
|
||
@jobs.background_job | ||
def calculate_slips(assign_id, timescale): | ||
def calculate_slips(assign_id, timescale, show_results): | ||
logger = jobs.get_job_logger() | ||
job = jobs.get_current_job() | ||
|
||
logger.info('Calculating Slip {}...'.format(timescale.title())) | ||
|
||
assignment = Assignment.query.get(assign_id) | ||
course = assignment.course | ||
subms = assignment.course_submissions(include_empty=False) | ||
deadline = assignment.due_date | ||
|
||
|
@@ -39,12 +34,25 @@ def get_row(subm): | |
|
||
header = ('User Email', 'Slip {} Used'.format(timescale.title())) | ||
rows = (get_row(subm) for subm in subms) | ||
data = csv_data(header, rows) | ||
|
||
logger.info(repr(data)) | ||
|
||
# upload = ExternalFile.upload(csv_data, user_id=1, course_id=1, | ||
# name='temp.okfile', prefix='jobs/example/') | ||
|
||
logger.info('Outputting csv...\n') | ||
csv_iterable = output_csv_iterable(header, rows) | ||
|
||
logger.info('Uploading...') | ||
created_time = local_time(dt.now(), course, fmt='%m-%d-%I-%M-%p') | ||
csv_name = '{}_{}.csv'.format(assignment.name.replace('/', '-'), created_time) | ||
upload = ExternalFile.upload(csv_iterable, | ||
user_id=job.user.id, course_id=course.id, name=csv_name, | ||
prefix='jobs/slips/{}'.format(course.offering)) | ||
logger.info('Saved as: {}'.format(upload.object_name)) | ||
|
||
download_link = "/files/{}".format(encode_id(upload.id)) | ||
logger.info('Download link: {} (see "result" above)\n'.format(download_link)) | ||
|
||
if show_results: | ||
logger.info('Results:\n') | ||
csv_data = ''.join([row.decode('utf-8') for row in csv_iterable]) | ||
logger.info(csv_data) | ||
|
||
return download_link | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -236,6 +236,16 @@ def chunks(l, n): | |
prev_index = index | ||
|
||
|
||
def output_csv_iterable(header, rows): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is too similar to Instead, try to use
where |
||
""" Generate csv string for given header list and list of rows (lists). """ | ||
output = StringIO() | ||
writer = csv.writer(output, quoting=csv.QUOTE_NONNUMERIC) | ||
writer.writerow(header) | ||
[writer.writerow(row) for row in rows] | ||
rows = output.getvalue().split('\r\n') | ||
return [bytes(row + '\r\n', 'utf-8') for row in rows] | ||
|
||
|
||
def generate_csv(query, items, selector_fn): | ||
""" Generate csv export of scores for assignment. | ||
selector_fn: 1 arg function that returns a list of dictionaries | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is useful as an option. We should either always show the results, or don't