diff options
-rw-r--r-- | yaksh/code_evaluator.py | 38 | ||||
-rw-r--r-- | yaksh/cpp_code_evaluator.py | 31 | ||||
-rw-r--r-- | yaksh/java_code_evaluator.py | 29 | ||||
-rw-r--r-- | yaksh/python_assertion_evaluator.py | 14 | ||||
-rw-r--r-- | yaksh/python_stdout_evaluator.py | 4 | ||||
-rw-r--r-- | yaksh/scilab_code_evaluator.py | 91 |
6 files changed, 123 insertions, 84 deletions
diff --git a/yaksh/code_evaluator.py b/yaksh/code_evaluator.py index 180d719..b7a523c 100644 --- a/yaksh/code_evaluator.py +++ b/yaksh/code_evaluator.py @@ -127,7 +127,7 @@ class CodeEvaluator(object): # success, err = self.check_code(*args) # success, err = self.check_code(**kwargs) #@@@v2 for test_case in test_case_data: - self.compile_user_answer(user_answer, **test_case) + self.compile_code(user_answer, **test_case) success, err = self.check_code(user_answer, **test_case) if not success: break @@ -150,7 +150,7 @@ class CodeEvaluator(object): def check_code(self): raise NotImplementedError("check_code method not implemented") - def compile_user_answer(self, user_answer, **kwargs): + def compile_code(self, user_answer, **kwargs): pass def create_submit_code_file(self, file_name): @@ -198,23 +198,23 @@ class CodeEvaluator(object): raise return proc, stdout, stderr - def _compile_command(self, cmd, *args, **kw): - """Compiles C/C++/java code and returns errors if any. - Run a command in a subprocess while blocking, the process is killed - if it takes more than 2 seconds to run. Return the Popen object, the - stderr. - """ - try: - proc_compile = subprocess.Popen(cmd, shell=True, stdin=None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out, err = proc_compile.communicate() - except TimeoutException: - # Runaway code, so kill it. - proc_compile.kill() - # Re-raise exception. - raise - return proc_compile, err + # def _compile_command(self, cmd, *args, **kw): + # """Compiles C/C++/java code and returns errors if any. + # Run a command in a subprocess while blocking, the process is killed + # if it takes more than 2 seconds to run. Return the Popen object, the + # stderr. + # """ + # try: + # proc_compile = subprocess.Popen(cmd, shell=True, stdin=None, + # stdout=subprocess.PIPE, + # stderr=subprocess.PIPE) + # out, err = proc_compile.communicate() + # except TimeoutException: + # # Runaway code, so kill it. + # proc_compile.kill() + # # Re-raise exception. + # raise + # return proc_compile, err def _change_dir(self, in_dir): if in_dir is not None and isdir(in_dir): diff --git a/yaksh/cpp_code_evaluator.py b/yaksh/cpp_code_evaluator.py index 250de8e..312467d 100644 --- a/yaksh/cpp_code_evaluator.py +++ b/yaksh/cpp_code_evaluator.py @@ -15,6 +15,8 @@ class CppCodeEvaluator(CodeEvaluator): def setup(self): super(CppCodeEvaluator, self).setup() self.submit_code_path = self.create_submit_code_file('submit.c') + self.compiled_user_answer = None + self.compiled_test_code = None def teardown(self): super(CppCodeEvaluator, self).teardown() @@ -37,7 +39,7 @@ class CppCodeEvaluator(CodeEvaluator): return compile_command, compile_main def compile_code(self, user_answer, test_case): - if hasattr(self, 'compiled_output'): + if self.compiled_user_answer and self.compiled_test_code: return None else: ref_code_path = test_case @@ -51,8 +53,19 @@ class CppCodeEvaluator(CodeEvaluator): self.write_to_submit_code_file(self.submit_code_path, user_answer) self.user_output_path, self.ref_output_path = self.set_file_paths() self.compile_command, self.compile_main = self.get_commands(clean_ref_code_path, self.user_output_path, self.ref_output_path) - self.compiled_output = self._compile_command(self.compile_command) - return self.compiled_output + # self.compiled_output = self._compile_command(self.compile_command) + self.compiled_user_answer = self._run_command(self.compile_command, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + self.compiled_test_code = self._run_command(self.compile_main, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + + return self.compiled_user_answer, self.compiled_test_code def check_code(self, user_answer, test_case): """ Function validates student code using instructor code as @@ -89,17 +102,19 @@ class CppCodeEvaluator(CodeEvaluator): # ret = self._compile_command(compile_command) # proc, stdnt_stderr = ret # stdnt_stderr = self._remove_null_substitute_char(stdnt_stderr) - success = False - proc, stdnt_stderr = self.compiled_output + proc, stdnt_out, stdnt_stderr = self.compiled_user_answer stdnt_stderr = self._remove_null_substitute_char(stdnt_stderr) - # Only if compilation is successful, the program is executed # And tested with testcases if stdnt_stderr == '': - ret = self._compile_command(self.compile_main) - proc, main_err = ret + # ret = self._compile_command(self.compile_main) + # ret = self._run_command(self.compile_main, + # shell=True, + # stdout=subprocess.PIPE, + # stderr=subprocess.PIPE) + proc, main_out, main_err = self.compiled_test_code main_err = self._remove_null_substitute_char(main_err) if main_err == '': diff --git a/yaksh/java_code_evaluator.py b/yaksh/java_code_evaluator.py index 167981b..9ec4209 100644 --- a/yaksh/java_code_evaluator.py +++ b/yaksh/java_code_evaluator.py @@ -15,6 +15,8 @@ class JavaCodeEvaluator(CodeEvaluator): def setup(self): super(JavaCodeEvaluator, self).setup() self.submit_code_path = self.create_submit_code_file('Test.java') + self.compiled_user_answer = None + self.compiled_test_code = None def teardown(self): super(JavaCodeEvaluator, self).teardown() @@ -34,7 +36,7 @@ class JavaCodeEvaluator(CodeEvaluator): return output_path def compile_code(self, user_answer, test_case): - if hasattr(self, 'compiled_output'): + if self.compiled_user_answer and self.compiled_test_code: return None else: ref_code_path = test_case @@ -59,8 +61,18 @@ class JavaCodeEvaluator(CodeEvaluator): compile_command, self.compile_main = self.get_commands(clean_ref_code_path, user_code_directory) self.run_command_args = "java -cp {0} {1}".format(user_code_directory, ref_file_name) - self.compiled_output = self._compile_command(compile_command) - return self.compiled_output + # self.compiled_output = self._compile_command(compile_command) + self.compiled_user_answer = self._run_command(compile_command, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + self.compiled_test_code = self._run_command(self.compile_main, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + return self.compiled_user_answer, self.compiled_test_code def check_code(self, user_answer, test_case): """ Function validates student code using instructor code as @@ -108,14 +120,19 @@ class JavaCodeEvaluator(CodeEvaluator): # ret = self._compile_command(compile_command) # proc, stdnt_stderr = ret success = False - proc, stdnt_stderr = self.compiled_output + proc, stdnt_out, stdnt_stderr = self.compiled_user_answer stdnt_stderr = self._remove_null_substitute_char(stdnt_stderr) # Only if compilation is successful, the program is executed # And tested with testcases if stdnt_stderr == '': - ret = self._compile_command(self.compile_main) - proc, main_err = ret + # ret = self._compile_command(self.compile_main) + # ret = self._run_command(self.compile_main, + # shell=True, + # stdout=subprocess.PIPE, + # stderr=subprocess.PIPE) + + proc, main_out, main_err = self.compiled_test_code main_err = self._remove_null_substitute_char(main_err) if main_err == '': diff --git a/yaksh/python_assertion_evaluator.py b/yaksh/python_assertion_evaluator.py index c6661d1..82b5912 100644 --- a/yaksh/python_assertion_evaluator.py +++ b/yaksh/python_assertion_evaluator.py @@ -12,14 +12,18 @@ from code_evaluator import CodeEvaluator, TimeoutException class PythonAssertionEvaluator(CodeEvaluator): """Tests the Python code obtained from Code Server""" + def setup(self): + super(PythonAssertionEvaluator, self).setup() + self.exec_scope = None + def compile_code(self, user_answer, test_case): - if hasattr(self, 'g'): + if self.exec_scope: return None else: submitted = compile(user_answer, '<string>', mode='exec') - self.g = {} - exec submitted in self.g - return self.g + self.exec_scope = {} + exec submitted in self.exec_scope + return self.exec_scope # def check_code(self, test, user_answer, ref_code_path): # def check_code(self, user_answer, test_case_data): #@@@v2 @@ -31,7 +35,7 @@ class PythonAssertionEvaluator(CodeEvaluator): # g = {} # exec submitted in g _tests = compile(test_case, '<string>', mode='exec') - exec _tests in self.g + exec _tests in self.exec_scope except AssertionError: type, value, tb = sys.exc_info() info = traceback.extract_tb(tb) diff --git a/yaksh/python_stdout_evaluator.py b/yaksh/python_stdout_evaluator.py index 85efa51..4d89e16 100644 --- a/yaksh/python_stdout_evaluator.py +++ b/yaksh/python_stdout_evaluator.py @@ -31,8 +31,8 @@ class PythonStdoutEvaluator(CodeEvaluator): else: submitted = compile(user_answer, '<string>', mode='exec') with redirect_stdout() as output_buffer: - g = {} - exec submitted in g + exec_scope = {} + exec submitted in exec_scope self.output_value = output_buffer.getvalue() return self.output_value diff --git a/yaksh/scilab_code_evaluator.py b/yaksh/scilab_code_evaluator.py index 87c0e1e..fedfab3 100644 --- a/yaksh/scilab_code_evaluator.py +++ b/yaksh/scilab_code_evaluator.py @@ -33,52 +33,53 @@ class ScilabCodeEvaluator(CodeEvaluator): # Delete the created file. os.remove(self.submit_code_path) - def compile_code(self, user_answer, test_case): - if hasattr(self, 'compiled_output'): - return None - else: - ref_code_path = test_case - clean_ref_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path) - user_answer, terminate_commands = self._remove_scilab_exit(user_answer.lstrip()) - - self.write_to_submit_code_file(self.submit_code_path, user_answer) - # Throw message if there are commmands that terminates scilab - self.add_err = "" - if terminate_commands: - self.add_err = "Please do not use exit, quit and abort commands in your\ - code.\n Otherwise your code will not be evaluated\ - correctly.\n" - - cmd = 'printf "lines(0)\nexec(\'{0}\',2);\nquit();"'.format(clean_ref_path) - cmd += ' | timeout 8 scilab-cli -nb' - self.compiled_output = self._run_command(cmd, - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - return self.compiled_output + # def compile_code(self, user_answer, test_case): + # if hasattr(self, 'compiled_output'): + # return None + # else: + # ref_code_path = test_case + # clean_ref_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path) + # user_answer, terminate_commands = self._remove_scilab_exit(user_answer.lstrip()) + + # self.write_to_submit_code_file(self.submit_code_path, user_answer) + # # Throw message if there are commmands that terminates scilab + # self.add_err = "" + # if terminate_commands: + # self.add_err = "Please do not use exit, quit and abort commands in your\ + # code.\n Otherwise your code will not be evaluated\ + # correctly.\n" + + # cmd = 'printf "lines(0)\nexec(\'{0}\',2);\nquit();"'.format(clean_ref_path) + # cmd += ' | timeout 8 scilab-cli -nb' + # self.compiled_output = self._run_command(cmd, + # shell=True, + # stdout=subprocess.PIPE, + # stderr=subprocess.PIPE) + # return self.compiled_output def check_code(self, user_answer, test_case): - # ref_code_path = test_case - # clean_ref_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path) - # user_answer, terminate_commands = self._remove_scilab_exit(user_answer.lstrip()) + ref_code_path = test_case + clean_ref_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path) + user_answer, terminate_commands = self._remove_scilab_exit(user_answer.lstrip()) - # success = False - # self.write_to_submit_code_file(self.submit_code_path, user_answer) - # # Throw message if there are commmands that terminates scilab - # add_err = "" - # if terminate_commands: - # add_err = "Please do not use exit, quit and abort commands in your\ - # code.\n Otherwise your code will not be evaluated\ - # correctly.\n" - - # cmd = 'printf "lines(0)\nexec(\'{0}\',2);\nquit();"'.format(clean_ref_path) - # cmd += ' | timeout 8 scilab-cli -nb' - # ret = self._run_command(cmd, - # shell=True, - # stdout=subprocess.PIPE, - # stderr=subprocess.PIPE) success = False - proc, stdout, stderr = self.compiled_output + self.write_to_submit_code_file(self.submit_code_path, user_answer) + # Throw message if there are commmands that terminates scilab + add_err = "" + if terminate_commands: + add_err = "Please do not use exit, quit and abort commands in your\ + code.\n Otherwise your code will not be evaluated\ + correctly.\n" + + cmd = 'printf "lines(0)\nexec(\'{0}\',2);\nquit();"'.format(clean_ref_path) + cmd += ' | timeout 8 scilab-cli -nb' + ret = self._run_command(cmd, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + # success = False + # proc, stdout, stderr = self.compiled_output + proc, stdout, stderr = ret # Get only the error. stderr = self._get_error(stdout) @@ -88,9 +89,11 @@ class ScilabCodeEvaluator(CodeEvaluator): if proc.returncode == 5: success, err = True, "Correct answer" else: - err = self.add_err + stdout + # err = self.add_err + stdout + err = add_err + stdout else: - err = self.add_err + stderr + # err = self.add_err + stderr + err = add_err + stderr return success, err |