diff --git a/AUTHORS b/AUTHORS index ae6a09069a..119bb8b20a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -462,6 +462,7 @@ answer newbie questions, and generally made Django that much better: tt@gurgle.no David Tulig Amit Upadhyay + Adam Vandenberg Geert Vanderkelen Vasil Vangelovski I.S. van Oostveen diff --git a/django/template/__init__.py b/django/template/__init__.py index 584b14b06f..eba2429928 100644 --- a/django/template/__init__.py +++ b/django/template/__init__.py @@ -421,6 +421,20 @@ class TokenParser(object): "A microparser that parses for a value: some string constant or variable name." subject = self.subject i = self.pointer + + def next_space_index(subject, i): + "Increment pointer until a real space (i.e. a space not within quotes) is encountered" + while i < len(subject) and subject[i] not in (' ', '\t'): + if subject[i] in ('"', "'"): + c = subject[i] + i += 1 + while i < len(subject) and subject[i] != c: + i += 1 + if i >= len(subject): + raise TemplateSyntaxError("Searching for value. Unexpected end of string in column %d: %s" % (i, subject)) + i += 1 + return i + if i >= len(subject): raise TemplateSyntaxError("Searching for value. Expected another value but found end of string: %s" % subject) if subject[i] in ('"', "'"): @@ -431,6 +445,10 @@ class TokenParser(object): if i >= len(subject): raise TemplateSyntaxError("Searching for value. Unexpected end of string in column %d: %s" % (i, subject)) i += 1 + + # Continue parsing until next "real" space, so that filters are also included + i = next_space_index(subject, i) + res = subject[p:i] while i < len(subject) and subject[i] in (' ', '\t'): i += 1 @@ -439,15 +457,7 @@ class TokenParser(object): return res else: p = i - while i < len(subject) and subject[i] not in (' ', '\t'): - if subject[i] in ('"', "'"): - c = subject[i] - i += 1 - while i < len(subject) and subject[i] != c: - i += 1 - if i >= len(subject): - raise TemplateSyntaxError("Searching for value. Unexpected end of string in column %d: %s" % (i, subject)) - i += 1 + i = next_space_index(subject, i) s = subject[p:i] while i < len(subject) and subject[i] in (' ', '\t'): i += 1 diff --git a/tests/regressiontests/templates/parser.py b/tests/regressiontests/templates/parser.py index 6ad301d9c3..9e6ad2166e 100644 --- a/tests/regressiontests/templates/parser.py +++ b/tests/regressiontests/templates/parser.py @@ -2,6 +2,55 @@ Testing some internals of the template processing. These are *not* examples to be copied in user code. """ +token_parsing=r""" +Tests for TokenParser behavior in the face of quoted strings with spaces. + +>>> from django.template import TokenParser + + +Test case 1: {% tag thevar|filter sometag %} + +>>> p = TokenParser("tag thevar|filter sometag") +>>> p.tagname +'tag' +>>> p.value() +'thevar|filter' +>>> p.more() +True +>>> p.tag() +'sometag' +>>> p.more() +False + +Test case 2: {% tag "a value"|filter sometag %} + +>>> p = TokenParser('tag "a value"|filter sometag') +>>> p.tagname +'tag' +>>> p.value() +'"a value"|filter' +>>> p.more() +True +>>> p.tag() +'sometag' +>>> p.more() +False + +Test case 3: {% tag 'a value'|filter sometag %} + +>>> p = TokenParser("tag 'a value'|filter sometag") +>>> p.tagname +'tag' +>>> p.value() +"'a value'|filter" +>>> p.more() +True +>>> p.tag() +'sometag' +>>> p.more() +False +""" + filter_parsing = r""" >>> from django.template import FilterExpression, Parser diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index b2ba9f6f90..925fc57084 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -22,7 +22,7 @@ from django.utils.tzinfo import LocalTimezone from context import context_tests from custom import custom_filters -from parser import filter_parsing, variable_parsing +from parser import token_parsing, filter_parsing, variable_parsing from unicode import unicode_tests from smartif import * @@ -37,7 +37,9 @@ import filters __test__ = { 'unicode': unicode_tests, 'context': context_tests, + 'token_parsing': token_parsing, 'filter_parsing': filter_parsing, + 'variable_parsing': variable_parsing, 'custom_filters': custom_filters, }