diff options
Diffstat (limited to 'yaksh')
-rw-r--r-- | yaksh/decorators.py | 12 | ||||
-rw-r--r-- | yaksh/error_messages.py | 38 | ||||
-rw-r--r-- | yaksh/evaluator_tests/test_python_evaluation.py | 554 | ||||
-rw-r--r-- | yaksh/grader.py | 40 | ||||
-rw-r--r-- | yaksh/models.py | 15 | ||||
-rw-r--r-- | yaksh/python_assertion_evaluator.py | 20 | ||||
-rw-r--r-- | yaksh/static/yaksh/js/requesthandler.js | 21 | ||||
-rw-r--r-- | yaksh/templates/yaksh/error_template.html | 2 | ||||
-rw-r--r-- | yaksh/templates/yaksh/question.html | 8 | ||||
-rw-r--r-- | yaksh/test_models.py | 61 | ||||
-rw-r--r-- | yaksh/urls.py | 2 | ||||
-rw-r--r-- | yaksh/urls_password_reset.py | 2 | ||||
-rw-r--r-- | yaksh/views.py | 243 |
13 files changed, 529 insertions, 489 deletions
diff --git a/yaksh/decorators.py b/yaksh/decorators.py index 9e9bc6d..4b886a3 100644 --- a/yaksh/decorators.py +++ b/yaksh/decorators.py @@ -1,4 +1,4 @@ -from django.shortcuts import render_to_response, redirect +from django.shortcuts import render, redirect from django.conf import settings from django.template import RequestContext @@ -20,15 +20,13 @@ def has_profile(func): def _wrapped_view(request, *args, **kwargs): if user_has_profile(request.user): return func(request, *args, **kwargs) - ci = RequestContext(request) if request.user.groups.filter(name='moderator').exists(): template = 'manage.html' else: template = 'user.html' form = ProfileForm(user=request.user, instance=None) context = {'template': template, 'form': form} - return render_to_response('yaksh/editprofile.html', context, - context_instance=ci) + return render(request, 'yaksh/editprofile.html', context) return _wrapped_view @@ -40,7 +38,6 @@ def email_verified(func): """ def is_email_verified(request, *args, **kwargs): - ci = RequestContext(request) user = request.user context = {} if not settings.IS_DEVELOPMENT: @@ -49,7 +46,8 @@ def email_verified(func): context['success'] = False context['msg'] = "Your account is not verified. \ Please verify your account" - return render_to_response('yaksh/activation_status.html', - context, context_instance=ci) + return render( + request, 'yaksh/activation_status.html', context + ) return func(request, *args, **kwargs) return is_email_verified
\ No newline at end of file diff --git a/yaksh/error_messages.py b/yaksh/error_messages.py index 7ea8618..7a18c22 100644 --- a/yaksh/error_messages.py +++ b/yaksh/error_messages.py @@ -3,7 +3,9 @@ try: except ImportError: from itertools import izip_longest as zip_longest -def prettify_exceptions(exception, message, traceback=None, testcase=None): + +def prettify_exceptions(exception, message, traceback=None, + testcase=None, line_no=None): err = {"type": "assertion", "exception": exception, "traceback": traceback, @@ -13,23 +15,28 @@ def prettify_exceptions(exception, message, traceback=None, testcase=None): err["traceback"] = None if exception == 'AssertionError': - value = ("Expected answer from the" - + " test case did not match the output") - err["message"] = value + value = ("Expected answer from the" + + " test case did not match the output") + if message: + err["message"] = message + else: + err["message"] = value err["traceback"] = None - if testcase: - err["test_case"] = testcase + err["test_case"] = testcase + err["line_no"] = line_no return err + def _get_incorrect_user_lines(exp_lines, user_lines): err_line_numbers = [] for line_no, (expected_line, user_line) in \ - enumerate(zip_longest(exp_lines, user_lines)): - if not user_line or not expected_line or \ - user_line.strip() != expected_line.strip(): + enumerate(zip_longest(exp_lines, user_lines)): + if (not user_line or not expected_line or + user_line.strip() != expected_line.strip()): err_line_numbers.append(line_no) return err_line_numbers - + + def compare_outputs(expected_output, user_output, given_input=None): given_lines = user_output.splitlines() exp_lines = expected_output.splitlines() @@ -44,18 +51,17 @@ def compare_outputs(expected_output, user_output, given_input=None): msg["error_line_numbers"] = err_line_numbers if ng != ne: msg["error_msg"] = ("Incorrect Answer: " - + "We had expected {} number of lines. "\ - .format(ne) + + "We had expected {} number of lines. ".format(ne) + "We got {} number of lines.".format(ng) ) return False, msg else: if err_line_numbers: msg["error_msg"] = ("Incorrect Answer: " - + "Line number(s) {0} did not match." - .format(", ".join(map( - str,[x+1 for x in err_line_numbers] - )))) + + "Line number(s) {0} did not match." + .format(", ".join( + map(str, [x+1 for x in err_line_numbers]) + ))) return False, msg else: msg["error_msg"] = "Correct Answer" diff --git a/yaksh/evaluator_tests/test_python_evaluation.py b/yaksh/evaluator_tests/test_python_evaluation.py index 71d7732..1933d17 100644 --- a/yaksh/evaluator_tests/test_python_evaluation.py +++ b/yaksh/evaluator_tests/test_python_evaluation.py @@ -1,7 +1,6 @@ from __future__ import unicode_literals import unittest import os -import sys import tempfile import shutil from textwrap import dedent @@ -26,13 +25,13 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): self.in_dir = tmp_in_dir_path self.test_case_data = [{"test_case_type": "standardtestcase", "test_case": 'assert(add(1,2)==3)', - 'weight': 0.0}, + 'weight': 0.0}, {"test_case_type": "standardtestcase", "test_case": 'assert(add(-1,2)==1)', - 'weight': 0.0}, + 'weight': 0.0}, {"test_case_type": "standardtestcase", "test_case": 'assert(add(-1,-2)==-3)', - 'weight': 0.0}, + 'weight': 0.0}, ] self.timeout_msg = ("Code took more than {0} seconds to run. " "You probably have an infinite loop in" @@ -46,14 +45,12 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): def test_correct_answer(self): # Given user_answer = "def add(a,b):\n\treturn a + b" - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data, + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data, } # When @@ -66,14 +63,12 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): def test_incorrect_answer(self): # Given user_answer = "def add(a,b):\n\treturn a - b" - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data, + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data, } # When @@ -85,13 +80,13 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): given_test_case_list = [tc["test_case"] for tc in self.test_case_data] for error in result.get("error"): self.assertEqual(error['exception'], 'AssertionError') - self.assertEqual(error['message'], - "Expected answer from the test case did not match the output" - ) + self.assertEqual( + error['message'], + "Expected answer from the test case did not match the output" + ) error_testcase_list = [tc['test_case'] for tc in result.get('error')] self.assertEqual(error_testcase_list, given_test_case_list) - def test_partial_incorrect_answer(self): # Given user_answer = "def add(a,b):\n\treturn abs(a) + abs(b)" @@ -100,19 +95,17 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): 'weight': 1.0}, {"test_case_type": "standardtestcase", "test_case": 'assert(add(-1,-2)==-3)', - 'weight': 1.0}, + 'weight': 1.0}, {"test_case_type": "standardtestcase", "test_case": 'assert(add(1,2)==3)', 'weight': 2.0} ] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': True, - 'language': 'python' - }, - 'test_case_data': test_case_data, + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': True, + 'language': 'python'}, + 'test_case_data': test_case_data, } # When @@ -126,22 +119,22 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): given_test_case_list.remove('assert(add(1,2)==3)') for error in result.get("error"): self.assertEqual(error['exception'], 'AssertionError') - self.assertEqual(error['message'], - "Expected answer from the test case did not match the output" - ) + self.assertEqual( + error['message'], + "Expected answer from the test case did not match the output" + ) error_testcase_list = [tc['test_case'] for tc in result.get('error')] self.assertEqual(error_testcase_list, given_test_case_list) + def test_infinite_loop(self): # Given user_answer = "def add(a, b):\n\twhile True:\n\t\tpass" - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data, + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data, } # When @@ -168,14 +161,12 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): "SyntaxError", "invalid syntax" ] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data, + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data, } # When @@ -201,14 +192,12 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): "IndentationError", "indented block" ] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data, + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data, } # When @@ -220,9 +209,9 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): self.assertFalse(result.get("success")) self.assertEqual(5, len(err)) for msg in indent_error_msg: - self.assert_correct_output(msg, - result.get("error")[0]['traceback'] - ) + self.assert_correct_output( + msg, result.get("error")[0]['traceback'] + ) def test_name_error(self): # Given @@ -234,15 +223,13 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): "defined" ] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data, - } + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data, + } # When grader = Grader(self.in_dir) @@ -258,15 +245,13 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): return add(3, 3) """) recursion_error_msg = "maximum recursion depth exceeded" - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data, - } + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data, + } # When grader = Grader(self.in_dir) @@ -289,15 +274,13 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): "argument" ] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data, - } + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data, + } # When grader = Grader(self.in_dir) @@ -323,25 +306,26 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): "base" ] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data, - } + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data, + } # When grader = Grader(self.in_dir) result = grader.evaluate(kwargs) - err = result.get("error")[0]['traceback'] + errors = result.get("error") # Then self.assertFalse(result.get("success")) for msg in value_error_msg: - self.assert_correct_output(msg, err) + self.assert_correct_output(msg, errors[0]['traceback']) + for index, error in enumerate(errors): + self.assertEqual(error['test_case'], + self.test_case_data[index]['test_case']) def test_file_based_assert(self): # Given @@ -356,15 +340,13 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): return f.read()[0] """) - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data, - } + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data, + } # When grader = Grader(self.in_dir) @@ -390,25 +372,23 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): ] kwargs = {'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': test_case_data, - } + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': test_case_data, + } # When grader = Grader(self.in_dir) result = grader.evaluate(kwargs) - err = result.get("error")[0]['traceback'] + err = result.get("error")[0]['traceback'] # Then self.assertFalse(result.get("success")) for msg in syntax_error_msg: self.assert_correct_output(msg, err) - def test_multiple_testcase_error(self): """ Tests the user answer with an correct test case first and then with an incorrect test case """ @@ -418,7 +398,8 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): "test_case": 'assert(palindrome("abba")==True)', "weight": 0.0}, {"test_case_type": "standardtestcase", - "test_case": 's="abbb"\nassert palindrome(S)==False', + "test_case": 's="abbb"\n' + 'assert palindrome(S)==False', "weight": 0.0} ] name_error_msg = ["Traceback", @@ -426,15 +407,13 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): "NameError", "name 'S' is not defined" ] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': test_case_data, - } + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': test_case_data, + } # When grader = Grader(self.in_dir) @@ -454,18 +433,15 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): return type(a) """) test_case_data = [{"test_case_type": "standardtestcase", - "test_case": 'assert(strchar("hello")==str)', - "weight": 0.0 - },] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': test_case_data, - } + "test_case": 'assert(strchar("hello")==str)', + "weight": 0.0}] + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': test_case_data, + } # When grader = Grader(self.in_dir) result = grader.evaluate(kwargs) @@ -473,6 +449,31 @@ class PythonAssertionEvaluationTestCases(EvaluatorBaseTest): # Then self.assertTrue(result.get("success")) + def test_incorrect_answer_with_nose_assert(self): + user_answer = dedent("""\ + def add(a, b): + return a - b + """) + test_case_data = [{"test_case_type": "standardtestcase", + "test_case": 'assert_equal(add(1, 2), 3)', + "weight": 0.0}] + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': test_case_data, + } + # When + grader = Grader(self.in_dir) + result = grader.evaluate(kwargs) + + # Then + self.assertFalse(result.get("success")) + error = result.get("error")[0] + self.assertEqual(error['exception'], 'AssertionError') + self.assertEqual(error['message'], '-1 != 3') + class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): def setUp(self): @@ -501,13 +502,12 @@ class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): """ ) kwargs = {'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data - } + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data + } # When grader = Grader(self.in_dir) @@ -534,13 +534,12 @@ class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): ) kwargs = {'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data - } + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data + } # When grader = Grader(self.in_dir) @@ -551,11 +550,13 @@ class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): def test_correct_answer_string(self): # Given - self.test_case_data = [{"test_case_type": "stdiobasedtestcase", - "expected_input": ("the quick brown fox jumps over the lazy dog\nthe"), - "expected_output": "2", - "weight": 0.0 - }] + self.test_case_data = [{ + "test_case_type": "stdiobasedtestcase", + "expected_input": ("the quick brown fox jumps over " + "the lazy dog\nthe"), + "expected_output": "2", + "weight": 0.0 + }] user_answer = dedent(""" from six.moves import input a = str(input()) @@ -565,13 +566,12 @@ class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): ) kwargs = {'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data - } + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data + } # When grader = Grader(self.in_dir) @@ -594,13 +594,12 @@ class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): """ ) kwargs = {'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data - } + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data + } # When grader = Grader(self.in_dir) @@ -629,13 +628,12 @@ class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): """ ) kwargs = {'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data - } + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data + } # When grader = Grader(self.in_dir) @@ -646,24 +644,24 @@ class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): def test_infinite_loop(self): # Given - self.test_case_data = [{"test_case_type": "stdiobasedtestcase", - "expected_input": "1\n2", - "expected_output": "3", - "weight": 0.0 - }] + self.test_case_data = [{ + "test_case_type": "stdiobasedtestcase", + "expected_input": "1\n2", + "expected_output": "3", + "weight": 0.0 + }] timeout_msg = ("Code took more than {0} seconds to run. " - "You probably have an infinite loop in" - " your code.").format(SERVER_TIMEOUT) + "You probably have an infinite loop in" + " your code.").format(SERVER_TIMEOUT) user_answer = "while True:\n\tpass" kwargs = {'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': self.test_case_data - } + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': self.test_case_data + } # When grader = Grader(self.in_dir) @@ -675,7 +673,6 @@ class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): ) self.assertFalse(result.get('success')) - def test_unicode_literal_bug(self): # Given user_answer = dedent("""\ @@ -687,21 +684,44 @@ class PythonStdIOEvaluationTestCases(EvaluatorBaseTest): "expected_output": "str", "weight": 0.0 }] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': test_case_data, - } + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': test_case_data, + } # When grader = Grader(self.in_dir) result = grader.evaluate(kwargs) # Then self.assertTrue(result.get("success")) + def test_get_error_lineno(self): + user_answer = dedent("""\ + print(1/0) + """) + test_case_data = [{"test_case_type": "stdiobasedtestcase", + "expected_input": "", + "expected_output": "1", + "weight": 0.0 + }] + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': test_case_data, + } + # When + grader = Grader(self.in_dir) + result = grader.evaluate(kwargs) + # Then + self.assertFalse(result.get("success")) + error = result.get("error")[0] + self.assertEqual(error['line_no'], 1) + self.assertEqual(error['exception'], "ZeroDivisionError") + class PythonHookEvaluationTestCases(EvaluatorBaseTest): @@ -733,19 +753,17 @@ class PythonHookEvaluationTestCases(EvaluatorBaseTest): success, err, mark_fraction = True, "", 1.0 return success, err, mark_fraction """ - ) + ) test_case_data = [{"test_case_type": "hooktestcase", - "hook_code": hook_code,"weight": 1.0 - }] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': True, - 'language': 'python' - }, - 'test_case_data': test_case_data, + "hook_code": hook_code, "weight": 1.0 + }] + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': True, + 'language': 'python'}, + 'test_case_data': test_case_data, } # When @@ -768,20 +786,18 @@ class PythonHookEvaluationTestCases(EvaluatorBaseTest): success, err, mark_fraction = True, "", 1.0 return success, err, mark_fraction """ - ) + ) test_case_data = [{"test_case_type": "hooktestcase", - "hook_code": hook_code,"weight": 1.0 - }] - - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': test_case_data, + "hook_code": hook_code, "weight": 1.0 + }] + + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': test_case_data, } # When @@ -805,21 +821,19 @@ class PythonHookEvaluationTestCases(EvaluatorBaseTest): success, err, mark_fraction = True, "", 1.0 return success, err, mark_fraction """ - ) + ) test_case_data = [{"test_case_type": "standardtestcase", "test_case": assert_test_case, 'weight': 1.0}, {"test_case_type": "hooktestcase", "hook_code": hook_code, 'weight': 1.0}, ] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': True, - 'language': 'python' - }, - 'test_case_data': test_case_data, + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': True, + 'language': 'python'}, + 'test_case_data': test_case_data, } # When @@ -842,7 +856,7 @@ class PythonHookEvaluationTestCases(EvaluatorBaseTest): success, err, mark_fraction = True, "", 0.5 return success, err, mark_fraction """ - ) + ) hook_code_2 = dedent("""\ def check_answer(user_answer): success = False @@ -853,22 +867,19 @@ class PythonHookEvaluationTestCases(EvaluatorBaseTest): success, err, mark_fraction = True, "", 1.0 return success, err, mark_fraction """ - ) - + ) test_case_data = [{"test_case_type": "hooktestcase", "hook_code": hook_code_1, 'weight': 1.0}, {"test_case_type": "hooktestcase", "hook_code": hook_code_2, 'weight': 1.0}, ] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': True, - 'language': 'python' - }, - 'test_case_data': test_case_data, + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': True, + 'language': 'python'}, + 'test_case_data': test_case_data, } # When @@ -892,19 +903,18 @@ class PythonHookEvaluationTestCases(EvaluatorBaseTest): success, err, mark_fraction = True, "", 1.0 return success, err, mark_fraction """ - ) + ) + test_case_data = [{"test_case_type": "hooktestcase", - "hook_code": hook_code,"weight": 1.0 - }] - - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': test_case_data, + "hook_code": hook_code, "weight": 1.0 + }] + + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': test_case_data, } # When @@ -931,19 +941,18 @@ class PythonHookEvaluationTestCases(EvaluatorBaseTest): success, err, mark_fraction = True, "", 1.0 return success, err, mark_fraction """ - ) + ) + test_case_data = [{"test_case_type": "hooktestcase", - "hook_code": hook_code,"weight": 1.0 - }] - kwargs = { - 'metadata': { - 'user_answer': user_answer, - 'file_paths': self.file_paths, - 'assign_files': [(self.tmp_file, False)], - 'partial_grading': False, - 'language': 'python' - }, - 'test_case_data': test_case_data, + "hook_code": hook_code, "weight": 1.0 + }] + kwargs = {'metadata': { + 'user_answer': user_answer, + 'file_paths': self.file_paths, + 'assign_files': [(self.tmp_file, False)], + 'partial_grading': False, + 'language': 'python'}, + 'test_case_data': test_case_data, } # When @@ -953,5 +962,6 @@ class PythonHookEvaluationTestCases(EvaluatorBaseTest): # Then self.assertTrue(result.get('success')) + if __name__ == '__main__': unittest.main() diff --git a/yaksh/grader.py b/yaksh/grader.py index c9dc8a2..320e7e7 100644 --- a/yaksh/grader.py +++ b/yaksh/grader.py @@ -1,22 +1,12 @@ #!/usr/bin/env python from __future__ import unicode_literals import sys -import pwd import os -import stat import contextlib -from os.path import isdir, dirname, abspath, join, isfile, exists +from os.path import dirname, abspath import signal import traceback -from multiprocessing import Process, Queue -import subprocess -import re -try: - from SimpleXMLRPCServer import SimpleXMLRPCServer -except ImportError: - # The above import will not work on Python-3.x. - from xmlrpc.server import SimpleXMLRPCServer # Local imports from .settings import SERVER_TIMEOUT @@ -26,11 +16,13 @@ from .error_messages import prettify_exceptions MY_DIR = abspath(dirname(__file__)) registry = None + # Raised when the code times-out. # c.f. http://pguides.net/python/timeout-a-function class TimeoutException(Exception): pass + @contextlib.contextmanager def change_dir(path): cur_dir = abspath(dirname(MY_DIR)) @@ -75,7 +67,6 @@ class Grader(object): self.timeout_msg = msg self.in_dir = in_dir if in_dir else MY_DIR - def evaluate(self, kwargs): """Evaluates given code with the test cases based on given arguments in test_case_data. @@ -122,7 +113,6 @@ class Grader(object): test_case_instances.append(test_case_instance) return test_case_instances - def safe_evaluate(self, test_case_instances): """ Handles code evaluation along with compilation, signal handling @@ -157,20 +147,24 @@ class Grader(object): test_case_instance.teardown() except TimeoutException: - error.append(prettify_exceptions("TimeoutException", - self.timeout_msg - ) - ) - except Exception: + error.append( + prettify_exceptions("TimeoutException", self.timeout_msg) + ) + except Exception as e: exc_type, exc_value, exc_tb = sys.exc_info() tb_list = traceback.format_exception(exc_type, exc_value, exc_tb) + try: + line_no = e.lineno + except AttributeError: + line_no = traceback.extract_tb(exc_tb)[-1][1] if len(tb_list) > 2: del tb_list[1:3] - error.append(prettify_exceptions(exc_type.__name__, - str(exc_value), - "".join(tb_list), - ) - ) + error.append( + prettify_exceptions( + exc_type.__name__, str(exc_value), "".join(tb_list), + line_no=line_no + ) + ) finally: # Set back any original signal handler. set_original_signal_handler(prev_handler) diff --git a/yaksh/models.py b/yaksh/models.py index d011bb0..3010a3c 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -317,7 +317,7 @@ class Quiz(models.Model): attempts_allowed = models.IntegerField(default=1, choices=attempts) time_between_attempts = models.FloatField( - "Time Between Quiz Attempts in hours" + "Time Between Quiz Attempts in hours", default=0.0 ) is_trial = models.BooleanField(default=False) @@ -1356,11 +1356,18 @@ class QuestionPaper(models.Model): ) if last_attempt: time_lag = (timezone.now() - last_attempt.start_time).total_seconds() / 3600 - return time_lag >= self.quiz.time_between_attempts + can_attempt = time_lag >= self.quiz.time_between_attempts + msg = "You cannot start the next attempt for this quiz before {0} hour(s)".format( + self.quiz.time_between_attempts + ) if not can_attempt else None + return can_attempt, msg else: - return True + return True, None else: - return False + msg = "You cannot attempt {0} quiz more than {1} time(s)".format( + self.quiz.description, self.quiz.attempts_allowed + ) + return False, msg def create_demo_quiz_ppr(self, demo_quiz, user): question_paper = QuestionPaper.objects.create(quiz=demo_quiz, diff --git a/yaksh/python_assertion_evaluator.py b/yaksh/python_assertion_evaluator.py index 440f422..4b016a1 100644 --- a/yaksh/python_assertion_evaluator.py +++ b/yaksh/python_assertion_evaluator.py @@ -1,10 +1,6 @@ #!/usr/bin/env python import sys import traceback -import os -import re -from os.path import join -import importlib # Local imports from .file_utils import copy_files, delete_files @@ -53,22 +49,24 @@ class PythonAssertionEvaluator(BaseEvaluator): -------- Returns a tuple (success, error, test_case_weight) - success - Boolean, indicating if code was executed successfully, correctly + success - Boolean, indicating if code was executed successfully, + correctly weight - Float, indicating total weight of all successful test cases error - String, error message if success is false - returns (True, "Correct answer", 1.0) : If the student script passes all - test cases/have same output, when compared to the instructor script + returns (True, "Correct answer", 1.0) : If the student script passes + all test cases/have same output, when compared to the instructor script returns (False, error_msg, 0.0): If the student script fails a single test/have dissimilar output, when compared to the instructor script. - Returns (False, error_msg, 0.0): If mandatory arguments are not files or if - the required permissions are not given to the file(s). + Returns (False, error_msg, 0.0): If mandatory arguments are not files + or if the required permissions are not given to the file(s). """ success = False mark_fraction = 0.0 try: + exec("from nose.tools import *", self.exec_scope) _tests = compile(self.test_case, '<string>', mode='exec') exec(_tests, self.exec_scope) except TimeoutException: @@ -76,12 +74,14 @@ class PythonAssertionEvaluator(BaseEvaluator): except Exception: exc_type, exc_value, exc_tb = sys.exc_info() tb_list = traceback.format_exception(exc_type, exc_value, exc_tb) + line_no = traceback.extract_tb(exc_tb)[-1][1] if len(tb_list) > 2: del tb_list[1:3] err = prettify_exceptions(exc_type.__name__, str(exc_value), "".join(tb_list), - self.test_case + self.test_case, + line_no ) else: success = True diff --git a/yaksh/static/yaksh/js/requesthandler.js b/yaksh/static/yaksh/js/requesthandler.js index a215ce4..952de3a 100644 --- a/yaksh/static/yaksh/js/requesthandler.js +++ b/yaksh/static/yaksh/js/requesthandler.js @@ -75,6 +75,24 @@ function response_handler(method_type, content_type, data, uid){ var error_output = document.getElementById("error_panel"); error_output.innerHTML = res.error; focus_on_error(error_output); + if(global_editor.editor){ + err_lineno = $("#err_lineno").val(); + if(marker){ + marker.clear(); + } + if(err_lineno){ + var lineno = parseInt(err_lineno) - 1; + var editor = global_editor.editor; + var line_length = editor.getLine(lineno).length; + marker = editor.markText({line: lineno, ch: 0}, {line: lineno, ch: line_length}, + {className: "activeline", clearOnEnter:true}); + } + else{ + if(marker){ + marker.clear(); + } + } + } } } else { reset_values(); @@ -125,6 +143,8 @@ function ajax_check_code(url, method_type, data_type, data, uid) var global_editor = {}; var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val(); +var err_lineno; +var marker; $(document).ready(function(){ if(is_exercise == "True" && can_skip == "False"){ setTimeout(function() {show_solution();}, delay_time*1000); @@ -148,6 +168,7 @@ $(document).ready(function(){ mode: mode_dict[lang], gutter: true, lineNumbers: true, + styleSelectedText: true, onChange: function (instance, changes) { render(); } diff --git a/yaksh/templates/yaksh/error_template.html b/yaksh/templates/yaksh/error_template.html index 61657ae..301020e 100644 --- a/yaksh/templates/yaksh/error_template.html +++ b/yaksh/templates/yaksh/error_template.html @@ -3,7 +3,6 @@ {% endblock %} {% load custom_filters %} - {% if error_message %} {% for error in error_message %} @@ -35,6 +34,7 @@ </tr> <tr> {% if error.traceback %} + <input type="hidden" id="err_lineno" value="{{error.line_no}}"> <td><b>Full Traceback: </b></td> <td><pre>{{error.traceback}}</pre></td> {% endif %} diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index b65073a..ebfe066 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -11,6 +11,10 @@ .CodeMirror{ border-style: groove; } + .activeline { + background: #FBC2C4 !important; + color: #8a1f11 !important; + } </style> {% endblock %} @@ -221,7 +225,7 @@ question_type = "{{ question.type }}" {% if question.type == "integer" %} Enter Integer:<br/> - <input autofocus name="answer" type="number" id="integer" value={{ last_attempt|safe }} /> + <input autofocus name="answer" type="number" id="integer" value="{{ last_attempt|safe }}" /> <br/><br/> {% endif %} @@ -233,7 +237,7 @@ question_type = "{{ question.type }}" {% if question.type == "float" %} Enter Decimal Value :<br/> - <input autofocus name="answer" type="number" step="any" id="float" value={{ last_attempt|safe }} /> + <input autofocus name="answer" type="number" step="any" id="float" value="{{ last_attempt|safe }}" /> <br/><br/> {% endif %} diff --git a/yaksh/test_models.py b/yaksh/test_models.py index 41730c3..3bf8a00 100644 --- a/yaksh/test_models.py +++ b/yaksh/test_models.py @@ -630,6 +630,15 @@ class QuestionPaperTestCases(unittest.TestCase): # All active questions self.questions = Question.objects.filter(active=True, user=self.user) self.quiz = Quiz.objects.get(description="demo quiz 1") + self.quiz_with_time_between_attempts = Quiz.objects.create( + description="demo quiz with time between attempts", + start_date_time=datetime(2015, 10, 9, 10, 8, 15, 0, tzinfo=pytz.utc), + end_date_time=datetime(2199, 10, 9, 10, 8, 15, 0, tzinfo=pytz.utc), + duration=30, active=True, + attempts_allowed=3, time_between_attempts=1.0, + pass_criteria=0, + instructions="Demo Instructions" + ) # create question paper with only fixed questions self.question_paper_fixed_questions = QuestionPaper.objects.create( @@ -657,6 +666,12 @@ class QuestionPaperTestCases(unittest.TestCase): shuffle_questions=True ) + self.question_paper_with_time_between_attempts = QuestionPaper.objects.create( + quiz=self.quiz_with_time_between_attempts, + total_marks=0.0, + shuffle_questions=True + ) + self.question_paper.fixed_question_order = "{0}, {1}".format( self.questions[3].id, self.questions[5].id ) @@ -784,8 +799,10 @@ class QuestionPaperTestCases(unittest.TestCase): answerpaper.passed = True answerpaper.save() # test can_attempt_now(self): - self.assertFalse(self.question_paper.can_attempt_now(self.user, - self.course.id)) + result = (False, u'You cannot attempt demo quiz 1 quiz more than 1 time(s)') + self.assertEquals( + self.question_paper.can_attempt_now(self.user, self.course.id), result + ) # trying to create an answerpaper with same parameters passed. answerpaper2 = self.question_paper.make_answerpaper(self.user, self.ip, attempt_num, @@ -794,6 +811,46 @@ class QuestionPaperTestCases(unittest.TestCase): self.assertEqual(answerpaper, answerpaper2) + def test_time_between_attempt(self): + """ Test make_answerpaper() method of Question Paper""" + already_attempted = self.attempted_papers.count() + attempt_num = 1 + + self.first_start_time = timezone.now() + self.first_end_time = self.first_start_time + timedelta(minutes=20) + self.second_start_time = self.first_start_time + timedelta(minutes=30) + self.second_end_time = self.second_start_time + timedelta(minutes=20) + + # create answerpaper + self.first_answerpaper = AnswerPaper( + user=self.user, + question_paper=self.question_paper_with_time_between_attempts, + start_time=self.first_start_time, + end_time=self.first_end_time, + user_ip=self.ip, + course=self.course, + attempt_number=attempt_num + ) + self.first_answerpaper.passed = True + self.first_answerpaper.save() + + self.second_answerpaper = AnswerPaper( + user=self.user, + question_paper=self.question_paper_with_time_between_attempts, + start_time=self.second_start_time, + end_time=self.second_end_time, + user_ip=self.ip, + course=self.course, + attempt_number=attempt_num + 1 + ) + self.second_answerpaper.passed = True + self.second_answerpaper.save() + + result = (False, u'You cannot start the next attempt for this quiz before 1.0 hour(s)') + self.assertEquals( + self.question_paper_with_time_between_attempts.can_attempt_now(self.user, self.course.id), result + ) + def test_create_trial_paper_to_test_quiz(self): qu_list = [str(self.questions_list[0]), str(self.questions_list[1])] diff --git a/yaksh/urls.py b/yaksh/urls.py index dd450ba..3611573 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import patterns, url +from django.conf.urls import url from yaksh import views urlpatterns = [ diff --git a/yaksh/urls_password_reset.py b/yaksh/urls_password_reset.py index c1e36c6..4a7ddf3 100644 --- a/yaksh/urls_password_reset.py +++ b/yaksh/urls_password_reset.py @@ -1,4 +1,4 @@ -from django.conf.urls import patterns, url +from django.conf.urls import url from django.contrib.auth.views import password_reset, password_reset_confirm,\ password_reset_done, password_reset_complete, password_change,\ password_change_done diff --git a/yaksh/views.py b/yaksh/views.py index 1cb77fc..e1c1889 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -7,7 +7,7 @@ import csv from django.http import HttpResponse, JsonResponse from django.core.urlresolvers import reverse from django.contrib.auth import login, logout, authenticate -from django.shortcuts import render_to_response, get_object_or_404, redirect +from django.shortcuts import render, get_object_or_404, redirect from django.template import RequestContext, Context, Template from django.template.loader import get_template, render_to_string from django.http import Http404 @@ -65,14 +65,14 @@ def my_redirect(url): return redirect(URL_ROOT + url) -def my_render_to_response(template, context=None, **kwargs): +def my_render_to_response(request, template, context=None, **kwargs): """Overridden render_to_response. """ if context is None: context = {'URL_ROOT': URL_ROOT} else: context['URL_ROOT'] = URL_ROOT - return render_to_response(template, context, **kwargs) + return render(request, template, context, **kwargs) def is_moderator(user): @@ -115,7 +115,6 @@ def user_register(request): Create a user and corresponding profile and store roll_number also.""" user = request.user - ci = RequestContext(request) if user.is_authenticated(): return my_redirect("/exam/quizzes/") context = {} @@ -130,16 +129,18 @@ def user_register(request): success, msg = send_user_mail(user_email, key) context = {'activation_msg': msg} return my_render_to_response( + request, 'yaksh/activation_status.html', context ) return index(request) else: - return my_render_to_response('yaksh/register.html', {'form': form}, - context_instance=ci) + return my_render_to_response( + request, 'yaksh/register.html', {'form': form} + ) else: form = UserRegisterForm() return my_render_to_response( - 'yaksh/register.html', {'form': form}, context_instance=ci + request, 'yaksh/register.html', {'form': form} ) @@ -147,7 +148,7 @@ def user_logout(request): """Show a page to inform user that the quiz has been compeleted.""" logout(request) context = {'message': "You have been logged out successfully"} - return my_render_to_response('yaksh/complete.html', context) + return my_render_to_response(request, 'yaksh/complete.html', context) @login_required @@ -156,7 +157,6 @@ def user_logout(request): def quizlist_user(request, enrolled=None, msg=None): """Show All Quizzes that is available to logged-in user.""" user = request.user - ci = RequestContext(request) if request.method == "POST": course_code = request.POST.get('course_code') @@ -178,9 +178,7 @@ def quizlist_user(request, enrolled=None, msg=None): context = {'user': user, 'courses': courses, 'title': title, 'msg': msg} - return my_render_to_response( - "yaksh/quizzes_user.html", context, context_instance=ci - ) + return my_render_to_response(request, "yaksh/quizzes_user.html", context) @login_required @@ -190,14 +188,13 @@ def results_user(request): user = request.user papers = AnswerPaper.objects.get_user_answerpapers(user) context = {'papers': papers} - return my_render_to_response("yaksh/results_user.html", context) + return my_render_to_response(request, "yaksh/results_user.html", context) @login_required @email_verified def add_question(request, question_id=None): user = request.user - ci = RequestContext(request) test_case_type = None if question_id is None: @@ -259,7 +256,7 @@ def add_question(request, question_id=None): 'uploaded_files': uploaded_files } return my_render_to_response( - "yaksh/add_question.html", context, context_instance=ci + request, "yaksh/add_question.html", context ) qform = QuestionForm(instance=question) @@ -284,7 +281,7 @@ def add_question(request, question_id=None): context = {'qform': qform, 'fileform': fileform, 'question': question, 'formsets': formsets, 'uploaded_files': uploaded_files} return my_render_to_response( - "yaksh/add_question.html", context, context_instance=ci + request, "yaksh/add_question.html", context ) @@ -294,7 +291,6 @@ def add_quiz(request, quiz_id=None, course_id=None): """To add a new quiz in the database. Create a new quiz and store it.""" user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this course !') if quiz_id: @@ -325,16 +321,13 @@ def add_quiz(request, quiz_id=None, course_id=None): context["course_id"] = course_id context["quiz"] = quiz context["form"] = form - return my_render_to_response( - 'yaksh/add_quiz.html', context, context_instance=ci - ) + return my_render_to_response(request, 'yaksh/add_quiz.html', context) @login_required @email_verified def add_exercise(request, quiz_id=None, course_id=None): user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this course !') if quiz_id: @@ -374,9 +367,7 @@ def add_exercise(request, quiz_id=None, course_id=None): context["exercise"] = quiz context["course_id"] = course_id context["form"] = form - return my_render_to_response( - 'yaksh/add_exercise.html', context, context_instance=ci - ) + return my_render_to_response(request, 'yaksh/add_exercise.html', context) @login_required @@ -386,7 +377,6 @@ def prof_manage(request, msg=None): """Take credentials of the user with professor/moderator rights/permissions and log in.""" user = request.user - ci = RequestContext(request) if not user.is_authenticated(): return my_redirect('/exam/login') if not is_moderator(user): @@ -416,7 +406,7 @@ def prof_manage(request, msg=None): 'trial_paper': trial_paper, 'msg': msg } return my_render_to_response( - 'yaksh/moderator_dashboard.html', context, context_instance=ci + request, 'yaksh/moderator_dashboard.html', context ) @@ -424,7 +414,6 @@ def user_login(request): """Take the credentials of the user and log the user in.""" user = request.user - ci = RequestContext(request) context = {} if user.is_authenticated(): return index(request) @@ -444,8 +433,7 @@ def user_login(request): form = UserLoginForm() context = {"form": form} - return my_render_to_response('yaksh/login.html', context, - context_instance=ci) + return my_render_to_response(request, 'yaksh/login.html', context) @login_required @@ -455,7 +443,6 @@ def start(request, questionpaper_id=None, attempt_num=None, course_id=None, """Check the user cedentials and if any quiz is available, start the exam.""" user = request.user - ci = RequestContext(request) # check conditions try: quest_paper = QuestionPaper.objects.get(id=questionpaper_id) @@ -534,9 +521,8 @@ def start(request, questionpaper_id=None, attempt_num=None, course_id=None, previous_question=last_attempt.current_question() ) # allowed to start - if not quest_paper.can_attempt_now(user, course_id): - msg = "You cannot attempt {0} quiz more than {1} time(s)".format( - quest_paper.quiz.description, quest_paper.quiz.attempts_allowed) + if not quest_paper.can_attempt_now(user, course_id)[0]: + msg = quest_paper.can_attempt_now(user, course_id)[1] if is_moderator(user): return prof_manage(request, msg=msg) return view_module(request, module_id=module_id, course_id=course_id, @@ -555,8 +541,7 @@ def start(request, questionpaper_id=None, attempt_num=None, course_id=None, } if is_moderator(user): context["status"] = "moderator" - return my_render_to_response('yaksh/intro.html', context, - context_instance=ci) + return my_render_to_response(request, 'yaksh/intro.html', context) else: ip = request.META['REMOTE_ADDR'] if not hasattr(user, 'profile'): @@ -565,10 +550,11 @@ def start(request, questionpaper_id=None, attempt_num=None, course_id=None, new_paper = quest_paper.make_answerpaper(user, ip, attempt_number, course_id) if new_paper.status == 'inprogress': - return show_question(request, new_paper.current_question(), - new_paper, course_id=course_id, - module_id=module_id, previous_question=None - ) + return show_question( + request, new_paper.current_question(), + new_paper, course_id=course_id, + module_id=module_id, previous_question=None + ) else: msg = 'You have already finished the quiz!' raise Http404(msg) @@ -647,9 +633,7 @@ def show_question(request, question, paper, error_message=None, notification=Non last_attempt = answers[0].answer if last_attempt: context['last_attempt'] = last_attempt.encode('unicode-escape') - ci = RequestContext(request) - return my_render_to_response('yaksh/question.html', context, - context_instance=ci) + return my_render_to_response(request, 'yaksh/question.html', context) @login_required @@ -903,8 +887,7 @@ def quit(request, reason=None, attempt_num=None, questionpaper_id=None, course_id=course_id) context = {'paper': paper, 'message': reason, 'course_id': course_id, 'module_id': module_id} - return my_render_to_response('yaksh/quit.html', context, - context_instance=RequestContext(request)) + return my_render_to_response(request, 'yaksh/quit.html', context) @login_required @@ -917,7 +900,7 @@ def complete(request, reason=None, attempt_num=None, questionpaper_id=None, message = reason or "An Unexpected Error occurred. Please contact your '\ 'instructor/administrator.'" context = {'message': message} - return my_render_to_response('yaksh/complete.html', context) + return my_render_to_response(request, 'yaksh/complete.html', context) else: q_paper = QuestionPaper.objects.get(id=questionpaper_id) paper = AnswerPaper.objects.get( @@ -937,14 +920,13 @@ def complete(request, reason=None, attempt_num=None, questionpaper_id=None, 'course_id': course_id, 'learning_unit': learning_unit} if is_moderator(user): context['user'] = "moderator" - return my_render_to_response('yaksh/complete.html', context) + return my_render_to_response(request, 'yaksh/complete.html', context) @login_required @email_verified def add_course(request, course_id=None): user = request.user - ci = RequestContext(request) if course_id: course = Course.objects.get(id=course_id) if not course.is_creator(user) and not course.is_teacher(user): @@ -963,12 +945,12 @@ def add_course(request, course_id=None): return my_redirect('/exam/manage/courses') else: return my_render_to_response( - 'yaksh/add_course.html', {'form': form}, context_instance=ci + request, 'yaksh/add_course.html', {'form': form} ) else: form = CourseForm(instance=course) return my_render_to_response( - 'yaksh/add_course.html', {'form': form}, context_instance=ci + request, 'yaksh/add_course.html', {'form': form} ) @@ -976,7 +958,6 @@ def add_course(request, course_id=None): @email_verified def enroll_request(request, course_id): user = request.user - ci = RequestContext(request) course = get_object_or_404(Course, pk=course_id) if not course.is_active_enrollment() and course.hidden: msg = ( @@ -996,7 +977,6 @@ def enroll_request(request, course_id): @email_verified def self_enroll(request, course_id): user = request.user - ci = RequestContext(request) course = get_object_or_404(Course, pk=course_id) if course.is_self_enroll(): was_rejected = False @@ -1011,7 +991,6 @@ def self_enroll(request, course_id): @email_verified def courses(request): user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page') courses = Course.objects.filter( @@ -1020,15 +999,13 @@ def courses(request): teachers=user, is_trial=False).order_by('-active', '-id') context = {'courses': courses, "allotted_courses": allotted_courses, "type": "courses"} - return my_render_to_response('yaksh/courses.html', context, - context_instance=ci) + return my_render_to_response(request, 'yaksh/courses.html', context) @login_required @email_verified def course_detail(request, course_id): user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page') @@ -1038,7 +1015,7 @@ def course_detail(request, course_id): raise Http404('This course does not belong to you') return my_render_to_response( - 'yaksh/course_detail.html', {'course': course}, context_instance=ci + request, 'yaksh/course_detail.html', {'course': course} ) @@ -1046,7 +1023,6 @@ def course_detail(request, course_id): @email_verified def enroll(request, course_id, user_id=None, was_rejected=False): user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page') @@ -1068,7 +1044,7 @@ def enroll(request, course_id, user_id=None, was_rejected=False): enroll_ids = [user_id] if not enroll_ids: return my_render_to_response( - 'yaksh/course_detail.html', {'course': course}, context_instance=ci + request, 'yaksh/course_detail.html', {'course': course} ) users = User.objects.filter(id__in=enroll_ids) course.enroll(was_rejected, *users) @@ -1079,7 +1055,6 @@ def enroll(request, course_id, user_id=None, was_rejected=False): @email_verified def send_mail(request, course_id, user_id=None): user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page') @@ -1103,16 +1078,13 @@ def send_mail(request, course_id, user_id=None): 'course': course, 'message': message, 'state': 'mail' } - return my_render_to_response( - 'yaksh/course_detail.html', context, context_instance=ci - ) + return my_render_to_response(request, 'yaksh/course_detail.html', context) @login_required @email_verified def reject(request, course_id, user_id=None, was_enrolled=False): user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page') @@ -1127,8 +1099,8 @@ def reject(request, course_id, user_id=None, was_enrolled=False): if not reject_ids: message = "Please select atleast one User" return my_render_to_response( - 'yaksh/course_detail.html', {'course': course, 'message': message}, - context_instance=ci + request, 'yaksh/course_detail.html', + {'course': course, 'message': message}, ) users = User.objects.filter(id__in=reject_ids) course.reject(was_enrolled, *users) @@ -1168,8 +1140,9 @@ def show_statistics(request, questionpaper_id, attempt_number=None, context = {'quiz': quiz, 'attempts': attempt_numbers, 'questionpaper_id': questionpaper_id, 'course_id': course_id} - return my_render_to_response('yaksh/statistics_question.html', context, - context_instance=RequestContext(request)) + return my_render_to_response( + request, 'yaksh/statistics_question.html', context + ) total_attempt = AnswerPaper.objects.get_count(questionpaper_id, attempt_number, course_id) @@ -1183,8 +1156,9 @@ def show_statistics(request, questionpaper_id, attempt_number=None, 'questionpaper_id': questionpaper_id, 'attempts': attempt_numbers, 'total': total_attempt, 'course_id': course_id} - return my_render_to_response('yaksh/statistics_question.html', context, - context_instance=RequestContext(request)) + return my_render_to_response( + request, 'yaksh/statistics_question.html', context + ) @login_required @@ -1193,7 +1167,6 @@ def monitor(request, quiz_id=None, course_id=None): """Monitor the progress of the papers taken so far.""" user = request.user - ci = RequestContext(request) if not user.is_authenticated() or not is_moderator(user): raise Http404('You are not allowed to view this page!') @@ -1206,9 +1179,7 @@ def monitor(request, quiz_id=None, course_id=None): "papers": [], "course_details": course_details, "msg": "Monitor" } - return my_render_to_response( - 'yaksh/monitor.html', context, context_instance=ci - ) + return my_render_to_response(request, 'yaksh/monitor.html', context) # quiz_id is not None. try: quiz = get_object_or_404(Quiz, id=quiz_id) @@ -1254,8 +1225,7 @@ def monitor(request, quiz_id=None, course_id=None): "attempt_numbers": attempt_numbers, "course": course } - return my_render_to_response('yaksh/monitor.html', context, - context_instance=ci) + return my_render_to_response(request, 'yaksh/monitor.html', context) @csrf_exempt @@ -1279,7 +1249,7 @@ def ajax_questions_filter(request): questions = list(Question.objects.filter(**filter_dict)) return my_render_to_response( - 'yaksh/ajax_question_filter.html', {'questions': questions} + request, 'yaksh/ajax_question_filter.html', {'questions': questions} ) @@ -1408,9 +1378,7 @@ def design_questionpaper(request, quiz_id, questionpaper_id=None, 'course_id': course_id } return my_render_to_response( - 'yaksh/design_questionpaper.html', - context, - context_instance=RequestContext(request) + request, 'yaksh/design_questionpaper.html', context ) @@ -1420,7 +1388,6 @@ def show_all_questions(request): """Show a list of all the questions currently in the database.""" user = request.user - ci = RequestContext(request) context = {} if not is_moderator(user): raise Http404("You are not allowed to view this page !") @@ -1497,8 +1464,7 @@ def show_all_questions(request): user=user).distinct() context['questions'] = search_result - return my_render_to_response('yaksh/showquestions.html', context, - context_instance=ci) + return my_render_to_response(request, 'yaksh/showquestions.html', context) @login_required @@ -1512,8 +1478,7 @@ def user_data(request, user_id, questionpaper_id=None, course_id=None): data = AnswerPaper.objects.get_user_data(user, questionpaper_id, course_id) context = {'data': data, 'course_id': course_id} - return my_render_to_response('yaksh/user_data.html', context, - context_instance=RequestContext(request)) + return my_render_to_response(request, 'yaksh/user_data.html', context) def _expand_questions(questions, field_list): @@ -1602,7 +1567,6 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None, and update all their marks and also give comments for each paper. """ current_user = request.user - ci = RequestContext(request) if not current_user.is_authenticated() or not is_moderator(current_user): raise Http404('You are not allowed to view this page!') course_details = Course.objects.filter(Q(creator=current_user) | @@ -1676,9 +1640,7 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None, if course_status.exists(): course_status.first().set_grade() - return my_render_to_response( - 'yaksh/grade_user.html', context, context_instance=ci - ) + return my_render_to_response(request, 'yaksh/grade_user.html', context) @login_required @@ -1687,13 +1649,12 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None, def view_profile(request): """ view moderators and users profile """ user = request.user - ci = RequestContext(request) if is_moderator(user): template = 'manage.html' else: template = 'user.html' context = {'template': template, 'user': user} - return my_render_to_response('yaksh/view_profile.html', context) + return my_render_to_response(request, 'yaksh/view_profile.html', context) @login_required @@ -1702,7 +1663,6 @@ def edit_profile(request): """ edit profile details facility for moderator and students """ user = request.user - ci = RequestContext(request) if is_moderator(user): template = 'manage.html' else: @@ -1722,19 +1682,17 @@ def edit_profile(request): form_data.user.last_name = request.POST['last_name'] form_data.user.save() form_data.save() - return my_render_to_response( - 'yaksh/profile_updated.html', context_instance=ci - ) + return my_render_to_response(request, 'yaksh/profile_updated.html') else: context['form'] = form return my_render_to_response( - 'yaksh/editprofile.html', context, context_instance=ci + request, 'yaksh/editprofile.html', context ) else: form = ProfileForm(user=user, instance=profile) context['form'] = form return my_render_to_response( - 'yaksh/editprofile.html', context, context_instance=ci + request, 'yaksh/editprofile.html', context ) @@ -1743,7 +1701,6 @@ def edit_profile(request): def search_teacher(request, course_id): """ search teachers for the course """ user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page!') @@ -1770,9 +1727,7 @@ def search_teacher(request, course_id): ) context['success'] = True context['teachers'] = teachers - return my_render_to_response( - 'yaksh/addteacher.html', context, context_instance=ci - ) + return my_render_to_response(request, 'yaksh/addteacher.html', context) @login_required @@ -1781,7 +1736,6 @@ def add_teacher(request, course_id): """ add teachers to the course """ user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page!') @@ -1800,9 +1754,7 @@ def add_teacher(request, course_id): course.add_teachers(*teachers) context['status'] = True context['teachers_added'] = teachers - return my_render_to_response( - 'yaksh/addteacher.html', context, context_instance=ci - ) + return my_render_to_response(request, 'yaksh/addteacher.html', context) @login_required @@ -1882,7 +1834,9 @@ def view_answerpaper(request, questionpaper_id, course_id): ).exists() context = {'data': data, 'quiz': quiz, "has_user_assignment": has_user_assignment} - return my_render_to_response('yaksh/view_answerpaper.html', context) + return my_render_to_response( + request, 'yaksh/view_answerpaper.html', context + ) else: return my_redirect('/exam/quizzes/') @@ -1892,7 +1846,6 @@ def view_answerpaper(request, questionpaper_id, course_id): def create_demo_course(request): """ creates a demo course for user """ user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404("You are not allowed to view this page") demo_course = Course() @@ -1915,7 +1868,7 @@ def grader(request, extra_context=None): context = {'courses': user_courses} if extra_context: context.update(extra_context) - return my_render_to_response('yaksh/regrade.html', context) + return my_render_to_response(request, 'yaksh/regrade.html', context) @login_required @@ -1999,14 +1952,13 @@ def download_course_csv(request, course_id): def activate_user(request, key): - ci = RequestContext(request) profile = get_object_or_404(Profile, activation_key=key) context = {} context['success'] = False if profile.is_email_verified: context['activation_msg'] = "Your account is already verified" return my_render_to_response( - 'yaksh/activation_status.html', context, context_instance=ci + request, 'yaksh/activation_status.html', context ) if timezone.now() > profile.key_expiry_time: @@ -2020,12 +1972,11 @@ def activate_user(request, key): profile.save() context['msg'] = "Your account is activated" return my_render_to_response( - 'yaksh/activation_status.html', context, context_instance=ci + request, 'yaksh/activation_status.html', context ) def new_activation(request, email=None): - ci = RequestContext(request) context = {} if request.method == "POST": email = request.POST.get('email') @@ -2036,15 +1987,13 @@ def new_activation(request, email=None): context['email_err_msg'] = "Multiple entries found for this email"\ "Please change your email" return my_render_to_response( - 'yaksh/activation_status.html', context, context_instance=ci + request, 'yaksh/activation_status.html', context ) except ObjectDoesNotExist: context['success'] = False context['msg'] = "Your account is not verified. \ Please verify your account" - return render_to_response( - 'yaksh/activation_status.html', context, context_instance=ci - ) + return render_to_response('yaksh/activation_status.html', context) if not user.profile.is_email_verified: user.profile.activation_key = generate_activation_key(user.username) @@ -2063,13 +2012,12 @@ def new_activation(request, email=None): context['activation_msg'] = "Your account is already verified" return my_render_to_response( - 'yaksh/activation_status.html', context, context_instance=ci + request, 'yaksh/activation_status.html', context ) def update_email(request): context = {} - ci = RequestContext(request) if request.method == "POST": email = request.POST.get('email') username = request.POST.get('username') @@ -2080,7 +2028,7 @@ def update_email(request): else: context['email_err_msg'] = "Please Update your email" return my_render_to_response( - 'yaksh/activation_status.html', context, context_instance=ci + request, 'yaksh/activation_status.html', context ) @@ -2119,7 +2067,6 @@ def download_assignment_file(request, quiz_id, question_id=None, user_id=None): @email_verified def upload_users(request, course_id): user = request.user - ci = RequestContext(request) course = get_object_or_404(Course, pk=course_id) context = {'course': course} @@ -2129,32 +2076,35 @@ def upload_users(request, course_id): if request.method == 'POST': if 'csv_file' not in request.FILES: context['message'] = "Please upload a CSV file." - return my_render_to_response('yaksh/course_detail.html', context, - context_instance=ci) + return my_render_to_response( + request, 'yaksh/course_detail.html', context + ) csv_file = request.FILES['csv_file'] is_csv_file, dialect = is_csv(csv_file) if not is_csv_file: context['message'] = "The file uploaded is not a CSV file." - return my_render_to_response('yaksh/course_detail.html', context, - context_instance=ci) + return my_render_to_response( + request, 'yaksh/course_detail.html', context + ) required_fields = ['firstname', 'lastname', 'email'] try: reader = csv.DictReader(csv_file.read().decode('utf-8').splitlines(), dialect=dialect) except TypeError: context['message'] = "Bad CSV file" - return my_render_to_response('yaksh/course_detail.html', context, - context_instance=ci) + return my_render_to_response( + request, 'yaksh/course_detail.html', context + ) stripped_fieldnames = [field.strip().lower() for field in reader.fieldnames] for field in required_fields: if field not in stripped_fieldnames: context['message'] = "The CSV file does not contain the required headers" - return my_render_to_response('yaksh/course_detail.html', context, - context_instance=ci) + return my_render_to_response( + request, 'yaksh/course_detail.html', context + ) reader.fieldnames = stripped_fieldnames context['upload_details'] = _read_user_csv(reader, course) - return my_render_to_response('yaksh/course_detail.html', context, - context_instance=ci) + return my_render_to_response(request, 'yaksh/course_detail.html', context) def _read_user_csv(reader, course): @@ -2312,7 +2262,6 @@ def download_yaml_template(request): @email_verified def edit_lesson(request, lesson_id=None, course_id=None): user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page!') if lesson_id: @@ -2365,9 +2314,7 @@ def edit_lesson(request, lesson_id=None, course_id=None): context['lesson_file_form'] = lesson_files_form context['lesson_files'] = lesson_files context['course_id'] = course_id - return my_render_to_response( - 'yaksh/add_lesson.html', context, context_instance=ci - ) + return my_render_to_response(request, 'yaksh/add_lesson.html', context) @login_required @@ -2408,14 +2355,13 @@ def show_lesson(request, lesson_id, module_id, course_id): 'course': course, 'state': "lesson", "all_modules": all_modules, 'learning_units': learning_units, "current_unit": learn_unit, 'learning_module': learn_module} - return my_render_to_response('yaksh/show_video.html', context) + return my_render_to_response(request, 'yaksh/show_video.html', context) @login_required @email_verified def design_module(request, module_id, course_id=None): user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page!') context = {} @@ -2481,15 +2427,13 @@ def design_module(request, module_id, course_id=None): context['status'] = 'design' context['module_id'] = module_id context['course_id'] = course_id - return my_render_to_response('yaksh/add_module.html', context, - context_instance=ci) + return my_render_to_response(request, 'yaksh/add_module.html', context) @login_required @email_verified def add_module(request, module_id=None, course_id=None): user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page!') redirect_url = "/exam/manage/courses/all_learning_module/" @@ -2522,8 +2466,7 @@ def add_module(request, module_id=None, course_id=None): context['module_form'] = module_form context['course_id'] = course_id context['status'] = "add" - return my_render_to_response("yaksh/add_module.html", - context, context_instance=ci) + return my_render_to_response(request, "yaksh/add_module.html", context) @login_required @@ -2534,7 +2477,7 @@ def show_all_quizzes(request): raise Http404('You are not allowed to view this page!') quizzes = Quiz.objects.filter(creator=user, is_trial=False) context = {"quizzes": quizzes, "type": "quiz"} - return my_render_to_response('yaksh/courses.html', context) + return my_render_to_response(request, 'yaksh/courses.html', context) @login_required @@ -2545,7 +2488,7 @@ def show_all_lessons(request): raise Http404('You are not allowed to view this page!') lessons = Lesson.objects.filter(creator=user) context = {"lessons": lessons, "type": "lesson"} - return my_render_to_response('yaksh/courses.html', context) + return my_render_to_response(request, 'yaksh/courses.html', context) @login_required @@ -2557,7 +2500,7 @@ def show_all_modules(request): learning_modules = LearningModule.objects.filter( creator=user, is_trial=False) context = {"learning_modules": learning_modules, "type": "learning_module"} - return my_render_to_response('yaksh/courses.html', context) + return my_render_to_response(request, 'yaksh/courses.html', context) @login_required @@ -2632,7 +2575,6 @@ def get_next_unit(request, course_id, module_id, current_unit_id=None, @email_verified def design_course(request, course_id): user = request.user - ci = RequestContext(request) if not is_moderator(user): raise Http404('You are not allowed to view this page!') course = Course.objects.get(id=course_id) @@ -2686,8 +2628,9 @@ def design_course(request, course_id): context['added_learning_modules'] = added_learning_modules context['learning_modules'] = learning_modules context['course_id'] = course_id - return my_render_to_response('yaksh/design_course_session.html', context, - context_instance=ci) + return my_render_to_response( + request, 'yaksh/design_course_session.html', context + ) @login_required @@ -2722,7 +2665,7 @@ def view_module(request, module_id, course_id, msg=None): context['course'] = course context['state'] = "module" context['msg'] = msg - return my_render_to_response('yaksh/show_video.html', context) + return my_render_to_response(request, 'yaksh/show_video.html', context) @login_required @@ -2746,7 +2689,7 @@ def course_modules(request, course_id, msg=None): if not course_status.grade: course_status.set_grade() context['grade'] = course_status.get_grade() - return my_render_to_response('yaksh/course_modules.html', context) + return my_render_to_response(request, 'yaksh/course_modules.html', context) @login_required @@ -2763,7 +2706,7 @@ def course_status(request, course_id): 'course': course, 'students': students, 'state': 'course_status', 'modules': course.get_learning_modules() } - return my_render_to_response('yaksh/course_detail.html', context) + return my_render_to_response(request, 'yaksh/course_detail.html', context) def _update_unit_status(course_id, user, unit): @@ -2797,5 +2740,5 @@ def preview_questionpaper(request, questionpaper_id): } return my_render_to_response( - 'yaksh/preview_questionpaper.html', context + request, 'yaksh/preview_questionpaper.html', context ) |