-
Notifications
You must be signed in to change notification settings - Fork 1
/
submission.py
executable file
·106 lines (88 loc) · 3.67 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
106
from urllib.parse import urlencode
from urllib.request import urlopen
import pickle
import json
from collections import OrderedDict
import numpy as np
import os
import ssl
class Submission:
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")
gcontext = ssl.SSLContext()
f = urlopen(self.submit_url, params, context=gcontext)
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