Index: runtime.py =================================================================== --- runtime.py (revision 327) +++ runtime.py (working copy) @@ -8,11 +8,12 @@ from mako import exceptions, util import inspect, sys +import copy class Context(object): """provides runtime namespace, output buffer, and various callstacks for templates.""" - def __init__(self, buffer, **data): - self._buffer_stack = [buffer] + def __init__(self, **data): + self._buffer_stack = [] self._data = data self._kwargs = data.copy() self._with_template = None @@ -33,9 +34,16 @@ return self._data.keys() def __getitem__(self, key): return self._data[key] - def push_buffer(self): + def push_buffer(self, as_unicode=False, output_encoding=None, encoding_errors=None): """push a capturing buffer onto this Context.""" - self._buffer_stack.append(util.FastEncodingBuffer()) + unicode = 'utf-8', 'utf8', 'unicode' + if as_unicode: + buf = util.FastEncodingBuffer() + elif output_encoding and output_encoding.lower() in unicode: + buf = util.FastEncodingBuffer(output_encoding, encoding_errors) + else: + buf = util.StringIO() + self._buffer_stack.append(buf) def pop_buffer(self): """pop the most recent capturing buffer from this Context.""" return self._buffer_stack.pop() @@ -276,13 +284,8 @@ def _render(template, callable_, args, data, as_unicode=False): """create a Context and return the string output of the given template and template callable.""" - if as_unicode: - buf = util.FastEncodingBuffer() - elif template.output_encoding: - buf = util.FastEncodingBuffer(template.output_encoding, template.encoding_errors) - else: - buf = util.StringIO() - context = Context(buf, **data) + context = Context(**data) + context.push_buffer(as_unicode, template.output_encoding, template.encoding_errors) context._with_template = template _render_context(template, callable_, context, *args, **_kwargs_for_callable(callable_, data)) return context.pop_buffer().getvalue() @@ -294,7 +297,7 @@ if arg != 'context' and arg in data and arg not in kwargs: kwargs[arg] = data[arg] return kwargs - + def _render_context(tmpl, callable_, context, *args, **kwargs): import mako.template as template # create polymorphic 'self' namespace for this template with possibly updated context @@ -306,7 +309,7 @@ # otherwise, call the actual rendering method specified (inherit, lclcontext) = _populate_self_namespace(context, tmpl.parent) _exec_template(callable_, context, args=args, kwargs=kwargs) - + def _exec_template(callable_, context, args=None, kwargs=None): """execute a rendering callable given the callable, a Context, and optional explicit arguments @@ -329,8 +332,9 @@ if not result: raise error else: - context._buffer_stack = [util.StringIO()] error_template = exceptions.html_error_template() + while context._buffer_stack: del context._buffer_stack[0] + context.push_buffer(False, error_template.output_encoding, error_template.encoding_errors) context._with_template = error_template error_template.render_context(context, error=error) else: