diff options
Diffstat (limited to 'yaksh')
-rw-r--r-- | yaksh/code_evaluator.py | 11 | ||||
-rw-r--r-- | yaksh/cpp_code_evaluator.py | 57 | ||||
-rw-r--r-- | yaksh/java_code_evaluator.py | 88 | ||||
-rw-r--r-- | yaksh/python_assertion_evaluator.py | 17 | ||||
-rw-r--r-- | yaksh/python_stdout_evaluator.py | 27 | ||||
-rw-r--r-- | yaksh/scilab_code_evaluator.py | 67 |
6 files changed, 183 insertions, 84 deletions
diff --git a/yaksh/code_evaluator.py b/yaksh/code_evaluator.py index 39f0d48..180d719 100644 --- a/yaksh/code_evaluator.py +++ b/yaksh/code_evaluator.py @@ -127,6 +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) success, err = self.check_code(user_answer, **test_case) if not success: break @@ -149,14 +150,8 @@ class CodeEvaluator(object): def check_code(self): raise NotImplementedError("check_code method not implemented") - # def create_submit_code_file(self, file_name): - # """ Write the code (`answer`) to a file and set the file path""" - # submit_f = open(file_name, 'w') - # submit_f.write(self.user_answer.lstrip()) - # submit_f.close() - # submit_path = abspath(submit_f.name) - - # return submit_path + def compile_user_answer(self, user_answer, **kwargs): + pass def create_submit_code_file(self, file_name): """ Set the file path for code (`answer`)""" diff --git a/yaksh/cpp_code_evaluator.py b/yaksh/cpp_code_evaluator.py index 8cdc27c..250de8e 100644 --- a/yaksh/cpp_code_evaluator.py +++ b/yaksh/cpp_code_evaluator.py @@ -19,7 +19,7 @@ class CppCodeEvaluator(CodeEvaluator): def teardown(self): super(CppCodeEvaluator, self).teardown() # Delete the created file. - os.remove(self.submit_code_path) + os.remove(self.submit_code_path) def set_file_paths(self): user_output_path = os.getcwd() + '/output' @@ -36,6 +36,24 @@ class CppCodeEvaluator(CodeEvaluator): ref_output_path) return compile_command, compile_main + def compile_code(self, user_answer, test_case): + if hasattr(self, 'compiled_output'): + return None + else: + ref_code_path = test_case + clean_ref_code_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path) + + if not isfile(clean_ref_code_path): + return False, "No file at %s or Incorrect path" % clean_ref_code_path + if not isfile(self.submit_code_path): + return False, 'No file at %s or Incorrect path' % self.submit_code_path + + 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 + def check_code(self, user_answer, test_case): """ Function validates student code using instructor code as reference.The first argument ref_code_path, is the path to @@ -56,31 +74,36 @@ class CppCodeEvaluator(CodeEvaluator): if the required permissions are not given to the file(s). """ - ref_code_path = test_case - clean_ref_code_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path) - - if not isfile(clean_ref_code_path): - return False, "No file at %s or Incorrect path" % clean_ref_code_path - if not isfile(self.submit_code_path): - return False, 'No file at %s or Incorrect path' % self.submit_code_path + # ref_code_path = test_case + # clean_ref_code_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path) + + # if not isfile(clean_ref_code_path): + # return False, "No file at %s or Incorrect path" % clean_ref_code_path + # if not isfile(self.submit_code_path): + # return False, 'No file at %s or Incorrect path' % self.submit_code_path + + # success = False + # self.write_to_submit_code_file(self.submit_code_path, user_answer) + # user_output_path, ref_output_path = self.set_file_paths() + # compile_command, compile_main = self.get_commands(clean_ref_code_path, user_output_path, ref_output_path) + # ret = self._compile_command(compile_command) + # proc, stdnt_stderr = ret + # stdnt_stderr = self._remove_null_substitute_char(stdnt_stderr) success = False - self.write_to_submit_code_file(self.submit_code_path, user_answer) - user_output_path, ref_output_path = self.set_file_paths() - compile_command, compile_main = self.get_commands(clean_ref_code_path, user_output_path, ref_output_path) - ret = self._compile_command(compile_command) - proc, stdnt_stderr = ret + proc, stdnt_stderr = self.compiled_output 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(compile_main) + ret = self._compile_command(self.compile_main) proc, main_err = ret main_err = self._remove_null_substitute_char(main_err) if main_err == '': - ret = self._run_command([ref_output_path], stdin=None, + ret = self._run_command([self.ref_output_path], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) proc, stdout, stderr = ret @@ -88,7 +111,7 @@ class CppCodeEvaluator(CodeEvaluator): success, err = True, "Correct answer" else: err = stdout + "\n" + stderr - os.remove(ref_output_path) + os.remove(self.ref_output_path) else: err = "Error:" try: @@ -100,7 +123,7 @@ class CppCodeEvaluator(CodeEvaluator): err = err + "\n" + e except: err = err + "\n" + main_err - os.remove(user_output_path) + os.remove(self.user_output_path) else: err = "Compilation Error:" try: diff --git a/yaksh/java_code_evaluator.py b/yaksh/java_code_evaluator.py index b325208..167981b 100644 --- a/yaksh/java_code_evaluator.py +++ b/yaksh/java_code_evaluator.py @@ -29,6 +29,39 @@ class JavaCodeEvaluator(CodeEvaluator): user_code_directory) return compile_command, compile_main + def set_file_paths(self, directory, file_name): + output_path = "{0}{1}.class".format(directory, file_name) + return output_path + + def compile_code(self, user_answer, test_case): + if hasattr(self, 'compiled_output'): + return None + else: + ref_code_path = test_case + clean_ref_code_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path) + + if not isfile(clean_ref_code_path): + return False, "No file at %s or Incorrect path" % clean_ref_code_path + if not isfile(self.submit_code_path): + return False, 'No file at %s or Incorrect path' % self.submit_code_path + + user_code_directory = os.getcwd() + '/' + self.write_to_submit_code_file(self.submit_code_path, user_answer) + ref_file_name = (clean_ref_code_path.split('/')[-1]).split('.')[0] + # user_output_path = "{0}{1}.class".format(user_code_directory, + # 'Test') + # ref_output_path = "{0}{1}.class".format(user_code_directory, + # ref_file_name) + # user_output_path, ref_output_path = self.set_file_paths(user_code_directory, clean_ref_code_path) + self.user_output_path = self.set_file_paths(user_code_directory, 'Test') + self.ref_output_path = self.set_file_paths(user_code_directory, ref_file_name) + + 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 + def check_code(self, user_answer, test_case): """ Function validates student code using instructor code as reference.The first argument ref_code_path, is the path to @@ -49,39 +82,44 @@ class JavaCodeEvaluator(CodeEvaluator): if the required permissions are not given to the file(s). """ - ref_code_path = test_case - clean_ref_code_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path) - - if not isfile(clean_ref_code_path): - return False, "No file at %s or Incorrect path" % clean_ref_code_path - if not isfile(self.submit_code_path): - return False, 'No file at %s or Incorrect path' % self.submit_code_path - + # ref_code_path = test_case + # clean_ref_code_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path) + + # if not isfile(clean_ref_code_path): + # return False, "No file at %s or Incorrect path" % clean_ref_code_path + # if not isfile(self.submit_code_path): + # return False, 'No file at %s or Incorrect path' % self.submit_code_path + + # success = False + # user_code_directory = os.getcwd() + '/' + # self.write_to_submit_code_file(self.submit_code_path, user_answer) + # ref_file_name = (clean_ref_code_path.split('/')[-1]).split('.')[0] + # # user_output_path = "{0}{1}.class".format(user_code_directory, + # # 'Test') + # # ref_output_path = "{0}{1}.class".format(user_code_directory, + # # ref_file_name) + # # user_output_path, ref_output_path = self.set_file_paths(user_code_directory, clean_ref_code_path) + # user_output_path = self.set_file_paths(user_code_directory, 'Test') + # ref_output_path = self.set_file_paths(user_code_directory, ref_file_name) + + # compile_command, compile_main = self.get_commands(clean_ref_code_path, user_code_directory) + # run_command_args = "java -cp {0} {1}".format(user_code_directory, + # ref_file_name) + # ret = self._compile_command(compile_command) + # proc, stdnt_stderr = ret success = False - user_code_directory = os.getcwd() + '/' - self.write_to_submit_code_file(self.submit_code_path, user_answer) - ref_file_name = (clean_ref_code_path.split('/')[-1]).split('.')[0] - user_output_path = "{0}{1}.class".format(user_code_directory, - 'Test') - ref_output_path = "{0}{1}.class".format(user_code_directory, - ref_file_name) - # user_output_path, ref_output_path = self.set_file_paths(user_code_directory, clean_ref_code_path) - compile_command, compile_main = self.get_commands(clean_ref_code_path, user_code_directory) - run_command_args = "java -cp {0} {1}".format(user_code_directory, - ref_file_name) - ret = self._compile_command(compile_command) - proc, stdnt_stderr = ret + proc, stdnt_stderr = self.compiled_output 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(compile_main) + ret = self._compile_command(self.compile_main) proc, main_err = ret main_err = self._remove_null_substitute_char(main_err) if main_err == '': - ret = self._run_command(run_command_args, shell=True, + ret = self._run_command(self.run_command_args, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -90,7 +128,7 @@ class JavaCodeEvaluator(CodeEvaluator): success, err = True, "Correct answer" else: err = stdout + "\n" + stderr - os.remove(ref_output_path) + os.remove(self.ref_output_path) else: err = "Error:" try: @@ -102,7 +140,7 @@ class JavaCodeEvaluator(CodeEvaluator): err = err + "\n" + e except: err = err + "\n" + main_err - os.remove(user_output_path) + os.remove(self.user_output_path) else: err = "Compilation Error:" try: diff --git a/yaksh/python_assertion_evaluator.py b/yaksh/python_assertion_evaluator.py index 15ff8fd..c6661d1 100644 --- a/yaksh/python_assertion_evaluator.py +++ b/yaksh/python_assertion_evaluator.py @@ -12,17 +12,26 @@ from code_evaluator import CodeEvaluator, TimeoutException class PythonAssertionEvaluator(CodeEvaluator): """Tests the Python code obtained from Code Server""" + def compile_code(self, user_answer, test_case): + if hasattr(self, 'g'): + return None + else: + submitted = compile(user_answer, '<string>', mode='exec') + self.g = {} + exec submitted in self.g + return self.g + # def check_code(self, test, user_answer, ref_code_path): # def check_code(self, user_answer, test_case_data): #@@@v2 def check_code(self, user_answer, test_case): success = False try: tb = None - submitted = compile(user_answer, '<string>', mode='exec') - g = {} - exec submitted in g + # submitted = compile(user_answer, '<string>', mode='exec') + # g = {} + # exec submitted in g _tests = compile(test_case, '<string>', mode='exec') - exec _tests in g + exec _tests in self.g 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 9443e37..85efa51 100644 --- a/yaksh/python_stdout_evaluator.py +++ b/yaksh/python_stdout_evaluator.py @@ -25,22 +25,31 @@ def redirect_stdout(): class PythonStdoutEvaluator(CodeEvaluator): """Tests the Python code obtained from Code Server""" + def compile_code(self, user_answer, expected_output): + if hasattr(self, 'output_value'): + return None + else: + submitted = compile(user_answer, '<string>', mode='exec') + with redirect_stdout() as output_buffer: + g = {} + exec submitted in g + self.output_value = output_buffer.getvalue() + return self.output_value + def check_code(self, user_answer, expected_output): success = False tb = None - # expected_output = test_case_data[0] - submitted = compile(user_answer, '<string>', mode='exec') - with redirect_stdout() as output_buffer: - g = {} - exec submitted in g - raw_output_value = output_buffer.getvalue() - # output_value = raw_output_value.encode('string_escape').strip() - output_value = raw_output_value.strip() + # submitted = compile(user_answer, '<string>', mode='exec') + # with redirect_stdout() as output_buffer: + # g = {} + # exec submitted in g + # raw_output_value = output_buffer.getvalue() + # output_value = raw_output_value.strip() if expected_output in user_answer: success = False err = "Incorrect Answer: Please avoid printing the expected output directly" - elif output_value == expected_output: + elif self.output_value == expected_output: success = True err = "Correct answer" diff --git a/yaksh/scilab_code_evaluator.py b/yaksh/scilab_code_evaluator.py index 61642fd..87c0e1e 100644 --- a/yaksh/scilab_code_evaluator.py +++ b/yaksh/scilab_code_evaluator.py @@ -33,27 +33,52 @@ class ScilabCodeEvaluator(CodeEvaluator): # Delete the created file. os.remove(self.submit_code_path) - 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()) + 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()) + + # 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 - 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) - proc, stdout, stderr = ret + proc, stdout, stderr = self.compiled_output # Get only the error. stderr = self._get_error(stdout) @@ -63,9 +88,9 @@ class ScilabCodeEvaluator(CodeEvaluator): if proc.returncode == 5: success, err = True, "Correct answer" else: - err = add_err + stdout + err = self.add_err + stdout else: - err = add_err + stderr + err = self.add_err + stderr return success, err |