summaryrefslogtreecommitdiff
path: root/yaksh
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh')
-rw-r--r--yaksh/error_messages.py3
-rw-r--r--yaksh/python_stdio_evaluator.py3
-rw-r--r--yaksh/templates/yaksh/add_question.html2
-rw-r--r--yaksh/templates/yaksh/error_template.html11
-rw-r--r--yaksh/templates/yaksh/moderator_dashboard.html6
-rw-r--r--yaksh/templatetags/custom_filters.py12
-rw-r--r--yaksh/templatetags/test_custom_filters.py11
-rw-r--r--yaksh/views.py24
8 files changed, 59 insertions, 13 deletions
diff --git a/yaksh/error_messages.py b/yaksh/error_messages.py
index f34bf28..2d27417 100644
--- a/yaksh/error_messages.py
+++ b/yaksh/error_messages.py
@@ -34,8 +34,7 @@ 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()):
+ if user_line != expected_line:
err_line_numbers.append(line_no)
return err_line_numbers
diff --git a/yaksh/python_stdio_evaluator.py b/yaksh/python_stdio_evaluator.py
index 64a2809..a1e8f72 100644
--- a/yaksh/python_stdio_evaluator.py
+++ b/yaksh/python_stdio_evaluator.py
@@ -46,6 +46,7 @@ class PythonStdIOEvaluator(BaseEvaluator):
if self.file_paths:
self.files = copy_files(self.file_paths)
submitted = compile(self.user_answer, '<string>', mode='exec')
+ self.expected_output = self.expected_output.replace('\r', '')
if self.expected_input:
self.expected_input = self.expected_input.replace('\r', '')
input_buffer = StringIO()
@@ -55,7 +56,7 @@ class PythonStdIOEvaluator(BaseEvaluator):
with redirect_stdout() as output_buffer:
exec_scope = {}
exec(submitted, exec_scope)
- self.output_value = output_buffer.getvalue().rstrip("\n")
+ self.output_value = output_buffer.getvalue()
return self.output_value
def check_code(self):
diff --git a/yaksh/templates/yaksh/add_question.html b/yaksh/templates/yaksh/add_question.html
index 692af48..c4cd8a7 100644
--- a/yaksh/templates/yaksh/add_question.html
+++ b/yaksh/templates/yaksh/add_question.html
@@ -50,7 +50,9 @@
{% for form in formset %}
<div class="link-formset well">
+ {% autoescape off %}
{{ form.as_p }}
+ {% endautoescape %}
</div>
{% endfor %}
diff --git a/yaksh/templates/yaksh/error_template.html b/yaksh/templates/yaksh/error_template.html
index 5530844..00fa306 100644
--- a/yaksh/templates/yaksh/error_template.html
+++ b/yaksh/templates/yaksh/error_template.html
@@ -1,4 +1,11 @@
+{% block css%}
+ <link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/dashboard.css" type="text/css" />
+{% endblock %}
+{% block script %}
+ <script src="{{ URL_ROOT }}/static/yaksh/js/jquery-ui.js"></script>
+{% endblock %}
+
{% load custom_filters %}
{% if error_message %}
<div class="container-fluid row justify-content-center">
@@ -64,8 +71,8 @@
</tr>
{% for expected,user in error.expected_output|zip:error.user_output %}
<td> {{forloop.counter}} </td>
- <td>{{expected|default:""}} </td>
- <td>{{user|default:""}}</td>
+ <td>{{expected|default:""|highlight_spaces|safe}} </td>
+ <td>{{user|default:""|highlight_spaces|safe}}</td>
{% if forloop.counter0 in error.error_line_numbers or not expected or not user %}
<td><span class ="fa fa-times text-warning"/></td>
{% else %}
diff --git a/yaksh/templates/yaksh/moderator_dashboard.html b/yaksh/templates/yaksh/moderator_dashboard.html
index 503cc72..59dd123 100644
--- a/yaksh/templates/yaksh/moderator_dashboard.html
+++ b/yaksh/templates/yaksh/moderator_dashboard.html
@@ -102,7 +102,11 @@
</tr>
{% endfor %}
</table>
- <center><button class="btn btn-danger" type="submit">Delete Selected</button></center>
+<center>
+ <button class="btn btn-danger" type="submit">
+ Delete Selected
+ <span class="glyphicon glyphicon-trash"></span>
+</button></center>
</form>
</div>
{% endif %}
diff --git a/yaksh/templatetags/custom_filters.py b/yaksh/templatetags/custom_filters.py
index b59d320..92a1169 100644
--- a/yaksh/templatetags/custom_filters.py
+++ b/yaksh/templatetags/custom_filters.py
@@ -101,3 +101,15 @@ def pygmentise_user_answer(language, answer):
style = formatter.get_style_defs('.highlight')
result = highlight(answer, lexer, formatter)
return result, style
+
+
+@register.simple_tag
+def course_grade(course, user):
+ return course.get_grade(user)
+
+
+@register.filter(name='highlight_spaces')
+def highlight_spaces(text):
+ return text.replace(
+ " ", '<span style="background-color:#ffb6db">&nbsp</span>'
+ )
diff --git a/yaksh/templatetags/test_custom_filters.py b/yaksh/templatetags/test_custom_filters.py
index eb1f0fb..9d7f246 100644
--- a/yaksh/templatetags/test_custom_filters.py
+++ b/yaksh/templatetags/test_custom_filters.py
@@ -11,7 +11,8 @@ from yaksh.models import (User, Profile, Question, Quiz, QuestionPaper,
from yaksh.templatetags.custom_filters import (completed, inprogress,
get_ordered_testcases,
- get_answer_for_arrange_options
+ get_answer_for_arrange_options,
+ highlight_spaces
)
@@ -57,6 +58,7 @@ def tearDownModule():
User.objects.get(username="teacher2000").delete()
Group.objects.all().delete()
+
class CustomFiltersTestCases(unittest.TestCase):
@classmethod
@@ -148,3 +150,10 @@ class CustomFiltersTestCases(unittest.TestCase):
self.assertSequenceEqual(testcases, ordered_testcases)
new_answerpaper.delete()
+
+ def test_highlight_spaces(self):
+ expected_output = "A "
+ highlighted_output = highlight_spaces(expected_output)
+ self.assertEqual(highlighted_output,
+ 'A<span style="background-color:#ffb6db">&nbsp</span>'
+ )
diff --git a/yaksh/views.py b/yaksh/views.py
index 0bf91eb..56f1873 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -6,10 +6,12 @@ from django.shortcuts import render, get_object_or_404, redirect
from django.template import Context, Template
from django.http import Http404
from django.db.models import Max, Q, F
+from django.db import models
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group
from django.forms.models import inlineformset_factory
+from django.forms import fields
from django.utils import timezone
from django.core.exceptions import (
MultipleObjectsReturned, ObjectDoesNotExist
@@ -97,6 +99,13 @@ def get_html_text(md_text):
return Markdown().convert(md_text)
+def formfield_callback(field):
+ if (isinstance(field, models.TextField) and field.name == 'expected_output'
+ or field.name == 'expected_input'):
+ return fields.CharField(strip=False)
+ return field.formfield()
+
+
@email_verified
def index(request, next_url=None):
"""The start page.
@@ -243,8 +252,12 @@ def add_question(request, question_id=None):
file.toggle_hide_status()
formsets = []
for testcase in TestCase.__subclasses__():
- formset = inlineformset_factory(Question, testcase, extra=0,
- fields='__all__')
+
+ formset = inlineformset_factory(
+ Question, testcase, extra=0,
+ fields='__all__',
+ formfield_callback=formfield_callback
+ )
formsets.append(formset(
request.POST, request.FILES, instance=question
)
@@ -929,10 +942,9 @@ def complete(request, reason=None, attempt_num=None, questionpaper_id=None,
"""Show a page to inform user that the quiz has been completed."""
user = request.user
if questionpaper_id is None:
- message = (
- reason or "An Unexpected Error occurred."
- " Please contact your instructor/administrator."
- )
+ message = reason or ("An Unexpected Error occurred. Please "
+ "contact your instructor/administrator."
+ )
context = {'message': message}
return my_render_to_response(request, 'yaksh/complete.html', context)
else: