Code

Ticket #5971: 5971-tokenparser-consistency-r10001.diff

File 5971-tokenparser-consistency-r10001.diff, 3.3 KB (added by ramiro, 5 years ago)

Unified and updated patches (implementation bt Dmitri Fedortchenko and tests by adamv)

Line 
1diff --git a/django/template/__init__.py b/django/template/__init__.py
2--- a/django/template/__init__.py
3+++ b/django/template/__init__.py
4@@ -409,6 +409,20 @@
5         "A microparser that parses for a value: some string constant or variable name."
6         subject = self.subject
7         i = self.pointer
8+
9+        def __next_space_index(subject, i):
10+            """Increment pointer until a real space (i.e. a space not within quotes) is encountered"""
11+            while i < len(subject) and subject[i] not in (' ', '\t'):
12+                if subject[i] in ('"', "'"):
13+                    c = subject[i]
14+                    i += 1
15+                    while i < len(subject) and subject[i] != c:
16+                        i += 1
17+                    if i >= len(subject):
18+                        raise TemplateSyntaxError("Searching for value. Unexpected end of string in column %d: %s" % (i, subject))
19+               i += 1
20+            return i
21+
22         if i >= len(subject):
23             raise TemplateSyntaxError("Searching for value. Expected another value but found end of string: %s" % subject)
24         if subject[i] in ('"', "'"):
25@@ -419,6 +433,10 @@
26             if i >= len(subject):
27                 raise TemplateSyntaxError("Searching for value. Unexpected end of string in column %d: %s" % (i, subject))
28             i += 1
29+
30+            # Continue parsing until next "real" space, so that filters are also included
31+            i = __next_space_index(subject, i)
32+
33             res = subject[p:i]
34             while i < len(subject) and subject[i] in (' ', '\t'):
35                 i += 1
36@@ -427,15 +445,7 @@
37             return res
38         else:
39             p = i
40-            while i < len(subject) and subject[i] not in (' ', '\t'):
41-                if subject[i] in ('"', "'"):
42-                    c = subject[i]
43-                    i += 1
44-                    while i < len(subject) and subject[i] != c:
45-                        i += 1
46-                    if i >= len(subject):
47-                        raise TemplateSyntaxError("Searching for value. Unexpected end of string in column %d: %s" % (i, subject))
48-                i += 1
49+            i = __next_space_index(subject, i)
50             s = subject[p:i]
51             while i < len(subject) and subject[i] in (' ', '\t'):
52                 i += 1
53diff --git a/tests/regressiontests/tokenparser/__init__.py b/tests/regressiontests/tokenparser/__init__.py
54new file mode 100644
55diff --git a/tests/regressiontests/tokenparser/models.py b/tests/regressiontests/tokenparser/models.py
56new file mode 100644
57diff --git a/tests/regressiontests/tokenparser/tests.py b/tests/regressiontests/tokenparser/tests.py
58new file mode 100644
59--- /dev/null
60+++ b/tests/regressiontests/tokenparser/tests.py
61@@ -0,0 +1,44 @@
62+"""
63+Tests for TokenParser behavior in the face of quoted strings with spaces.
64+
65+>>> from django.template import TokenParser
66+
67+
68+Test case 1: {% tag thevar|filter sometag %}
69+
70+>>> p = TokenParser("tag thevar|filter sometag")
71+>>> p.tagname
72+'tag'
73+
74+>>> p.value()
75+'thevar|filter'
76+
77+>>> p.more()
78+True
79+
80+>>> p.tag()
81+'sometag'
82+
83+>>> p.more()
84+False
85+
86+
87+Test case 2: {% tag "a value"|filter sometag %}
88+
89+>>> p = TokenParser('tag "a value"|filter sometag')
90+>>> p.tagname
91+'tag'
92+
93+>>> p.value()
94+'"a value"|filter'
95+
96+>>> p.more()
97+True
98+
99+>>> p.tag()
100+'sometag'
101+
102+
103+>>> p.more()
104+False
105+"""