icp/oer/exercise-formats/program/scriptgrade/controller.py

113 lines
2.7 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Standardized types do not require authors to specify any control script as
# it can be generated on import. However when provided it will overwrite the
# default behaivior.
import sys
import subprocess
import re
import time
def build(ctx):
# Add filenames
allArgs = ['/usr/bin/make']
#, self.sourcefile, "-o", "%s.exe" % self.sourcefile]
# start subprocess in with work_path as cwd
p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path)
msgs,errs = p.communicate()
retval = p.wait()
errs = errs.decode("utf-8")
msgs = msgs.decode("utf-8")
return retval, errs, msgs
def execute(ctx):
allArgs = ['/usr/bin/make', 'execute']
allArgs = ['./execute.sh']
# start subprocess in with work_path as cwd
p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path)
timeout = 1
poll_period = 0.1
p.poll()
while p.returncode is None and timeout > 0:
time.sleep(poll_period)
timeout -= poll_period
p.poll()
if timeout <= 0:
p.kill() # timed out
msgs,errs = p.communicate()
retval = p.wait()
errs = errs.decode("utf-8")
msgs = msgs.decode("utf-8")
return retval, errs, msgs
def grade(ctx):
#print("GRADING!!", file=sys.stderr)
# if build failed, return early and set grade to FAIL
if ctx.build_result[0] != 0:
return 'FAIL'
print(ctx.execute_result, file=sys.stderr)
allArgs = ['/usr/bin/make', 'execute']
allArgs = ['./test.sh']
# start subprocess in with work_path as cwd
p = subprocess.Popen(allArgs, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=ctx.work_path)
timeout = 1
poll_period = 0.1
p.poll()
while p.returncode is None and timeout > 0:
time.sleep(poll_period)
timeout -= poll_period
p.poll()
if timeout <= 0:
p.kill() # timed out
msgs,errs = p.communicate()
retval = p.wait()
errs = errs.decode("utf-8")
msgs = msgs.decode("utf-8")
ctx.execute_result = (retval, errs, msgs)
print(ctx.execute_result, file=sys.stderr)
if re.match('FAIL', msgs, re.MULTILINE) != None:
return 'FAIL'
else:
return 'PASS'
def response(ctx):
output = ""
print(ctx.build_result, file=sys.stderr)
print(ctx.execute_result, file=sys.stderr)
print(ctx.grade_result, file=sys.stderr)
if ctx.build_result[0] != 0:
output = ctx.build_result[1]
else:
output = ctx.execute_result[2]
grade = ctx.grade_result
msg = ""
return {'output': output, 'grade': grade, 'msg': msg, 'data': None}