From 138de533ff677b470a1e7b4b6ff084a5b7a7444b Mon Sep 17 00:00:00 2001 From: Michael van Tellingen Date: Thu, 14 Feb 2013 09:45:55 +0100 Subject: [PATCH] Fixed #19819 - Improved template filter errors handling. Wrap the Parser.compile_filter method call with a try/except and call the newly added Parser.compile_filter_error(). Overwrite this method in the DebugParser to throw the correct error. Since this error was otherwise catched by the compile_function try/except block the debugger highlighted the wrong line. --- django/template/base.py | 9 ++++++++- django/template/debug.py | 4 ++++ tests/regressiontests/templates/parser.py | 12 +++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/django/template/base.py b/django/template/base.py index 0a2b2c9437..9577d586d8 100644 --- a/django/template/base.py +++ b/django/template/base.py @@ -250,7 +250,11 @@ class Parser(object): elif token.token_type == 1: # TOKEN_VAR if not token.contents: self.empty_variable(token) - filter_expression = self.compile_filter(token.contents) + try: + filter_expression = self.compile_filter(token.contents) + except TemplateSyntaxError as e: + if not self.compile_filter_error(token, e): + raise var_node = self.create_variable_node(filter_expression) self.extend_nodelist(nodelist, var_node, token) elif token.token_type == 2: # TOKEN_BLOCK @@ -330,6 +334,9 @@ class Parser(object): def unclosed_block_tag(self, parse_until): raise self.error(None, "Unclosed tags: %s " % ', '.join(parse_until)) + def compile_filter_error(self, token, e): + pass + def compile_function_error(self, token, e): pass diff --git a/django/template/debug.py b/django/template/debug.py index c7ac007b48..043dd91b4e 100644 --- a/django/template/debug.py +++ b/django/template/debug.py @@ -64,6 +64,10 @@ class DebugParser(Parser): msg = "Unclosed tag '%s'. Looking for one of: %s " % (command, ', '.join(parse_until)) raise self.source_error(source, msg) + def compile_filter_error(self, token, e): + if not hasattr(e, 'django_template_source'): + e.django_template_source = token.source + def compile_function_error(self, token, e): if not hasattr(e, 'django_template_source'): e.django_template_source = token.source diff --git a/tests/regressiontests/templates/parser.py b/tests/regressiontests/templates/parser.py index 6c9deee9ff..9422da80d7 100644 --- a/tests/regressiontests/templates/parser.py +++ b/tests/regressiontests/templates/parser.py @@ -4,8 +4,10 @@ Testing some internals of the template processing. These are *not* examples to b from __future__ import unicode_literals from django.template import (TokenParser, FilterExpression, Parser, Variable, - TemplateSyntaxError) + Template, TemplateSyntaxError) +from django.test.utils import override_settings from django.utils.unittest import TestCase +from django.utils import six class ParserTests(TestCase): @@ -83,3 +85,11 @@ class ParserTests(TestCase): self.assertRaises(TemplateSyntaxError, Variable, "article._hidden" ) + + @override_settings(DEBUG=True, TEMPLATE_DEBUG=True) + def test_compile_filter_error(self): + # regression test for #19819 + msg = "Could not parse the remainder: '@bar' from 'foo@bar'" + with six.assertRaisesRegex(self, TemplateSyntaxError, msg) as cm: + Template("{% if 1 %}{{ foo@bar }}{% endif %}") + self.assertEqual(cm.exception.django_template_source[1], (10, 23))