]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Introduce {% module %} syntax for calling UIModules.
authorBen Darnell <ben@bendarnell.com>
Sun, 5 Jun 2011 20:47:02 +0000 (13:47 -0700)
committerBen Darnell <ben@bendarnell.com>
Sun, 5 Jun 2011 20:47:02 +0000 (13:47 -0700)
Add linkify and xsrf_form_html as default modules.

demos/chat/templates/index.html
demos/chat/templates/message.html
tornado/template.py
tornado/test/web_test.py
tornado/web.py

index c38190b19dd83dc8f3d75aed9cdcceb5040c9567..0e85ded2806226868181792c714c18d8cb9d474e 100644 (file)
@@ -24,7 +24,7 @@
               <td style="padding-left:5px">
                 <input type="submit" value="{{ _("Post") }}"/>
                 <input type="hidden" name="next" value="{{ request.path }}"/>
-                {% raw xsrf_form_html() %}
+                {% module xsrf_form_html() %}
               </td>
             </tr>
           </table>
index 64d2f67f5c874891d2e50a2e293894270089f1c8..c48a634eeb6c2fcd289815b45bcf8255b604616b 100644 (file)
@@ -1 +1 @@
-<div class="message" id="m{{ message["id"] }}"><b>{{ message["from"] }}: </b>{% raw linkify(message["body"]) %}</div>
+<div class="message" id="m{{ message["id"] }}"><b>{{ message["from"] }}: </b>{% module linkify(message["body"]) %}</div>
index d83ffa3f14570b4ca15da5d55e33a9324d40fb79..dded819a0272e3b7e8b1a4fca8d482c7b410b6fa 100644 (file)
@@ -388,6 +388,10 @@ class _Expression(_Node):
                               writer.current_template.autoescape)
         writer.write_line("_buffer.append(_tmp)")
 
+class _Module(_Expression):
+    def __init__(self, expression):
+        super(_Module, self).__init__("modules." + expression,
+                                      raw=True)
 
 class _Text(_Node):
     def __init__(self, value):
@@ -588,7 +592,7 @@ def _parse(reader, template, in_block=None):
             return body
 
         elif operator in ("extends", "include", "set", "import", "from",
-                          "comment", "autoescape", "raw"):
+                          "comment", "autoescape", "raw", "module"):
             if operator == "comment":
                 continue
             if operator == "extends":
@@ -616,6 +620,8 @@ def _parse(reader, template, in_block=None):
                 continue
             elif operator == "raw":
                 block = _Expression(suffix, raw=True)
+            elif operator == "module":
+                block = _Module(suffix)
             body.chunks.append(block)
             continue
 
index 70b2edb07dee78bf81712895a6648e3ef85a6601..cfb12cf6e087dcffd975f07fea720e910833e940 100644 (file)
@@ -1,5 +1,6 @@
 from tornado.escape import json_decode, utf8, to_unicode, recursive_unicode, native_str
 from tornado.iostream import IOStream
+from tornado.template import DictLoader
 from tornado.testing import LogTrapTestCase, AsyncHTTPTestCase
 from tornado.util import b, bytes_type
 from tornado.web import RequestHandler, _O, authenticated, Application, asynchronous, url
@@ -236,13 +237,24 @@ class DecodeArgHandler(RequestHandler):
                     'query': describe(self.get_argument("foo")),
                     })
 
+class LinkifyHandler(RequestHandler):
+    def get(self):
+        self.render("linkify.html", message="http://example.com")
+
 class WebTest(AsyncHTTPTestCase, LogTrapTestCase):
     def get_app(self):
-        return Application([
-                url("/typecheck/(.*)", TypeCheckHandler, name='typecheck'),
-                url("/decode_arg/(.*)", DecodeArgHandler),
-                url("/decode_arg_kw/(?P<arg>.*)", DecodeArgHandler),
-                ])
+        loader = DictLoader({
+                "linkify.html": "{% module linkify(message) %}"
+                })
+        urls = [
+            url("/typecheck/(.*)", TypeCheckHandler, name='typecheck'),
+            url("/decode_arg/(.*)", DecodeArgHandler),
+            url("/decode_arg_kw/(?P<arg>.*)", DecodeArgHandler),
+            url("/linkify", LinkifyHandler),
+            ]
+        return Application(urls,
+                           template_loader=loader,
+                           autoescape="xhtml_escape")
 
     def test_types(self):
         response = self.fetch("/typecheck/asdf?foo=bar",
@@ -274,3 +286,8 @@ class WebTest(AsyncHTTPTestCase, LogTrapTestCase):
         self.assertEqual(data, {u'path': [u'bytes', u'c3a9'],
                                 u'query': [u'bytes', u'c3a9'],
                                 })
+
+    def test_uimodule_unescaped(self):
+        response = self.fetch("/linkify")
+        self.assertEqual(response.body,
+                         b("<a href=\"http://example.com\">http://example.com</a>"))
index adcfae3c7d0ee024ea15882dc6c1eda33b3ebfa8..af1643b2eb2ac268dae4e7b3b0b3d8f5577669d5 100644 (file)
@@ -1101,7 +1101,8 @@ class Application(object):
         self.named_handlers = {}
         self.default_host = default_host
         self.settings = settings
-        self.ui_modules = {}
+        self.ui_modules = {'linkify': _linkify,
+                           'xsrf_form_html': _xsrf_form_html}
         self.ui_methods = {}
         self._wsgi = wsgi
         self._load_ui_modules(settings.get("ui_modules", {}))
@@ -1609,6 +1610,14 @@ class UIModule(object):
     def render_string(self, path, **kwargs):
         return self.handler.render_string(path, **kwargs)
 
+class _linkify(UIModule):
+    def render(self, text, **kwargs):
+        return escape.linkify(text, **kwargs)
+
+class _xsrf_form_html(UIModule):
+    def render(self):
+        return self.handler.xsrf_form_html()
+
 class URLSpec(object):
     """Specifies mappings between URLs and handlers."""
     def __init__(self, pattern, handler_class, kwargs={}, name=None):