-
Notifications
You must be signed in to change notification settings - Fork 8
/
submit.py
177 lines (138 loc) · 6.14 KB
/
submit.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/python3
"""
always produces:
- results, an html fragment to display to the user
- category: "Internal Error"/"Pre-syntax Error"/"Syntax Error"/"Sandbox Limit"/"Runtime Error"/"Failed Tests"/"Passed"
... it should correspond to the exit point from the logic in this script
sometimes produces:
- errmsg, the high-level description of the error (without line numbers)
- epilogue, commentary after a submission
"""
import config, json, cgi, sys, Websheet, re, os
from utils import *
def submit_and_log(websheet_name, student, client_request, meta):
config.meta = meta
websheet = Websheet.Websheet.from_name(websheet_name, client_request['preview']=='True', student)
errmsg = None
epilogue = None
def compile_and_run():
nonlocal errmsg, epilogue
if websheet.nocode:
if websheet.evaluate_nocode_submission(client_request["nocode_state"]):
return ("Passed", "<div>Correct!</div>")
else:
return ("Failed", "<div>Not correct, please try again.</div>")
user_poschunks = client_request["snippets"]
# this is the pre-syntax check
student_solution = websheet.combine_with_template(user_poschunks, "student")
if student_solution[0] == False:
if student_solution[1] == "Internal error! Wrong number of inputs":
return("Internal Error (Wrong number of snippets)", "Error: wrong number of snippets")
errmsg = student_solution[1].split('\n')
if len(errmsg) > 1:
errmsg = errmsg[1]
else:
errmsg = errmsg[0]
return("Pre-syntax Error",
"<div class='pre-syntax-error'>Syntax error:" +
"<pre>\n"+cgi.escape(student_solution[1])+"</pre></div>") # error text
ss_to_ui_linemap = student_solution[2]
def translate_line(ss_lineno):
ss_lineno = int(ss_lineno)
if ss_lineno in ss_to_ui_linemap:
return str(ss_to_ui_linemap[ss_lineno])
else:
return "???("+str(ss_lineno)+")" + "<!--" + json.dumps(ss_to_ui_linemap) + "-->"
reference_solution = websheet.get_reference_solution("reference")
ss = student_solution[1]
for i in range(len(ss)):
if badchar(ss[i]):
return("Pre-syntax Error",
"<div class='pre-syntax-error'>Syntax error:" +
" Your code contains character number " + str(ord(ss[i])) + ":<br>" +
"<pre>"
+("…" if i>5 else "")
+cgi.escape(ss[max(0,i-5):i])
+"<b style='background:orange'>"
+cgi.escape(ss[i])+"</b>"
+cgi.escape(ss[i+1:i+6])
+("…" if i+5<len(ss) else "")
+"</pre></div>")
for verboten in websheet.verboten:
for chunk in user_poschunks:
if verboten in chunk['code']:
return("Pre-syntax Error",
"<div class='pre-syntax-error'>" +
"You can't use " + tt(verboten) +
" in this exercise.</div>")
#print(cgi.escape(student_solution[1]))
#print(cgi.escape(reference_solution))
if websheet.lang.startswith("C++"):
student_solution = student_solution[1]
if websheet.lang == "C++func":
student_solution = re.sub(r"\bmain\b", "__student_main__", student_solution)
if websheet.lang.startswith("C++"):
import grade_cpp
return grade_cpp.grade(reference_solution, student_solution, translate_line, websheet)
elif websheet.lang == "Java":
import grade_java
# java needs to know student name to look up their solutions for dependencies
return grade_java.grade(reference_solution, student_solution, translate_line, websheet, student)
try:
category, results = compile_and_run()
config.uncreate_tempdirs()
except Exception:
category = "Internal Error (Script)"
import traceback
results = '<pre>' + cgi.escape(traceback.format_exc()) + '</pre>'
if category.startswith("Internal Error"):
results = "<b><p>"+category+"; please report to course staff!</p></b>" + results
import copy
print_output = {'category': category, 'results' : results}
save_this = {'category': category}
if errmsg is not None:
print_output['errmsg'] = errmsg
save_this['errmsg'] = errmsg
if category=='Passed' and websheet.epilogue is not None:
print_output['epilogue'] = websheet.epilogue
passed = (category == "Passed")
global authinfo
#print(authinfo)
if authinfo["error_span"] != "":
print_output["results"] = authinfo["error_span"]
print_output["category"] = "Auth Error"
meta["logout_bug"] = True
if (not client_request["viewing_ref"]):
if websheet.nocode:
user_state = client_request["nocode_state"]
else:
# remove positional information
user_state = [blank["code"] for blank in client_request["snippets"]]
config.save_submission(student, websheet.dbslug, user_state, save_this, passed)
if websheet.attempts_until_ref == 'never':
pass
elif websheet.attempts_until_ref == 'infinity':
if passed:
print_output["reference_sol"] = websheet.get_reference_snippets()
else:
if passed or config.num_submissions(student, websheet.dbslug) == websheet.attempts_until_ref:
print_output["reference_sol"] = websheet.get_reference_snippets()
# we can't reliably track # submissions of anonymous users so put trust in the UI
if ('reference_sol' not in print_output and authinfo['username'] == 'anonymous'
and websheet.attempts_until_ref not in ['never', 'infinity']):
print_output["anon_reference_sol"] = websheet.get_reference_snippets()
return print_output
if __name__ == "__main__":
global authinfo
stdin = json.loads(input()) # assume json all on one line
authinfo = stdin["authinfo"]
student = stdin["php_data"]["user"]
websheet_name = stdin["php_data"]["problem"]
meta = stdin["php_data"]["meta"]
if "frontend_user" in stdin["client_request"]:
meta["frontend_user"] = stdin["client_request"]["frontend_user"]
data = submit_and_log(websheet_name, student, stdin["client_request"], meta)
data["authinfo"] = authinfo
print(json.dumps(data,
indent=4, separators=(',', ': '))) # pretty!
sys.exit(0)