fixed bug with static unicode strings and auto escaping
authorArmin Ronacher <armin.ronacher@active-4.com>
Sat, 24 May 2008 17:54:43 +0000 (19:54 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Sat, 24 May 2008 17:54:43 +0000 (19:54 +0200)
--HG--
branch : trunk

jinja2/compiler.py
jinja2/environment.py
jinja2/filters.py
jinja2/lexer.py
jinja2/nodes.py
tests/test_ext.py
tests/test_filters.py
tests/test_security.py

index 24cae818da1908cfca54956212bd675b08b12b21..e43c3620843c3312eb965492925fb27c9cf50a70 100644 (file)
@@ -15,7 +15,7 @@ from itertools import chain
 from jinja2 import nodes
 from jinja2.visitor import NodeVisitor, NodeTransformer
 from jinja2.exceptions import TemplateAssertionError
-from jinja2.utils import Markup, concat
+from jinja2.utils import Markup, concat, escape
 
 
 operators = {
@@ -1062,8 +1062,20 @@ class CodeGenerator(NodeVisitor):
         body = []
         for child in node.nodes:
             try:
-                const = unicode(child.as_const())
+                const = child.as_const()
+            except nodes.Impossible:
+                body.append(child)
+                continue
+            try:
+                if self.environment.autoescape:
+                    if hasattr(const, '__html__'):
+                        const = const.__html__()
+                    else:
+                        const = escape(const)
+                const = unicode(const)
             except:
+                # if something goes wrong here we evaluate the node
+                # at runtime for easier debugging
                 body.append(child)
                 continue
             if body and isinstance(body[-1], list):
index 95dda11844fe01004fb493c5afa489efd67790a3..45d684d3bb62a2e5939412af893fc9e9a378e831 100644 (file)
@@ -642,8 +642,7 @@ class TemplateStream(object):
 
     def __init__(self, gen):
         self._gen = gen
-        self._next = gen.next
-        self.buffered = False
+        self.disable_buffering()
 
     def disable_buffering(self):
         """Disable the output buffering."""
index 2cbb46c351c969b25645564ff0002872c9d62698..ed3d57c1dda8912358c73695a14bdc3af38e4b94 100644 (file)
@@ -578,8 +578,7 @@ def do_groupby(environment, value, attribute):
 
 class _GroupTuple(tuple):
     __slots__ = ()
-    grouper = property(itemgetter(0))
-    list = property(itemgetter(1))
+    grouper, list = (property(itemgetter(x)) for x in xrange(2))
 
     def __new__(cls, (key, value)):
         return tuple.__new__(cls, (key, list(value)))
index 350023ddac34fcbe1db53cae283d370f21928fd9..64621fd1c6497d277634a9d213d77a8b5960b780 100644 (file)
@@ -195,7 +195,7 @@ class TokenStream(object):
             return self.next()
 
     def skip_if(self, expr):
-        """Like `next_if` but only returns `True` or `False`."""
+        """Like :meth:`next_if` but only returns `True` or `False`."""
         return self.next_if(expr) is not None
 
     def next(self):
index 9d327378097fdf9fbafb206fa55bf6c200b8166b..568220f8abf5daefe45745e43cc7e96df34b0844 100644 (file)
@@ -251,21 +251,6 @@ class Output(Stmt):
     """
     fields = ('nodes',)
 
-    def optimized_nodes(self):
-        """Try to optimize the nodes."""
-        buffer = []
-        for node in self.nodes:
-            try:
-                const = unicode(node.as_const())
-            except:
-                buffer.append(node)
-            else:
-                if buffer and isinstance(buffer[-1], unicode):
-                    buffer[-1] += const
-                else:
-                    buffer.append(const)
-        return buffer
-
 
 class Extends(Stmt):
     """Represents an extends statement."""
index f91b0f700b2843062237c394cd088bd84a02fd6c..7da2515a1840896677662be3a32b800bb5a5a18c 100644 (file)
@@ -66,3 +66,7 @@ def test_extension_nodes():
     env = Environment(extensions=[TestExtension])
     tmpl = env.from_string('{% test %}')
     assert tmpl.render() == 'False|42|23|{}'
+
+
+def test_identifier():
+    assert TestExtension.identifier == __name__ + '.TestExtension'
index 559b0b16b3095518a8233387fd191366b6b82194..6192d54e4ea9a5872f21914a6b229675d33eb680 100644 (file)
@@ -308,3 +308,11 @@ def test_replace():
 def test_forceescape(env):
     tmpl = env.from_string('{{ x|forceescape }}')
     assert tmpl.render(x=Markup('<div />')) == u'&lt;div /&gt;'
+
+
+def test_safe():
+    env = Environment(autoescape=True)
+    tmpl = env.from_string('{{ "<div>foo</div>"|safe }}')
+    assert tmpl.render() == '<div>foo</div>'
+    tmpl = env.from_string('{{ "<div>foo</div>" }}')
+    assert tmpl.render() == '&lt;div&gt;foo&lt;/div&gt;'
index 0cacf5f433bad20dba827ef56e5d188d63efa52b..0da2df2119e4ba6437328a162972328a481b82f2 100644 (file)
@@ -113,3 +113,8 @@ def test_markup_operations():
     assert Markup(Foo()) == '<em>awesome</em>'
     assert Markup('<strong>%s</strong>') % Foo() == \
            '<strong><em>awesome</em></strong>'
+
+    # escaping and unescaping
+    assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
+    assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
+    assert Markup("&lt;test&gt;").unescape() == "<test>"