diff options
Diffstat (limited to 'testapp/exam')
-rw-r--r-- | testapp/exam/bash_code_evaluator.py | 40 | ||||
-rw-r--r-- | testapp/exam/code_evaluator.py | 83 | ||||
-rwxr-xr-x | testapp/exam/code_server.py | 3 | ||||
-rw-r--r-- | testapp/exam/cpp_code_evaluator.py (renamed from testapp/exam/c_cpp_code_evaluator.py) | 70 | ||||
-rw-r--r-- | testapp/exam/java_code_evaluator.py | 68 | ||||
-rw-r--r-- | testapp/exam/language_registry.py | 21 | ||||
-rw-r--r-- | testapp/exam/models.py | 3 | ||||
-rw-r--r-- | testapp/exam/python_code_evaluator.py | 59 | ||||
-rw-r--r-- | testapp/exam/scilab_code_evaluator.py | 55 | ||||
-rw-r--r-- | testapp/exam/settings.py | 12 | ||||
-rw-r--r-- | testapp/exam/static/exam/js/add_question.js | 10 | ||||
-rw-r--r-- | testapp/exam/templates/exam/add_question.html | 2 | ||||
-rw-r--r-- | testapp/exam/tests.py | 1 | ||||
-rw-r--r-- | testapp/exam/views.py | 16 |
14 files changed, 115 insertions, 328 deletions
diff --git a/testapp/exam/bash_code_evaluator.py b/testapp/exam/bash_code_evaluator.py index 60f0bb3..7fcfb0f 100644 --- a/testapp/exam/bash_code_evaluator.py +++ b/testapp/exam/bash_code_evaluator.py @@ -8,20 +8,20 @@ import importlib # local imports from code_evaluator import CodeEvaluator -# from language_registry import registry class BashCodeEvaluator(CodeEvaluator): """Tests the Bash code obtained from Code Server""" - def __init__(self, test_case_data, language, user_answer, + def __init__(self, test_case_data, test, language, user_answer, ref_code_path=None, in_dir=None): - super(BashCodeEvaluator, self).__init__(test_case_data, language, user_answer, + super(BashCodeEvaluator, self).__init__(test_case_data, test, language, user_answer, ref_code_path, in_dir) self.submit_path = self.create_submit_code_file('submit.sh') - self.test_case_args = self.setup_code_evaluator() + self.test_case_args = self._setup() - def setup_code_evaluator(self): - super(BashCodeEvaluator, self).setup_code_evaluator() + # Private Protocol ########## + def _setup(self): + super(BashCodeEvaluator, self)._setup() self.set_file_as_executable(self.submit_path) get_ref_path, get_test_case_path = self.ref_code_path.strip().split(',') @@ -32,28 +32,12 @@ class BashCodeEvaluator(CodeEvaluator): return ref_path, self.submit_path, test_case_path + def _teardown(self): + # Delete the created file. + super(BashCodeEvaluator, self)._teardown() + os.remove(self.submit_path) - # # Public Protocol ########## - # def evaluate_code(self): - # submit_path = self.create_submit_code_file('submit.sh') - # self.set_file_as_executable(submit_path) - # get_ref_path, get_test_case_path = self.ref_code_path.strip().split(',') - # get_ref_path = get_ref_path.strip() - # get_test_case_path = get_test_case_path.strip() - # ref_path, test_case_path = self.set_test_code_file_path(get_ref_path, - # get_test_case_path) - - # success, err = self._check_bash_script(ref_path, submit_path, - # test_case_path) - - # # Delete the created file. - # os.remove(submit_path) - - # return success, err - - - # Private Protocol ########## - def check_code(self, ref_path, submit_path, + def _check_code(self, ref_path, submit_path, test_case_path=None): """ Function validates student script using instructor script as reference. Test cases can optionally be provided. The first argument @@ -136,5 +120,3 @@ class BashCodeEvaluator(CodeEvaluator): stdnt_stdout+stdnt_stderr) return False, err - -# registry.register('bash', EvaluateBashCode) diff --git a/testapp/exam/code_evaluator.py b/testapp/exam/code_evaluator.py index 3cc7374..1efd519 100644 --- a/testapp/exam/code_evaluator.py +++ b/testapp/exam/code_evaluator.py @@ -54,7 +54,7 @@ def delete_signal_handler(): ############################################################################### class CodeEvaluator(object): """Tests the code obtained from Code Server""" - def __init__(self, test_case_data, language, user_answer, + def __init__(self, test_case_data, test, language, user_answer, ref_code_path=None, in_dir=None): msg = 'Code took more than %s seconds to run. You probably '\ 'have an infinite loop in your code.' % SERVER_TIMEOUT @@ -63,6 +63,7 @@ class CodeEvaluator(object): self.language = language.lower() self.user_answer = user_answer self.ref_code_path = ref_code_path + self.test = test self.in_dir = in_dir self.test_case_args = None @@ -73,60 +74,15 @@ class CodeEvaluator(object): test_case_data = json_data.get("test_case_data") user_answer = json_data.get("user_answer") ref_code_path = json_data.get("ref_code_path") + test = json_data.get("test") - instance = cls(Test_case_data, language, user_answer, ref_code_path, + instance = cls(test_case_data, test, language, user_answer, ref_code_path, in_dir) return instance - # def run_code(self): - # """Tests given code (`answer`) with the test cases based on - # given arguments. - - # The ref_code_path is a path to the reference code. - # The reference code will call the function submitted by the student. - # The reference code will check for the expected output. - - # If the path's start with a "/" then we assume they are absolute paths. - # If not, we assume they are relative paths w.r.t. the location of this - # code_server script. - - # If the optional `in_dir` keyword argument is supplied it changes the - # directory to that directory (it does not change it back to the original - # when done). - - # Returns - # ------- - - # A tuple: (success, error message). - # """ - # self._change_dir(self.in_dir) - - # # Add a new signal handler for the execution of this code. - # prev_handler = self.create_signal_handler() - # success = False - - # # Do whatever testing needed. - # try: - # success, err = self.evaluate_code() #pass *list where list is a list of args obtained from setup - - # except TimeoutException: - # err = self.timeout_msg - # except: - # type, value = sys.exc_info()[:2] - # err = "Error: {0}".format(repr(value)) - # finally: - # # Set back any original signal handler. - # self.set_original_signal_handler(prev_handler) - - # # Cancel the signal - # self.delete_signal_handler() - - # result = {'success': success, 'error': err} - # return result - - def code_evaluator(self): - """Tests given code (`answer`) with the test cases based on - given arguments. + def evaluate(self): + """Evaluates given code with the test cases based on + given arguments in test_case_data. The ref_code_path is a path to the reference code. The reference code will call the function submitted by the student. @@ -146,18 +102,18 @@ class CodeEvaluator(object): A tuple: (success, error message). """ - self.setup_code_evaluator() - success, err = self.evaluate_code(self.test_case_args) - self.teardown_code_evaluator() + self._setup() + success, err = self._evaluate(self.test_case_args) + self._teardown() result = {'success': success, 'error': err} return result - # Public Protocol ########## - def setup_code_evaluator(self): + # Private Protocol ########## + def _setup(self): self._change_dir(self.in_dir) - def evaluate_code(self, args): + def _evaluate(self, args): # Add a new signal handler for the execution of this code. prev_handler = create_signal_handler() success = False @@ -165,7 +121,7 @@ class CodeEvaluator(object): # Do whatever testing needed. try: - success, err = self.check_code(*args) + success, err = self._check_code(*args) except TimeoutException: err = self.timeout_msg @@ -178,14 +134,13 @@ class CodeEvaluator(object): return success, err - def teardown_code_evaluator(self): + def _teardown(self): # Cancel the signal delete_signal_handler() - def check_code(self): + def _check_code(self): raise NotImplementedError("check_code method not implemented") - # Private Protocol ########## 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') @@ -209,7 +164,7 @@ class CodeEvaluator(object): return ref_path, test_case_path - def run_command(self, cmd_args, *args, **kw): + def _run_command(self, cmd_args, *args, **kw): """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 stdout and stderr. @@ -224,7 +179,7 @@ class CodeEvaluator(object): raise return proc, stdout, stderr - def compile_command(self, cmd, *args, **kw): + 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 @@ -246,7 +201,7 @@ class CodeEvaluator(object): if in_dir is not None and isdir(in_dir): os.chdir(in_dir) - def remove_null_substitute_char(self, string): + def _remove_null_substitute_char(self, string): """Returns a string without any null and substitute characters""" stripped = "" for c in string: diff --git a/testapp/exam/code_server.py b/testapp/exam/code_server.py index c621dcd..3dd5072 100755 --- a/testapp/exam/code_server.py +++ b/testapp/exam/code_server.py @@ -29,7 +29,6 @@ from multiprocessing import Process, Queue import subprocess import re import json -import importlib # Local imports. from settings import SERVER_PORTS, SERVER_TIMEOUT, SERVER_POOL_PORT from language_registry import set_registry @@ -71,7 +70,7 @@ class CodeServer(object): """ code_evaluator = self._create_evaluator_instance(language, json_data, in_dir) - result = code_evaluator.code_evaluator() + result = code_evaluator.evaluate() # Put us back into the server pool queue since we are free now. self.queue.put(self.port) diff --git a/testapp/exam/c_cpp_code_evaluator.py b/testapp/exam/cpp_code_evaluator.py index d611f96..04efba8 100644 --- a/testapp/exam/c_cpp_code_evaluator.py +++ b/testapp/exam/cpp_code_evaluator.py @@ -8,21 +8,20 @@ import importlib # local imports from code_evaluator import CodeEvaluator -# from language_registry import registry -class CCppCodeEvaluator(CodeEvaluator): +class CppCodeEvaluator(CodeEvaluator): """Tests the C code obtained from Code Server""" - def __init__(self, test_case_data, language, user_answer, + def __init__(self, test_case_data, test, language, user_answer, ref_code_path=None, in_dir=None): - super(CCppCodeEvaluator, self).__init__(test_case_data, language, user_answer, + super(CppCodeEvaluator, self).__init__(test_case_data, test, language, user_answer, ref_code_path, in_dir) self.submit_path = self.create_submit_code_file('submit.c') - self.test_case_args = self.setup_code_evaluator() + self.test_case_args = self._setup() # Private Protocol ########## - def setup_code_evaluator(self): - super(CCppCodeEvaluator, self).setup_code_evaluator() + def _setup(self): + super(CppCodeEvaluator, self)._setup() get_ref_path = self.ref_code_path ref_path, test_case_path = self.set_test_code_file_path(get_ref_path) @@ -43,42 +42,12 @@ class CCppCodeEvaluator(CodeEvaluator): return ref_path, self.submit_path, compile_command, compile_main, run_command_args, remove_user_output, remove_ref_output - def teardown_code_evaluator(self): + def _teardown(self): # Delete the created file. - super(CCppCodeEvaluator, self).teardown_code_evaluator() + super(CppCodeEvaluator, self)._teardown() os.remove(self.submit_path) - # # Public Protocol ########## - # def evaluate_code(self): - # submit_path = self.create_submit_code_file('submit.c') - # get_ref_path = self.ref_code_path - # ref_path, test_case_path = self.set_test_code_file_path(get_ref_path) - # success = False - - # # Set file paths - # c_user_output_path = os.getcwd() + '/output' - # c_ref_output_path = os.getcwd() + '/executable' - - # # Set command variables - # compile_command = 'g++ {0} -c -o {1}'.format(submit_path, - # c_user_output_path) - # compile_main = 'g++ {0} {1} -o {2}'.format(ref_path, - # c_user_output_path, - # c_ref_output_path) - # run_command_args = [c_ref_output_path] - # remove_user_output = c_user_output_path - # remove_ref_output = c_ref_output_path - - # success, err = self.check_code(ref_path, submit_path, compile_command, - # compile_main, run_command_args, - # remove_user_output, remove_ref_output) - - # # Delete the created file. - # os.remove(submit_path) - - # return success, err - - def check_code(self, ref_code_path, submit_code_path, compile_command, + def _check_code(self, ref_code_path, submit_code_path, compile_command, compile_main, run_command_args, remove_user_output, remove_ref_output): """ Function validates student code using instructor code as @@ -107,21 +76,21 @@ class CCppCodeEvaluator(CodeEvaluator): success = False # output_path = os.getcwd() + '/output' - ret = self.compile_command(compile_command) + ret = self._compile_command(compile_command) proc, stdnt_stderr = ret # if self.language == "java": - stdnt_stderr = self.remove_null_substitute_char(stdnt_stderr) + 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(compile_main) proc, main_err = ret # if self.language == "java": - main_err = self.remove_null_substitute_char(main_err) + main_err = self._remove_null_substitute_char(main_err) if main_err == '': - ret = self.run_command(run_command_args, stdin=None, + ret = self._run_command(run_command_args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) proc, stdout, stderr = ret @@ -155,14 +124,3 @@ class CCppCodeEvaluator(CodeEvaluator): err = err + "\n" + stdnt_stderr return success, err - - def remove_null_substitute_char(self, string): - """Returns a string without any null and substitute characters""" - stripped = "" - for c in string: - if ord(c) is not 26 and ord(c) is not 0: - stripped = stripped + c - return ''.join(stripped) - - -# registry.register('c', EvaluateCCode) diff --git a/testapp/exam/java_code_evaluator.py b/testapp/exam/java_code_evaluator.py index 4a80acd..709a0a1 100644 --- a/testapp/exam/java_code_evaluator.py +++ b/testapp/exam/java_code_evaluator.py @@ -7,23 +7,21 @@ import subprocess import importlib # local imports -# from c_code_evaluator import CCodeEvaluator from code_evaluator import CodeEvaluator -# from language_registry import registry class JavaCodeEvaluator(CodeEvaluator): """Tests the Java code obtained from Code Server""" - def __init__(self, test_case_data, language, user_answer, + def __init__(self, test_case_data, test, language, user_answer, ref_code_path=None, in_dir=None): - super(JavaCodeEvaluator, self).__init__(test_case_data, language, user_answer, + super(JavaCodeEvaluator, self).__init__(test_case_data, test, language, user_answer, ref_code_path, in_dir) self.submit_path = self.create_submit_code_file('Test.java') - self.test_case_args = self.setup_code_evaluator() + self.test_case_args = self._setup() # Private Protocol ########## - def setup_code_evaluator(self): - super(JavaCodeEvaluator, self).setup_code_evaluator() + def _setup(self): + super(JavaCodeEvaluator, self)._setup() ref_path, test_case_path = self.set_test_code_file_path(self.ref_code_path) @@ -32,7 +30,7 @@ class JavaCodeEvaluator(CodeEvaluator): java_ref_file_name = (ref_path.split('/')[-1]).split('.')[0] # Set command variables - compile_command = 'javac {0}'.format(submit_path), + compile_command = 'javac {0}'.format(self.submit_path), compile_main = ('javac {0} -classpath ' '{1} -d {2}').format(ref_path, java_student_directory, @@ -44,47 +42,14 @@ class JavaCodeEvaluator(CodeEvaluator): remove_ref_output = "{0}{1}.class".format(java_student_directory, java_ref_file_name) - return ref_path, submit_path, compile_command, compile_main, run_command_args, remove_user_output, remove_ref_output + return ref_path, self.submit_path, compile_command, compile_main, run_command_args, remove_user_output, remove_ref_output - def teardown_code_evaluator(self): + def _teardown(self): # Delete the created file. - super(JavaCodeEvaluator, self).teardown_code_evaluator() + super(JavaCodeEvaluator, self)._teardown() os.remove(self.submit_path) - - # Public Protocol ########## - # def evaluate_code(self): - # submit_path = self.create_submit_code_file('Test.java') - # ref_path, test_case_path = self.set_test_code_file_path(self.ref_code_path) - # success = False - - # # Set file paths - # java_student_directory = os.getcwd() + '/' - # java_ref_file_name = (ref_path.split('/')[-1]).split('.')[0] - - # # Set command variables - # compile_command = 'javac {0}'.format(submit_path), - # compile_main = ('javac {0} -classpath ' - # '{1} -d {2}').format(ref_path, - # java_student_directory, - # java_student_directory) - # run_command_args = "java -cp {0} {1}".format(java_student_directory, - # java_ref_file_name) - # remove_user_output = "{0}{1}.class".format(java_student_directory, - # 'Test') - # remove_ref_output = "{0}{1}.class".format(java_student_directory, - # java_ref_file_name) - - # success, err = self.check_code(ref_path, submit_path, compile_command, - # compile_main, run_command_args, - # remove_user_output, remove_ref_output) - - # # Delete the created file. - # os.remove(submit_path) - - # return success, err - - def check_code(self, ref_code_path, submit_code_path, compile_command, + def _check_code(self, ref_code_path, submit_code_path, compile_command, compile_main, run_command_args, remove_user_output, remove_ref_output): """ Function validates student code using instructor code as @@ -113,21 +78,21 @@ class JavaCodeEvaluator(CodeEvaluator): success = False # output_path = os.getcwd() + '/output' - ret = self.compile_command(compile_command) + ret = self._compile_command(compile_command) proc, stdnt_stderr = ret # if self.language == "java": - stdnt_stderr = self.remove_null_substitute_char(stdnt_stderr) + 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(compile_main) proc, main_err = ret # if self.language == "java": - main_err = self.remove_null_substitute_char(main_err) + main_err = self._remove_null_substitute_char(main_err) if main_err == '': - ret = self.run_command(run_command_args, stdin=None, + ret = self._run_command(run_command_args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) proc, stdout, stderr = ret @@ -161,6 +126,3 @@ class JavaCodeEvaluator(CodeEvaluator): err = err + "\n" + stdnt_stderr return success, err - - -# registry.register('java', EvaluateJavaCode) diff --git a/testapp/exam/language_registry.py b/testapp/exam/language_registry.py index 8700d32..76a23d7 100644 --- a/testapp/exam/language_registry.py +++ b/testapp/exam/language_registry.py @@ -1,31 +1,36 @@ -from settings import language_register +from settings import code_evaluators +import importlib registry = None def set_registry(): - globals registry = _LanguageRegistry() + global registry + registry = _LanguageRegistry() def get_registry(): return registry class _LanguageRegistry(object): def __init__(self): - for language, module in language_register.iteritems(): + self._register = {} + for language, module in code_evaluators.iteritems(): self._register[language] = None # Public Protocol ########## def get_class(self, language): - if not self._register[language]: - self._register[language] = language_register[language] + """ Get the code evaluator class for the given language """ + if not self._register.get(language): + self._register[language] = code_evaluators.get(language) cls = self._register[language] - module_name, class_name = cls.split(".") + module_name, class_name = cls.rsplit(".", 1) # load the module, will raise ImportError if module cannot be loaded get_module = importlib.import_module(module_name) # get the class, will raise AttributeError if class cannot be found get_class = getattr(get_module, class_name) return get_class - # def register(self, language, cls): - # self._register[language] = cls + def register(self, language, class_name): + """ Register a new code evaluator class for language""" + self._register[language] = class_name diff --git a/testapp/exam/models.py b/testapp/exam/models.py index 51e773a..a60550c 100644 --- a/testapp/exam/models.py +++ b/testapp/exam/models.py @@ -61,7 +61,7 @@ class Question(models.Model): points = models.FloatField(default=1.0) # Answer for MCQs. - solution = models.TextField(blank=True) + test = models.TextField(blank=True) # Test cases file paths (comma seperated for reference code path and test case code path) # Applicable for CPP, C, Java and Scilab @@ -118,6 +118,7 @@ class Question(models.Model): question_info_dict['user_answer'] = user_answer question_info_dict['test_parameter'] = test_case_data_dict question_info_dict['ref_code_path'] = self.ref_code_path + question_info_dict['test'] = self.test return json.dumps(question_info_dict) diff --git a/testapp/exam/python_code_evaluator.py b/testapp/exam/python_code_evaluator.py index 05a5063..61eee66 100644 --- a/testapp/exam/python_code_evaluator.py +++ b/testapp/exam/python_code_evaluator.py @@ -7,13 +7,12 @@ import importlib # local imports from code_evaluator import CodeEvaluator -# from language_registry import registry class PythonCodeEvaluator(CodeEvaluator): """Tests the Python code obtained from Code Server""" # Private Protocol ########## - def check_code(self): + def _check_code(self): success = False try: @@ -37,49 +36,23 @@ class PythonCodeEvaluator(CodeEvaluator): del tb return success, err - # # Public Protocol ########## - # def evaluate_code(self): - # success = False - - # try: - # tb = None - # test_code = self._create_test_case() - # submitted = compile(self.user_answer, '<string>', mode='exec') - # g = {} - # exec submitted in g - # _tests = compile(test_code, '<string>', mode='exec') - # exec _tests in g - # except AssertionError: - # type, value, tb = sys.exc_info() - # info = traceback.extract_tb(tb) - # fname, lineno, func, text = info[-1] - # text = str(test_code).splitlines()[lineno-1] - # err = "{0} {1} in: {2}".format(type.__name__, str(value), text) - # else: - # success = True - # err = 'Correct answer' - - # del tb - # return success, err - - # Private Protocol ########## def _create_test_case(self): """ Create assert based test cases in python """ test_code = "" - for test_case in self.test_case_data: - pos_args = ", ".join(str(i) for i in test_case.get('pos_args')) \ - if test_case.get('pos_args') else "" - kw_args = ", ".join(str(k+"="+a) for k, a - in test_case.get('kw_args').iteritems()) \ - if test_case.get('kw_args') else "" - args = pos_args + ", " + kw_args if pos_args and kw_args \ - else pos_args or kw_args - tcode = "assert {0}({1}) == {2}".format(test_case.get('func_name'), - args, test_case.get('expected_answer')) - test_code += tcode + "\n" - return test_code - - -# registry.register('python', EvaluatePythonCode) + if self.test: + return self.test + elif self.test_case_data: + for test_case in self.test_case_data: + pos_args = ", ".join(str(i) for i in test_case.get('pos_args')) \ + if test_case.get('pos_args') else "" + kw_args = ", ".join(str(k+"="+a) for k, a + in test_case.get('kw_args').iteritems()) \ + if test_case.get('kw_args') else "" + args = pos_args + ", " + kw_args if pos_args and kw_args \ + else pos_args or kw_args + tcode = "assert {0}({1}) == {2}".format(test_case.get('func_name'), + args, test_case.get('expected_answer')) + test_code += tcode + "\n" + return test_code diff --git a/testapp/exam/scilab_code_evaluator.py b/testapp/exam/scilab_code_evaluator.py index 073fbcb..a4628a2 100644 --- a/testapp/exam/scilab_code_evaluator.py +++ b/testapp/exam/scilab_code_evaluator.py @@ -8,37 +8,36 @@ import importlib # local imports from code_evaluator import CodeEvaluator -# from language_registry import registry class ScilabCodeEvaluator(CodeEvaluator): """Tests the Scilab code obtained from Code Server""" - def __init__(self, test_case_data, language, user_answer, + def __init__(self, test_case_data, test, language, user_answer, ref_code_path=None, in_dir=None): - super(ScilabCodeEvaluator, self).__init__(test_case_data, language, user_answer, + super(ScilabCodeEvaluator, self).__init__(test_case_data, test, language, user_answer, ref_code_path, in_dir) self.submit_path = self.create_submit_code_file('function.sci') - self.test_case_args = self.setup_code_evaluator() + self.test_case_args = self._setup() # Private Protocol ########## - def setup_code_evaluator(self): - super(ScilabCodeEvaluator, self).setup_code_evaluator() + def _setup(self): + super(ScilabCodeEvaluator, self)._setup() ref_path, test_case_path = self.set_test_code_file_path(self.ref_code_path) return ref_path, # Return as a tuple - def teardown_code_evaluator(self): + def _teardown(self): # Delete the created file. - super(ScilabCodeEvaluator, self).teardown_code_evaluator() + super(ScilabCodeEvaluator, self)._teardown() os.remove(self.submit_path) - def check_code(self, ref_path): + def _check_code(self, ref_path): success = False cmd = 'printf "lines(0)\nexec(\'{0}\',2);\nquit();"'.format(ref_path) cmd += ' | timeout 8 scilab-cli -nb' - ret = self.run_command(cmd, + ret = self._run_command(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -58,38 +57,6 @@ class ScilabCodeEvaluator(CodeEvaluator): return success, err - # # Public Protocol ########## - # def evaluate_code(self): - # submit_path = self.create_submit_code_file('function.sci') - # ref_path, test_case_path = self.set_test_code_file_path() - # success = False - - # cmd = 'printf "lines(0)\nexec(\'{0}\',2);\nquit();"'.format(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 - - # # Get only the error. - # stderr = self._get_error(stdout) - # if stderr is None: - # # Clean output - # stdout = self._strip_output(stdout) - # if proc.returncode == 5: - # success, err = True, "Correct answer" - # else: - # err = add_err + stdout - # else: - # err = add_err + stderr - - # # Delete the created file. - # os.remove(submit_path) - - # return success, err - - # Private Protocol ########## def _remove_scilab_exit(self, string): """ Removes exit, quit and abort from the scilab code @@ -105,7 +72,6 @@ class ScilabCodeEvaluator(CodeEvaluator): new_string = new_string + '\n' + new_line return new_string, i - # Private Protocol ########## def _get_error(self, string): """ Fetches only the error from the string. @@ -116,7 +82,6 @@ class ScilabCodeEvaluator(CodeEvaluator): return obj.group() return None - # Private Protocol ########## def _strip_output(self, out): """ Cleans whitespace from the output @@ -127,5 +92,3 @@ class ScilabCodeEvaluator(CodeEvaluator): strip_out = strip_out+"\n"+l.strip() return strip_out - -# registry.register('scilab', EvaluateScilabCode) diff --git a/testapp/exam/settings.py b/testapp/exam/settings.py index 497a620..93f90a9 100644 --- a/testapp/exam/settings.py +++ b/testapp/exam/settings.py @@ -19,10 +19,10 @@ SERVER_TIMEOUT = 2 # host.org/foo/exam set URL_ROOT='/foo' URL_ROOT = '' -language_register = {"python": "python_code_evaluator", - "c": "c_cpp_code_evaluator", - "cpp": "c_cpp_code_evaluator", - "java": "java_evaluator", - "bash": "bash_evaluator", - "scilab": "scilab_evaluator", +code_evaluators = {"python": "python_code_evaluator.PythonCodeEvaluator", + "c": "c_cpp_code_evaluator.CCPPCodeEvaluator", + "cpp": "c_cpp_code_evaluator.CCPPCodeEvaluator", + "java": "java_evaluator.JavaCodeEvaluator", + "bash": "bash_evaluator.BashCodeEvaluator", + "scilab": "scilab_evaluator.ScilabCodeEvaluator", } diff --git a/testapp/exam/static/exam/js/add_question.js b/testapp/exam/static/exam/js/add_question.js index 5a94f4c..946c139 100644 --- a/testapp/exam/static/exam/js/add_question.js +++ b/testapp/exam/static/exam/js/add_question.js @@ -154,16 +154,11 @@ function textareaformat() { document.getElementById('id_options').style.visibility='visible'; document.getElementById('label_option').innerHTML="Options :"; - document.getElementById('id_solution').style.visibility='visible'; - document.getElementById('label_solution').innerHTML="Solutions :"; - } else { document.getElementById('id_options').style.visibility='hidden'; document.getElementById('label_option').innerHTML = ""; - document.getElementById('id_solution').style.visibility='hidden'; - document.getElementById('label_solution').innerHTML="" } }); document.getElementById('my').innerHTML = document.getElementById('id_description').value ; @@ -172,16 +167,11 @@ function textareaformat() { document.getElementById('id_options').style.visibility='visible'; document.getElementById('label_option').innerHTML="Options :" - document.getElementById('id_solution').style.visibility='visible'; - document.getElementById('label_solution').innerHTML="Solutions :"; - } else { document.getElementById('id_options').style.visibility='hidden'; document.getElementById('label_option').innerHTML = ""; - document.getElementById('id_solution').style.visibility='hidden'; - document.getElementById('label_solution').innerHTML="" } } diff --git a/testapp/exam/templates/exam/add_question.html b/testapp/exam/templates/exam/add_question.html index e117ef3..43f09e1 100644 --- a/testapp/exam/templates/exam/add_question.html +++ b/testapp/exam/templates/exam/add_question.html @@ -30,7 +30,7 @@ <tr><td>Snippet: <td>{{ form.snippet }}{{ form.snippet.errors }}</td></tD></td></tr> <tr><td>Tags: <td>{{ form.tags }} <tr><td id='label_option'>Options: <td>{{ form.options }} {{form.options.errors}} - <tr><td id='label_solution'>Solution: <td>{{ form.solution }} {{form.solution.errors}} + <tr><td id='label_solution'>Test: <td>{{ form.solution }} {{form.solution.errors}} <tr><td id='label_ref_code_path'>Reference Code Path: <td>{{ form.ref_code_path }} {{form.ref_code_path.errors}} <form method="post" action=""> diff --git a/testapp/exam/tests.py b/testapp/exam/tests.py index f73d0e2..ff48c25 100644 --- a/testapp/exam/tests.py +++ b/testapp/exam/tests.py @@ -71,7 +71,6 @@ class QuestionTestCases(unittest.TestCase): "kw_args": {"a": "10", "b": "11"} }], - "ref_code_path": "", "id": self.question.id, "language": "Python"} self.answer_data_json = json.dumps(answer_data) diff --git a/testapp/exam/views.py b/testapp/exam/views.py index 2542a28..5b7baac 100644 --- a/testapp/exam/views.py +++ b/testapp/exam/views.py @@ -311,7 +311,7 @@ def edit_question(request): question.language = language[j] question.snippet = snippet[j] question.ref_code_path = ref_code_path[j] - question.solution = solution[j] + question.test = test[j] question.type = type[j] question.save() return my_redirect("/exam/manage/questions") @@ -376,7 +376,7 @@ def add_question(request, question_id=None): d.language = form['language'].data d.snippet = form['snippet'].data d.ref_code_path = form['ref_code_path'].data - d.solution = form['solution'].data + d.test = form['test'].data d.save() question = Question.objects.get(id=question_id) for tag in question.tags.all(): @@ -432,7 +432,7 @@ def add_question(request, question_id=None): form.initial['language'] = d.language form.initial['snippet'] = d.snippet form.initial['ref_code_path'] = d.ref_code_path - form.initial['solution'] = d.solution + form.initial['test'] = d.test form_tags = d.tags.all() form_tags_split = form_tags.values('name') initial_tags = "" @@ -916,7 +916,7 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): question = get_object_or_404(Question, pk=q_id) q_paper = QuestionPaper.objects.get(id=questionpaper_id) paper = AnswerPaper.objects.get(user=request.user, question_paper=q_paper) - test = TestCase.objects.filter(question=question) + test_cases = TestCase.objects.filter(question=question) snippet_code = request.POST.get('snippet') user_code = request.POST.get('answer') @@ -958,7 +958,7 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): # questions, we obtain the results via XML-RPC with the code executed # safely in a separate process (the code_server.py) running as nobody. if not question.type == 'upload': - json_data = question.consolidate_answer_data(test, user_answer) \ + json_data = question.consolidate_answer_data(test_cases, user_answer) \ if question.type == 'code' else None correct, result = validate_answer(user, user_answer, question, json_data) if correct: @@ -1020,11 +1020,11 @@ def validate_answer(user, user_answer, question, json_data=None): if user_answer is not None: if question.type == 'mcq': - if user_answer.strip() == question.solution.strip(): + if user_answer.strip() == question.test.strip(): correct = True message = 'Correct answer' elif question.type == 'mcc': - answers = set(question.solution.splitlines()) + answers = set(question.test.splitlines()) if set(user_answer) == answers: correct = True message = 'Correct answer' @@ -1253,7 +1253,7 @@ def show_all_questions(request): form.initial['language'] = d.language form.initial['snippet'] = d.snippet form.initial['ref_code_path'] = d.ref_code_path - form.initial['solution'] = d.solution + form.initial['test'] = d.test form_tags = d.tags.all() form_tags_split = form_tags.values('name') initial_tags = "" |