diff options
author | Prabhu Ramachandran | 2011-11-24 02:11:40 +0530 |
---|---|---|
committer | Prabhu Ramachandran | 2011-11-24 02:11:40 +0530 |
commit | 11a2eaefaba6d2b547d35afbee3e85b18520afd2 (patch) | |
tree | f05aef4423f613c4d38232569df77a88c66978e7 /exam | |
parent | 30f56443790841901f15b5ab435f97fba1c81d85 (diff) | |
download | online_test-11a2eaefaba6d2b547d35afbee3e85b18520afd2.tar.gz online_test-11a2eaefaba6d2b547d35afbee3e85b18520afd2.tar.bz2 online_test-11a2eaefaba6d2b547d35afbee3e85b18520afd2.zip |
ENH/TMP: Preliminary support for bash scripts.
- Changing the Question model to add a language attribute.
- Moving python_server.py -> code_server.py.
- Adding functionality to test for Shell scripts. This is still
incomplete since the shell code checker seems to have some problems.
- Modified the xmlrpc_clients to support multiple languages and right
now two.
- Using setgid/setuid instead of setegid/seteuid in the code_server.py..
- Adding a bash example to the sample_questions.py.
The shell script support doesn't quite work yet but this is really a
code_server/checking issue.
Diffstat (limited to 'exam')
-rw-r--r-- | exam/management/commands/load_questions_xml.py | 4 | ||||
-rw-r--r-- | exam/models.py | 8 | ||||
-rw-r--r-- | exam/views.py | 5 | ||||
-rw-r--r-- | exam/xmlrpc_clients.py | 37 |
4 files changed, 45 insertions, 9 deletions
diff --git a/exam/management/commands/load_questions_xml.py b/exam/management/commands/load_questions_xml.py index aa403dd..b4151ae 100644 --- a/exam/management/commands/load_questions_xml.py +++ b/exam/management/commands/load_questions_xml.py @@ -35,6 +35,9 @@ def load_questions_xml(filename): desc_node = question.getElementsByTagName("description")[0] description = (desc_node.childNodes[0].data).strip() + lang_node = question.getElementsByTagName("language")[0] + language = (lang_node.childNodes[0].data).strip() + points_node = question.getElementsByTagName("points")[0] points = int((points_node.childNodes[0].data).strip()) \ if points_node else 1 @@ -45,6 +48,7 @@ def load_questions_xml(filename): new_question = Question(summary=summary, description=description, points=points, + language=language, test=test) new_question.save() diff --git a/exam/models.py b/exam/models.py index d433c7c..ef4312f 100644 --- a/exam/models.py +++ b/exam/models.py @@ -12,6 +12,11 @@ class Profile(models.Model): position = models.CharField(max_length=64) +LANGUAGE_CHOICES = ( + ("python", "Python"), + ("bash", "Bash"), + ) + ################################################################################ class Question(models.Model): """A question in the database.""" @@ -29,6 +34,9 @@ class Question(models.Model): # This is simple Python code. test = models.TextField() + # The language being tested. + language = models.CharField(max_length=10, choices=LANGUAGE_CHOICES) + # Is this question active or not. If it is inactive it will not be used # when creating a QuestionPaper. active = models.BooleanField(default=True) diff --git a/exam/views.py b/exam/views.py index bafd0be..1f92553 100644 --- a/exam/views.py +++ b/exam/views.py @@ -13,7 +13,7 @@ from django.http import Http404 # Local imports. from exam.models import Quiz, Question, QuestionPaper, Profile, Answer, User from exam.forms import UserRegisterForm, UserLoginForm -from exam.xmlrpc_clients import python_server +from exam.xmlrpc_clients import code_server from settings import URL_ROOT # The directory where user data can be saved. @@ -203,7 +203,8 @@ def check(request, q_id): # with the code executed safely in a separate process (the python_server.py) # running as nobody. user_dir = get_user_dir(user) - success, err_msg = python_server.run_code(answer, question.test, user_dir) + success, err_msg = code_server.run_code(answer, question.test, + user_dir, question.language) new_answer.error = err_msg if success: diff --git a/exam/xmlrpc_clients.py b/exam/xmlrpc_clients.py index 115ee6e..01172d7 100644 --- a/exam/xmlrpc_clients.py +++ b/exam/xmlrpc_clients.py @@ -4,7 +4,7 @@ import random import socket -class PythonServer(object): +class CodeServer(object): """A class that manages accesing the farm of Python servers and making calls to them such that no one XMLRPC server is overloaded. """ @@ -12,19 +12,41 @@ class PythonServer(object): servers = [ServerProxy('http://localhost:%d'%(x)) for x in SERVER_PORTS] self.servers = servers self.indices = range(len(SERVER_PORTS)) + self.methods = {"python": 'run_python_code', + "bash": 'run_bash_code'} - def run_code(self, answer, test_code, user_dir): - """See the documentation of the method of the same name in - python_server.py. + def run_code(self, answer, test_code, user_dir, language): + """Tests given code (`answer`) with the `test_code` supplied. 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). The parameter language specifies which language to use for the + tests. + + Parameters + ---------- + answer : str + The user's answer for the question. + test_code : str + The test code to check the user code with. + user_dir : str (directory) + The directory to run the tests inside. + language : str + The programming language to use. + + Returns + ------- + A tuple: (success, error message). """ + method_name = self.methods[language] done = False - result = [False, 'Unable to connect to any Python servers!'] + result = [False, 'Unable to connect to any code servers!'] # Try to connect a few times if not, quit. count = 5 while (not done) and (count > 0): try: server = self._get_server() - result = server.run_code(answer, test_code, user_dir) + method = getattr(server, method_name) + result = method(answer, test_code, user_dir) except socket.error: count -= 1 else: @@ -38,4 +60,5 @@ class PythonServer(object): # views.py calls this Python server which forwards the request to one # of the running servers. -python_server = PythonServer() +code_server = CodeServer() + |