Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
  • Loading branch information...
commit 958e049d4d90fb5e0fe582eb4339af3c58dd5c07 1 parent 1d485cf
Jannis Leidel authored August 12, 2011
2  django/template/debug.py
@@ -78,7 +78,7 @@ def render_node(self, node, context):
78 78
             from sys import exc_info
79 79
             wrapped = TemplateSyntaxError(u'Caught %s while rendering: %s' %
80 80
                 (e.__class__.__name__, force_unicode(e, errors='replace')))
81  
-            wrapped.source = node.source
  81
+            wrapped.source = getattr(e, 'template_node_source', node.source)
82 82
             wrapped.exc_info = exc_info()
83 83
             raise wrapped, None, wrapped.exc_info[2]
84 84
         return result
17  django/template/defaulttags.py
@@ -227,8 +227,21 @@ def render(self, context):
227 227
                     context.update(unpacked_vars)
228 228
             else:
229 229
                 context[self.loopvars[0]] = item
230  
-            for node in self.nodelist_loop:
231  
-                nodelist.append(node.render(context))
  230
+            # In TEMPLATE_DEBUG mode providing source of the node which
  231
+            # actually raised an exception to DefaultNodeList.render_node
  232
+            if settings.TEMPLATE_DEBUG:
  233
+                for node in self.nodelist_loop:
  234
+                    try:
  235
+                        nodelist.append(node.render(context))
  236
+                    except Exception, e:
  237
+                        if not hasattr(e, 'template_node_source'):
  238
+                            from sys import exc_info
  239
+                            e.template_node_source = node.source
  240
+                            raise e, None, exc_info()[2]
  241
+                        raise
  242
+            else:
  243
+                for node in self.nodelist_loop:
  244
+                    nodelist.append(node.render(context))
232 245
             if pop_context:
233 246
                 # The loop variables were pushed on to the context so pop them
234 247
                 # off again. This is necessary because the tag lets the length
38  tests/regressiontests/templates/nodelist.py
... ...
@@ -1,8 +1,8 @@
  1
+from django.conf import settings
  2
+from django.template import VariableNode, Context, TemplateSyntaxError
1 3
 from django.template.loader import get_template_from_string
2  
-from django.template import VariableNode
3 4
 from django.utils.unittest import TestCase
4 5
 
5  
-
6 6
 class NodelistTest(TestCase):
7 7
 
8 8
     def test_for(self):
@@ -28,3 +28,37 @@ def test_ifchanged(self):
28 28
         template = get_template_from_string(source)
29 29
         vars = template.nodelist.get_nodes_by_type(VariableNode)
30 30
         self.assertEqual(len(vars), 1)
  31
+
  32
+
  33
+class ErrorIndexTest(TestCase):
  34
+    """
  35
+    Checks whether index of error is calculated correctly in
  36
+    template debugger in for loops. Refs ticket #5831
  37
+    """
  38
+    def setUp(self):
  39
+        self.old_template_debug = settings.TEMPLATE_DEBUG
  40
+        settings.TEMPLATE_DEBUG = True
  41
+
  42
+    def tearDown(self):
  43
+        settings.TEMPLATE_DEBUG = self.old_template_debug
  44
+
  45
+    def test_correct_exception_index(self):
  46
+        tests = [
  47
+            ('{% load bad_tag %}{% for i in range %}{% badsimpletag %}{% endfor %}', (38, 56)),
  48
+            ('{% load bad_tag %}{% for i in range %}{% for j in range %}{% badsimpletag %}{% endfor %}{% endfor %}', (58, 76)),
  49
+            ('{% load bad_tag %}{% for i in range %}{% badsimpletag %}{% for j in range %}Hello{% endfor %}{% endfor %}', (38, 56)),
  50
+            ('{% load bad_tag %}{% for i in range %}{% for j in five %}{% badsimpletag %}{% endfor %}{% endfor %}', (38, 57)),
  51
+            ('{% load bad_tag %}{% for j in five %}{% badsimpletag %}{% endfor %}', (18, 37)),
  52
+        ]
  53
+        context = Context({
  54
+            'range': range(5),
  55
+            'five': 5,
  56
+        })
  57
+        for source, expected_error_source_index in tests:
  58
+            template = get_template_from_string(source)
  59
+            try:
  60
+                template.render(context)
  61
+            except TemplateSyntaxError, e:
  62
+                error_source_index = e.source[1]
  63
+                self.assertEqual(error_source_index,
  64
+                                 expected_error_source_index)
4  tests/regressiontests/templates/templatetags/bad_tag.py
@@ -5,3 +5,7 @@
5 5
 @register.tag
6 6
 def badtag(parser, token):
7 7
     raise RuntimeError("I am a bad tag")
  8
+
  9
+@register.simple_tag
  10
+def badsimpletag():
  11
+    raise RuntimeError("I am a bad simpletag")
2  tests/regressiontests/templates/tests.py
@@ -32,7 +32,7 @@
32 32
 from custom import CustomTagTests, CustomFilterTests
33 33
 from parser import ParserTests
34 34
 from unicode import UnicodeTests
35  
-from nodelist import NodelistTest
  35
+from nodelist import NodelistTest, ErrorIndexTest
36 36
 from smartif import *
37 37
 from response import *
38 38
 

0 notes on commit 958e049

Please sign in to comment.
Something went wrong with that request. Please try again.