From ce3e1dedafea47467615c063a3462da21607e9ae Mon Sep 17 00:00:00 2001 From: Ben Darnell Date: Sun, 5 Jun 2011 13:47:02 -0700 Subject: [PATCH] Introduce {% module %} syntax for calling UIModules. Add linkify and xsrf_form_html as default modules. --- demos/chat/templates/index.html | 2 +- demos/chat/templates/message.html | 2 +- tornado/template.py | 8 +++++++- tornado/test/web_test.py | 27 ++++++++++++++++++++++----- tornado/web.py | 11 ++++++++++- 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/demos/chat/templates/index.html b/demos/chat/templates/index.html index c38190b19d..0e85ded280 100644 --- a/demos/chat/templates/index.html +++ b/demos/chat/templates/index.html @@ -24,7 +24,7 @@ - {% raw xsrf_form_html() %} + {% module xsrf_form_html() %} diff --git a/demos/chat/templates/message.html b/demos/chat/templates/message.html index 64d2f67f5c..c48a634eeb 100644 --- a/demos/chat/templates/message.html +++ b/demos/chat/templates/message.html @@ -1 +1 @@ -
{{ message["from"] }}: {% raw linkify(message["body"]) %}
+
{{ message["from"] }}: {% module linkify(message["body"]) %}
diff --git a/tornado/template.py b/tornado/template.py index d83ffa3f14..dded819a02 100644 --- a/tornado/template.py +++ b/tornado/template.py @@ -388,6 +388,10 @@ def generate(self, writer): 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 diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py index 70b2edb07d..cfb12cf6e0 100644 --- a/tornado/test/web_test.py +++ b/tornado/test/web_test.py @@ -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 @@ def describe(s): '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.*)", DecodeArgHandler), - ]) + loader = DictLoader({ + "linkify.html": "{% module linkify(message) %}" + }) + urls = [ + url("/typecheck/(.*)", TypeCheckHandler, name='typecheck'), + url("/decode_arg/(.*)", DecodeArgHandler), + url("/decode_arg_kw/(?P.*)", 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 @@ def test_decode_argument(self): 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("http://example.com")) diff --git a/tornado/web.py b/tornado/web.py index adcfae3c7d..af1643b2eb 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -1101,7 +1101,8 @@ def __init__(self, handlers=None, default_host="", transforms=None, 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 @@ def html_body(self): 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):