Fixed #5831 -- Made sure the ForNode reports the correct source of an exception happening in one of the loops. Thanks, Charmless and vladmos.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16605 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jannis Leidel 2011-08-12 14:15:17 +00:00
parent 1d485cf14f
commit 958e049d4d
5 changed files with 57 additions and 6 deletions

View File

@ -78,7 +78,7 @@ class DebugNodeList(NodeList):
from sys import exc_info from sys import exc_info
wrapped = TemplateSyntaxError(u'Caught %s while rendering: %s' % wrapped = TemplateSyntaxError(u'Caught %s while rendering: %s' %
(e.__class__.__name__, force_unicode(e, errors='replace'))) (e.__class__.__name__, force_unicode(e, errors='replace')))
wrapped.source = node.source wrapped.source = getattr(e, 'template_node_source', node.source)
wrapped.exc_info = exc_info() wrapped.exc_info = exc_info()
raise wrapped, None, wrapped.exc_info[2] raise wrapped, None, wrapped.exc_info[2]
return result return result

View File

@ -227,8 +227,21 @@ class ForNode(Node):
context.update(unpacked_vars) context.update(unpacked_vars)
else: else:
context[self.loopvars[0]] = item context[self.loopvars[0]] = item
for node in self.nodelist_loop: # In TEMPLATE_DEBUG mode providing source of the node which
nodelist.append(node.render(context)) # actually raised an exception to DefaultNodeList.render_node
if settings.TEMPLATE_DEBUG:
for node in self.nodelist_loop:
try:
nodelist.append(node.render(context))
except Exception, e:
if not hasattr(e, 'template_node_source'):
from sys import exc_info
e.template_node_source = node.source
raise e, None, exc_info()[2]
raise
else:
for node in self.nodelist_loop:
nodelist.append(node.render(context))
if pop_context: if pop_context:
# The loop variables were pushed on to the context so pop them # The loop variables were pushed on to the context so pop them
# off again. This is necessary because the tag lets the length # off again. This is necessary because the tag lets the length

View File

@ -1,8 +1,8 @@
from django.conf import settings
from django.template import VariableNode, Context, TemplateSyntaxError
from django.template.loader import get_template_from_string from django.template.loader import get_template_from_string
from django.template import VariableNode
from django.utils.unittest import TestCase from django.utils.unittest import TestCase
class NodelistTest(TestCase): class NodelistTest(TestCase):
def test_for(self): def test_for(self):
@ -28,3 +28,37 @@ class NodelistTest(TestCase):
template = get_template_from_string(source) template = get_template_from_string(source)
vars = template.nodelist.get_nodes_by_type(VariableNode) vars = template.nodelist.get_nodes_by_type(VariableNode)
self.assertEqual(len(vars), 1) self.assertEqual(len(vars), 1)
class ErrorIndexTest(TestCase):
"""
Checks whether index of error is calculated correctly in
template debugger in for loops. Refs ticket #5831
"""
def setUp(self):
self.old_template_debug = settings.TEMPLATE_DEBUG
settings.TEMPLATE_DEBUG = True
def tearDown(self):
settings.TEMPLATE_DEBUG = self.old_template_debug
def test_correct_exception_index(self):
tests = [
('{% load bad_tag %}{% for i in range %}{% badsimpletag %}{% endfor %}', (38, 56)),
('{% load bad_tag %}{% for i in range %}{% for j in range %}{% badsimpletag %}{% endfor %}{% endfor %}', (58, 76)),
('{% load bad_tag %}{% for i in range %}{% badsimpletag %}{% for j in range %}Hello{% endfor %}{% endfor %}', (38, 56)),
('{% load bad_tag %}{% for i in range %}{% for j in five %}{% badsimpletag %}{% endfor %}{% endfor %}', (38, 57)),
('{% load bad_tag %}{% for j in five %}{% badsimpletag %}{% endfor %}', (18, 37)),
]
context = Context({
'range': range(5),
'five': 5,
})
for source, expected_error_source_index in tests:
template = get_template_from_string(source)
try:
template.render(context)
except TemplateSyntaxError, e:
error_source_index = e.source[1]
self.assertEqual(error_source_index,
expected_error_source_index)

View File

@ -5,3 +5,7 @@ register = template.Library()
@register.tag @register.tag
def badtag(parser, token): def badtag(parser, token):
raise RuntimeError("I am a bad tag") raise RuntimeError("I am a bad tag")
@register.simple_tag
def badsimpletag():
raise RuntimeError("I am a bad simpletag")

View File

@ -32,7 +32,7 @@ from context import ContextTests
from custom import CustomTagTests, CustomFilterTests from custom import CustomTagTests, CustomFilterTests
from parser import ParserTests from parser import ParserTests
from unicode import UnicodeTests from unicode import UnicodeTests
from nodelist import NodelistTest from nodelist import NodelistTest, ErrorIndexTest
from smartif import * from smartif import *
from response import * from response import *