From 52e8c0a3deaae9017c76a17196aeac8b027b933e Mon Sep 17 00:00:00 2001 From: Cody Taylor <codemister99@yahoo.com> Date: Tue, 24 Mar 2015 20:57:02 -0400 Subject: [PATCH] Add STOP_RENDERING keyword; exiting of a template. Signed-off-by: Cody Taylor <codemister99@yahoo.com> --- doc/build/changelog.rst | 12 ++++++++++++ doc/build/syntax.rst | 21 +++++++++++++++------ mako/__init__.py | 2 +- mako/codegen.py | 3 ++- mako/runtime.py | 1 + test/test_template.py | 17 +++++++++++++++-- 6 files changed, 46 insertions(+), 10 deletions(-) diff --git a/doc/build/changelog.rst b/doc/build/changelog.rst index 03aaec7..9c321bb 100644 --- a/doc/build/changelog.rst +++ b/doc/build/changelog.rst @@ -5,6 +5,18 @@ Changelog 1.0 === +.. changelog:: + :version: 1.0.2 + + .. change:: + :tags: feature + :tickets: 236 + + Added STOP_RENDERING keyword for returning/exiting from a + template early. Previously the docs suggested a bare + ``return``, but this could cause ``None`` to appear in the + rendered template result. + .. changelog:: :version: 1.0.1 :released: Thu Jan 22 2015 diff --git a/doc/build/syntax.rst b/doc/build/syntax.rst index fe4a860..7ec68cb 100644 --- a/doc/build/syntax.rst +++ b/doc/build/syntax.rst @@ -443,19 +443,19 @@ Mako: <%def name="x()">${x}</%def> </%text> -Returning Early from a Template -=============================== +Exiting Early from a Template +============================= Sometimes you want to stop processing a template or ``<%def>`` method in the middle and just use the text you've accumulated so -far. You can use a ``return`` statement inside a Python -block to do that. +far. You can ``return`` the ``STOP_RENDERING`` value inside a Python +block to exit the current rendering process. .. sourcecode:: mako % if not len(records): No records found. - <% return %> + <% return STOP_RENDERING %> % endif Or perhaps: @@ -464,6 +464,15 @@ Or perhaps: <% if not len(records): - return + return STOP_RENDERING %> +In older versions, return an empty string instead to avoid having +``None`` in your rendered template: + +.. sourcecode:: mako + + <% return '' %> + +.. versionadded:: 1.0.2 + diff --git a/mako/__init__.py b/mako/__init__.py index d963848..59d4060 100644 --- a/mako/__init__.py +++ b/mako/__init__.py @@ -5,4 +5,4 @@ # the MIT License: http://www.opensource.org/licenses/mit-license.php -__version__ = '1.0.1' +__version__ = '1.0.2' diff --git a/mako/codegen.py b/mako/codegen.py index 4b0bda8..0226415 100644 --- a/mako/codegen.py +++ b/mako/codegen.py @@ -19,7 +19,7 @@ MAGIC_NUMBER = 10 # names which are hardwired into the # template and are not accessed via the # context itself -RESERVED_NAMES = set(['context', 'loop', 'UNDEFINED']) +RESERVED_NAMES = set(['context', 'loop', 'UNDEFINED', 'STOP_RENDERING']) def compile(node, uri, @@ -215,6 +215,7 @@ class _GenerateRenderMethod(object): (", ".join(self.compiler.future_imports),)) self.printer.writeline("from mako import runtime, filters, cache") self.printer.writeline("UNDEFINED = runtime.UNDEFINED") + self.printer.writeline("STOP_RENDERING = runtime.STOP_RENDERING") self.printer.writeline("__M_dict_builtin = dict") self.printer.writeline("__M_locals_builtin = locals") self.printer.writeline("_magic_number = %r" % MAGIC_NUMBER) diff --git a/mako/runtime.py b/mako/runtime.py index 6b6a35a..870efcc 100644 --- a/mako/runtime.py +++ b/mako/runtime.py @@ -228,6 +228,7 @@ class Undefined(object): return False UNDEFINED = Undefined() +STOP_RENDERING = "" class LoopStack(object): """a stack for LoopContexts that implements the context manager protocol diff --git a/test/test_template.py b/test/test_template.py index c5873dc..a6a491f 100644 --- a/test/test_template.py +++ b/test/test_template.py @@ -757,9 +757,22 @@ class UndefinedVarsTest(TemplateTest): ['t is: T', 'a,b,c'] ) +class StopRenderingTest(TemplateTest): + def test_return_in_template(self): + t = Template(""" + Line one + <% return STOP_RENDERING %> + Line Three + """, strict_undefined=True) + + eq_( + result_lines(t.render()), + ['Line one'] + ) + class ReservedNameTest(TemplateTest): def test_names_on_context(self): - for name in ('context', 'loop', 'UNDEFINED'): + for name in ('context', 'loop', 'UNDEFINED', 'STOP_RENDERING'): assert_raises_message( exceptions.NameConflictError, r"Reserved words passed to render\(\): %s" % name, @@ -767,7 +780,7 @@ class ReservedNameTest(TemplateTest): ) def test_names_in_template(self): - for name in ('context', 'loop', 'UNDEFINED'): + for name in ('context', 'loop', 'UNDEFINED', 'STOP_RENDERING'): assert_raises_message( exceptions.NameConflictError, r"Reserved words declared in template: %s" % name, -- GitLab