Browse Source

Fixed #25404 -- Added line numbers to TemplateSyntaxError strings.

This makes it much easier to diagnose a test failure when all
you have is the stack trace from an uncaught TemplateSyntaxError.
Dave Smith 9 năm trước cách đây
mục cha
commit
b53b4d5c10

+ 16 - 6
django/template/base.py

@@ -470,7 +470,7 @@ class Parser(object):
                 self.extend_nodelist(nodelist, TextNode(token.contents), token)
             elif token.token_type == 1:  # TOKEN_VAR
                 if not token.contents:
-                    raise self.error(token, 'Empty variable tag')
+                    raise self.error(token, 'Empty variable tag on line %d' % token.lineno)
                 try:
                     filter_expression = self.compile_filter(token.contents)
                 except TemplateSyntaxError as e:
@@ -481,7 +481,7 @@ class Parser(object):
                 try:
                     command = token.contents.split()[0]
                 except IndexError:
-                    raise self.error(token, 'Empty block tag')
+                    raise self.error(token, 'Empty block tag on line %d' % token.lineno)
                 if command in parse_until:
                     # A matching token has been reached. Return control to
                     # the caller. Put the token back on the token list so the
@@ -545,13 +545,23 @@ class Parser(object):
 
     def invalid_block_tag(self, token, command, parse_until=None):
         if parse_until:
-            raise self.error(token, "Invalid block tag: '%s', expected %s" %
-                (command, get_text_list(["'%s'" % p for p in parse_until])))
-        raise self.error(token, "Invalid block tag: '%s'" % command)
+            raise self.error(
+                token,
+                "Invalid block tag on line %d: '%s', expected %s" % (
+                    token.lineno,
+                    command,
+                    get_text_list(["'%s'" % p for p in parse_until]),
+                ),
+            )
+        raise self.error(token, "Invalid block tag on line %d: '%s'" % (token.lineno, command))
 
     def unclosed_block_tag(self, parse_until):
         command, token = self.command_stack.pop()
-        msg = "Unclosed tag '%s'. Looking for one of: %s." % (command, ', '.join(parse_until))
+        msg = "Unclosed tag on line %d: '%s'. Looking for one of: %s." % (
+            token.lineno,
+            command,
+            ', '.join(parse_until),
+        )
         raise self.error(token, msg)
 
     def next_token(self):

+ 4 - 4
tests/template_tests/syntax_tests/test_basic.py

@@ -61,7 +61,7 @@ class BasicSyntaxTests(SimpleTestCase):
         """
         Raise TemplateSyntaxError for empty variable tags.
         """
-        with self.assertRaises(TemplateSyntaxError):
+        with self.assertRaisesMessage(TemplateSyntaxError, 'Empty variable tag on line 1'):
             self.engine.get_template('basic-syntax07')
 
     @setup({'basic-syntax08': '{{        }}'})
@@ -69,7 +69,7 @@ class BasicSyntaxTests(SimpleTestCase):
         """
         Raise TemplateSyntaxError for empty variable tags.
         """
-        with self.assertRaises(TemplateSyntaxError):
+        with self.assertRaisesMessage(TemplateSyntaxError, 'Empty variable tag on line 1'):
             self.engine.get_template('basic-syntax08')
 
     @setup({'basic-syntax09': '{{ var.method }}'})
@@ -314,13 +314,13 @@ class BasicSyntaxTests(SimpleTestCase):
 
     @setup({'template': '{% block content %}'})
     def test_unclosed_block(self):
-        msg = "Unclosed tag 'block'. Looking for one of: endblock."
+        msg = "Unclosed tag on line 1: 'block'. Looking for one of: endblock."
         with self.assertRaisesMessage(TemplateSyntaxError, msg):
             self.engine.render_to_string('template')
 
     @setup({'template': '{% if a %}'})
     def test_unclosed_block2(self):
-        msg = "Unclosed tag 'if'. Looking for one of: elif, else, endif."
+        msg = "Unclosed tag on line 1: 'if'. Looking for one of: elif, else, endif."
         with self.assertRaisesMessage(TemplateSyntaxError, msg):
             self.engine.render_to_string('template')
 

+ 10 - 1
tests/template_tests/syntax_tests/test_filter_syntax.py

@@ -71,9 +71,18 @@ class FilterSyntaxTests(SimpleTestCase):
         """
         Raise TemplateSyntaxError for empty block tags
         """
-        with self.assertRaises(TemplateSyntaxError):
+        with self.assertRaisesMessage(TemplateSyntaxError, 'Empty block tag on line 1'):
             self.engine.get_template('filter-syntax08')
 
+    @setup({'filter-syntax08-multi-line': "line 1\nline 2\nline 3{% %}\nline 4\nline 5"})
+    def test_filter_syntax08_multi_line(self):
+        """
+        Raise TemplateSyntaxError for empty block tags in templates with
+        multiple lines.
+        """
+        with self.assertRaisesMessage(TemplateSyntaxError, 'Empty block tag on line 3'):
+            self.engine.get_template('filter-syntax08-multi-line')
+
     @setup({'filter-syntax09': '{{ var|cut:"o"|upper|lower }}'})
     def test_filter_syntax09(self):
         """

+ 1 - 1
tests/template_tests/tests.py

@@ -74,7 +74,7 @@ class TemplateTests(SimpleTestCase):
 
         self.assertEqual(
             e.exception.args[0],
-            "Invalid block tag: 'endblock', expected 'elif', 'else' or 'endif'",
+            "Invalid block tag on line 1: 'endblock', expected 'elif', 'else' or 'endif'",
         )
 
     def test_compile_filter_expression_error(self):