summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-03-05 17:23:18 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2010-03-05 17:23:18 +0000
commita1d018c13bd498b679e091b3a29c479727a6d937 (patch)
tree13d8e38085aad3662f1643c3a7f789b7bf2ac53b
parentb295167c5a3a4d880b75f8bfd9aa0b296b876bd3 (diff)
downloadmako-a1d018c13bd498b679e091b3a29c479727a6d937.tar.gz
- added docs for supports_caller() as well as runtime.py capture(), [ticket:124]
- cleanup
-rw-r--r--doc/build/content/namespaces.txt26
-rw-r--r--mako/runtime.py39
2 files changed, 55 insertions, 10 deletions
diff --git a/doc/build/content/namespaces.txt b/doc/build/content/namespaces.txt
index aab13d6..46f2e95 100644
--- a/doc/build/content/namespaces.txt
+++ b/doc/build/content/namespaces.txt
@@ -79,8 +79,10 @@ Namespaces can also import regular Python functions from modules. These callabl
A module file `some/module.py` might contain the callable:
+ {python}
def my_tag(context):
context.write("hello world")
+ return ''
A template can use this module via:
@@ -88,7 +90,29 @@ A template can use this module via:
${hw.my_tag()}
-Note that the `context` argument is not needed in the call; the `namespace` tag creates a locally-scoped callable which takes care of it.
+Note that the `context` argument is not needed in the call; the `namespace` tag creates a locally-scoped callable which takes care of it. The `return ''` is so that the def does not dump a `None` into the output stream - the return value of any def is rendered after the def completes, in addition to whatever was passed to `context.write()` within its body.
+
+If your def is to be called in an "embedded content" context, that is as described in [defs_defswithcontent](rel:defs_defswithcontent), you should use the `@supports_caller` decorator, which will ensure that Mako will ensure the correct "caller" variable is available when your def is called, supporting embedded content:
+
+ {python}
+ from mako.runtime import supports_caller
+
+ @supports_caller
+ def my_tag(context):
+ context.write("<div>")
+ context['caller'].body()
+ context.write("</div>")
+ return ''
+
+Capturing of output is available as well, using the outside-of-templates version of the `capture()` function, which accepts the "context" as its first argument:
+
+ {python}
+ from mako.runtime import supports_caller, capture
+
+ @supports_caller
+ def my_tag(context):
+ return "<div>%s</div>" % \
+ capture(context, context['caller'].body, x="foo", y="bar")
### Declaring defs in namespaces.
diff --git a/mako/runtime.py b/mako/runtime.py
index f59a8bc..8811fd6 100644
--- a/mako/runtime.py
+++ b/mako/runtime.py
@@ -151,8 +151,13 @@ class _NSAttr(object):
raise AttributeError(key)
class Namespace(object):
- """provides access to collections of rendering methods, which can be local, from other templates, or from imported modules"""
- def __init__(self, name, context, module=None, template=None, templateuri=None, callables=None, inherits=None, populate_self=True, calling_uri=None):
+ """provides access to collections of rendering methods, which
+ can be local, from other templates, or from imported modules"""
+
+ def __init__(self, name, context, module=None,
+ template=None, templateuri=None,
+ callables=None, inherits=None,
+ populate_self=True, calling_uri=None):
self.name = name
if module is not None:
mod = __import__(module)
@@ -176,16 +181,27 @@ class Namespace(object):
self.callables = None
if populate_self and self.template is not None:
(lclcallable, lclcontext) = _populate_self_namespace(context, self.template, self_ns=self)
-
- module = property(lambda s:s._module or s.template.module)
- filename = property(lambda s:s._module and s._module.__file__ or s.template.filename)
- uri = property(lambda s:s.template.uri)
+ @property
+ def module(self):
+ return self._module or self.template.module
+
+ @property
+ def filename(self):
+ if self._module:
+ return self._module.__file__
+ else:
+ return self.template.filename
+
+ @property
+ def uri(self):
+ return self.template.uri
+
+ @property
def attr(self):
if not hasattr(self, '_attr'):
self._attr = _NSAttr(self)
return self._attr
- attr = property(attr)
def get_namespace(self, uri):
"""return a namespace corresponding to the given template uri.
@@ -219,9 +235,9 @@ class Namespace(object):
kwargs.setdefault('url', self.template.cache_url)
return self.cache.get(key, **kwargs)
+ @property
def cache(self):
return self.template.cache
- cache = property(cache)
def include_file(self, uri, **kwargs):
"""include a file at the given uri"""
@@ -271,6 +287,7 @@ class Namespace(object):
def supports_caller(func):
"""apply a caller_stack compatibility decorator to a plain Python function."""
+
def wrap_stackframe(context, *args, **kwargs):
context.caller_stack._push_frame()
try:
@@ -281,8 +298,12 @@ def supports_caller(func):
def capture(context, callable_, *args, **kwargs):
"""execute the given template def, capturing the output into a buffer."""
+
if not callable(callable_):
- raise exceptions.RuntimeException("capture() function expects a callable as its argument (i.e. capture(func, *args, **kwargs))")
+ raise exceptions.RuntimeException(
+ "capture() function expects a callable as "
+ "its argument (i.e. capture(func, *args, **kwargs))"
+ )
context._push_buffer()
try:
callable_(*args, **kwargs)