-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathPythonGrader.py
119 lines (90 loc) · 3.41 KB
/
PythonGrader.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
import BaseHTTPServer
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import threading
import json
import os
import subprocess
import re
import time
import random
import gc
# Random file name generator
def randgen():
return str(random.random()).split('.')[-1]+'_'+str('%.6f' % time.time()).split('.')[-1]
class Handler(BaseHTTPRequestHandler):
def do_HEAD(self):
pass
def do_GET(self):
pass
def do_POST(self):
body_len = int(self.headers.getheader('content-length', 0))
body_content = self.rfile.read(body_len)
problem_name, student_response = get_info(body_content)
result = grade(problem_name, student_response)
self.send_response(200)
self.end_headers()
self.wfile.write(result)
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
""" This class allows to handle requests in separated threads.
No further content needed, don't touch this. """
class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_POST(self):
body_len = int(self.headers.getheader('content-length', 0))
body_content = self.rfile.read(body_len)
problem_name, student_response = get_info(body_content)
result = grade(problem_name, student_response)
self.send_response(200)
self.end_headers()
self.wfile.write(result)
def grade(problem_name, student_response):
randfilename = randgen()
# Create python file to be tested from student's submitted program
program_name = "Program{0}_{1}.py".format(problem_name['problem_name'], randfilename)
source_file = open(program_name, 'w')
source_file.write(student_response)
source_file.close()
correct = True
message = "Good job!!!"
# Use pytest to test the student's submitted program with the help of the appropriate test runner
p = subprocess.Popen(["py.test", "{0}_test_runner.py".format(problem_name['problem_name']), program_name, "-v"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
# print "Out is: >>>\n{0}\n<<<".format(out)
# print "Err is: >>>\n{0}\n<<<".format(err)
if 'FAILED' in out or '= ERRORS =' in out:
correct = False
message = 'Test Failed'
if err:
correct = None
message = 'There was a problem with the testing'
result = {}
result.update({"correct": correct, "msg": message,})
result = process_result(result)
#remove student's program from disk
os.remove(program_name)
#garbage collect
gc.collect()
return result
def process_result(result):
correct = result["correct"]
message = result["msg"]
if not correct:
score = None
elif (correct == True):
score = 1
else:
score = 0
result = {}
result.update({"correct": correct, "score": score, "msg": message })
result = json.dumps(result)
return result
def get_info(body_content):
json_object = json.loads(body_content)
json_object = json.loads(json_object["xqueue_body"])
problem_name = json.loads(json_object["grader_payload"])
student_response = json_object["student_response"]
return problem_name, student_response
if __name__ == '__main__':
server = ThreadedHTTPServer(('localhost', 1710), Handler)
print 'Starting server on port 1710...'
server.serve_forever()