diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-03-05 17:23:18 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-03-05 17:23:18 +0000 |
commit | a1d018c13bd498b679e091b3a29c479727a6d937 (patch) | |
tree | 13d8e38085aad3662f1643c3a7f789b7bf2ac53b | |
parent | b295167c5a3a4d880b75f8bfd9aa0b296b876bd3 (diff) | |
download | mako-a1d018c13bd498b679e091b3a29c479727a6d937.tar.gz |
- added docs for supports_caller() as well as runtime.py capture(), [ticket:124]
- cleanup
-rw-r--r-- | doc/build/content/namespaces.txt | 26 | ||||
-rw-r--r-- | mako/runtime.py | 39 |
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) |