-
Notifications
You must be signed in to change notification settings - Fork 4
/
submission.py
executable file
·105 lines (86 loc) · 3.62 KB
/
submission.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from urllib.parse import urlencode
from urllib.request import urlopen
import pickle
import json
from collections import OrderedDict
import numpy as np
import os
class SubmissionBase:
submit_url = 'https://www-origin.coursera.org/api/' \
'onDemandProgrammingImmediateFormSubmissions.v1'
save_file = 'token.pkl'
def __init__(self, assignment_slug, part_names):
self.assignment_slug = assignment_slug
self.part_names = part_names
self.login = None
self.token = None
self.functions = OrderedDict()
self.args = dict()
def grade(self):
print('\nSubmitting Solutions | Programming Exercise %s\n' % self.assignment_slug)
self.login_prompt()
# Evaluate the different parts of exercise
parts = OrderedDict()
for part_id, result in self:
parts[str(part_id)] = {'output': sprintf('%0.5f ', result)}
result, response = self.request(parts)
response = json.loads(response.decode("utf-8"))
# if an error was returned, print it and stop
if 'errorMessage' in response:
print(response['errorMessage'])
return
# Print the grading table
print('%43s | %9s | %-s' % ('Part Name', 'Score', 'Feedback'))
print('%43s | %9s | %-s' % ('---------', '-----', '--------'))
for part in parts:
part_feedback = response['partFeedbacks'][part]
part_evaluation = response['partEvaluations'][part]
score = '%d / %3d' % (part_evaluation['score'], part_evaluation['maxScore'])
print('%43s | %9s | %-s' % (self.part_names[int(part) - 1], score, part_feedback))
evaluation = response['evaluation']
total_score = '%d / %d' % (evaluation['score'], evaluation['maxScore'])
print(' --------------------------------')
print('%43s | %9s | %-s\n' % (' ', total_score, ' '))
def login_prompt(self):
if os.path.isfile(self.save_file):
with open(self.save_file, 'rb') as f:
login, token = pickle.load(f)
reenter = input('Use token from last successful submission (%s)? (Y/n): ' % login)
if reenter == '' or reenter[0] == 'Y' or reenter[0] == 'y':
self.login, self.token = login, token
return
else:
os.remove(self.save_file)
self.login = input('Login (email address): ')
self.token = input('Token: ')
# Save the entered credentials
if not os.path.isfile(self.save_file):
with open(self.save_file, 'wb') as f:
pickle.dump((self.login, self.token), f)
def request(self, parts):
params = {
'assignmentSlug': self.assignment_slug,
'secret': self.token,
'parts': parts,
'submitterEmail': self.login}
params = urlencode({'jsonBody': json.dumps(params)}).encode("utf-8")
f = urlopen(self.submit_url, params)
try:
return 0, f.read()
finally:
f.close()
def __iter__(self):
for part_id in self.functions:
yield part_id
def __setitem__(self, key, value):
self.functions[key] = value
def sprintf(fmt, arg):
""" Emulates (part of) Octave sprintf function. """
if isinstance(arg, tuple):
# for multiple return values, only use the first one
arg = arg[0]
if isinstance(arg, (np.ndarray, list)):
# concatenates all elements, column by column
return ' '.join(fmt % e for e in np.asarray(arg).ravel('F'))
else:
return fmt % arg