aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/build/changelog.rst12
-rw-r--r--doc/build/syntax.rst21
-rw-r--r--mako/__init__.py2
-rw-r--r--mako/codegen.py3
-rw-r--r--mako/runtime.py1
-rw-r--r--test/test_template.py17
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
@@ -6,6 +6,18 @@ Changelog
===
.. 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,