swr: [rasterizer scripts] Put codegen scripts into a separate directory
[mesa.git] / src / gallium / drivers / swr / rasterizer / codegen / mako / runtime.py
1 # mako/runtime.py
2 # Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
3 #
4 # This module is part of Mako and is released under
5 # the MIT License: http://www.opensource.org/licenses/mit-license.php
6
7 """provides runtime services for templates, including Context,
8 Namespace, and various helper functions."""
9
10 from mako import exceptions, util, compat
11 from mako.compat import compat_builtins
12 import sys
13
14
15 class Context(object):
16 """Provides runtime namespace, output buffer, and various
17 callstacks for templates.
18
19 See :ref:`runtime_toplevel` for detail on the usage of
20 :class:`.Context`.
21
22 """
23
24 def __init__(self, buffer, **data):
25 self._buffer_stack = [buffer]
26
27 self._data = data
28
29 self._kwargs = data.copy()
30 self._with_template = None
31 self._outputting_as_unicode = None
32 self.namespaces = {}
33
34 # "capture" function which proxies to the
35 # generic "capture" function
36 self._data['capture'] = compat.partial(capture, self)
37
38 # "caller" stack used by def calls with content
39 self.caller_stack = self._data['caller'] = CallerStack()
40
41 def _set_with_template(self, t):
42 self._with_template = t
43 illegal_names = t.reserved_names.intersection(self._data)
44 if illegal_names:
45 raise exceptions.NameConflictError(
46 "Reserved words passed to render(): %s" %
47 ", ".join(illegal_names))
48
49 @property
50 def lookup(self):
51 """Return the :class:`.TemplateLookup` associated
52 with this :class:`.Context`.
53
54 """
55 return self._with_template.lookup
56
57 @property
58 def kwargs(self):
59 """Return the dictionary of top level keyword arguments associated
60 with this :class:`.Context`.
61
62 This dictionary only includes the top-level arguments passed to
63 :meth:`.Template.render`. It does not include names produced within
64 the template execution such as local variable names or special names
65 such as ``self``, ``next``, etc.
66
67 The purpose of this dictionary is primarily for the case that
68 a :class:`.Template` accepts arguments via its ``<%page>`` tag,
69 which are normally expected to be passed via :meth:`.Template.render`,
70 except the template is being called in an inheritance context,
71 using the ``body()`` method. :attr:`.Context.kwargs` can then be
72 used to propagate these arguments to the inheriting template::
73
74 ${next.body(**context.kwargs)}
75
76 """
77 return self._kwargs.copy()
78
79 def push_caller(self, caller):
80 """Push a ``caller`` callable onto the callstack for
81 this :class:`.Context`."""
82
83
84 self.caller_stack.append(caller)
85
86 def pop_caller(self):
87 """Pop a ``caller`` callable onto the callstack for this
88 :class:`.Context`."""
89
90 del self.caller_stack[-1]
91
92 def keys(self):
93 """Return a list of all names established in this :class:`.Context`."""
94
95 return list(self._data.keys())
96
97 def __getitem__(self, key):
98 if key in self._data:
99 return self._data[key]
100 else:
101 return compat_builtins.__dict__[key]
102
103 def _push_writer(self):
104 """push a capturing buffer onto this Context and return
105 the new writer function."""
106
107 buf = util.FastEncodingBuffer()
108 self._buffer_stack.append(buf)
109 return buf.write
110
111 def _pop_buffer_and_writer(self):
112 """pop the most recent capturing buffer from this Context
113 and return the current writer after the pop.
114
115 """
116
117 buf = self._buffer_stack.pop()
118 return buf, self._buffer_stack[-1].write
119
120 def _push_buffer(self):
121 """push a capturing buffer onto this Context."""
122
123 self._push_writer()
124
125 def _pop_buffer(self):
126 """pop the most recent capturing buffer from this Context."""
127
128 return self._buffer_stack.pop()
129
130 def get(self, key, default=None):
131 """Return a value from this :class:`.Context`."""
132
133 return self._data.get(key, compat_builtins.__dict__.get(key, default))
134
135 def write(self, string):
136 """Write a string to this :class:`.Context` object's
137 underlying output buffer."""
138
139 self._buffer_stack[-1].write(string)
140
141 def writer(self):
142 """Return the current writer function."""
143
144 return self._buffer_stack[-1].write
145
146 def _copy(self):
147 c = Context.__new__(Context)
148 c._buffer_stack = self._buffer_stack
149 c._data = self._data.copy()
150 c._kwargs = self._kwargs
151 c._with_template = self._with_template
152 c._outputting_as_unicode = self._outputting_as_unicode
153 c.namespaces = self.namespaces
154 c.caller_stack = self.caller_stack
155 return c
156
157 def _locals(self, d):
158 """Create a new :class:`.Context` with a copy of this
159 :class:`.Context`'s current state,
160 updated with the given dictionary.
161
162 The :attr:`.Context.kwargs` collection remains
163 unaffected.
164
165
166 """
167
168 if not d:
169 return self
170 c = self._copy()
171 c._data.update(d)
172 return c
173
174 def _clean_inheritance_tokens(self):
175 """create a new copy of this :class:`.Context`. with
176 tokens related to inheritance state removed."""
177
178 c = self._copy()
179 x = c._data
180 x.pop('self', None)
181 x.pop('parent', None)
182 x.pop('next', None)
183 return c
184
185 class CallerStack(list):
186 def __init__(self):
187 self.nextcaller = None
188
189 def __nonzero__(self):
190 return self.__bool__()
191
192 def __bool__(self):
193 return len(self) and self._get_caller() and True or False
194
195 def _get_caller(self):
196 # this method can be removed once
197 # codegen MAGIC_NUMBER moves past 7
198 return self[-1]
199
200 def __getattr__(self, key):
201 return getattr(self._get_caller(), key)
202
203 def _push_frame(self):
204 frame = self.nextcaller or None
205 self.append(frame)
206 self.nextcaller = None
207 return frame
208
209 def _pop_frame(self):
210 self.nextcaller = self.pop()
211
212
213 class Undefined(object):
214 """Represents an undefined value in a template.
215
216 All template modules have a constant value
217 ``UNDEFINED`` present which is an instance of this
218 object.
219
220 """
221 def __str__(self):
222 raise NameError("Undefined")
223
224 def __nonzero__(self):
225 return self.__bool__()
226
227 def __bool__(self):
228 return False
229
230 UNDEFINED = Undefined()
231
232 class LoopStack(object):
233 """a stack for LoopContexts that implements the context manager protocol
234 to automatically pop off the top of the stack on context exit
235 """
236
237 def __init__(self):
238 self.stack = []
239
240 def _enter(self, iterable):
241 self._push(iterable)
242 return self._top
243
244 def _exit(self):
245 self._pop()
246 return self._top
247
248 @property
249 def _top(self):
250 if self.stack:
251 return self.stack[-1]
252 else:
253 return self
254
255 def _pop(self):
256 return self.stack.pop()
257
258 def _push(self, iterable):
259 new = LoopContext(iterable)
260 if self.stack:
261 new.parent = self.stack[-1]
262 return self.stack.append(new)
263
264 def __getattr__(self, key):
265 raise exceptions.RuntimeException("No loop context is established")
266
267 def __iter__(self):
268 return iter(self._top)
269
270
271 class LoopContext(object):
272 """A magic loop variable.
273 Automatically accessible in any ``% for`` block.
274
275 See the section :ref:`loop_context` for usage
276 notes.
277
278 :attr:`parent` -> :class:`.LoopContext` or ``None``
279 The parent loop, if one exists.
280 :attr:`index` -> `int`
281 The 0-based iteration count.
282 :attr:`reverse_index` -> `int`
283 The number of iterations remaining.
284 :attr:`first` -> `bool`
285 ``True`` on the first iteration, ``False`` otherwise.
286 :attr:`last` -> `bool`
287 ``True`` on the last iteration, ``False`` otherwise.
288 :attr:`even` -> `bool`
289 ``True`` when ``index`` is even.
290 :attr:`odd` -> `bool`
291 ``True`` when ``index`` is odd.
292 """
293
294 def __init__(self, iterable):
295 self._iterable = iterable
296 self.index = 0
297 self.parent = None
298
299 def __iter__(self):
300 for i in self._iterable:
301 yield i
302 self.index += 1
303
304 @util.memoized_instancemethod
305 def __len__(self):
306 return len(self._iterable)
307
308 @property
309 def reverse_index(self):
310 return len(self) - self.index - 1
311
312 @property
313 def first(self):
314 return self.index == 0
315
316 @property
317 def last(self):
318 return self.index == len(self) - 1
319
320 @property
321 def even(self):
322 return not self.odd
323
324 @property
325 def odd(self):
326 return bool(self.index % 2)
327
328 def cycle(self, *values):
329 """Cycle through values as the loop progresses.
330 """
331 if not values:
332 raise ValueError("You must provide values to cycle through")
333 return values[self.index % len(values)]
334
335
336 class _NSAttr(object):
337 def __init__(self, parent):
338 self.__parent = parent
339 def __getattr__(self, key):
340 ns = self.__parent
341 while ns:
342 if hasattr(ns.module, key):
343 return getattr(ns.module, key)
344 else:
345 ns = ns.inherits
346 raise AttributeError(key)
347
348 class Namespace(object):
349 """Provides access to collections of rendering methods, which
350 can be local, from other templates, or from imported modules.
351
352 To access a particular rendering method referenced by a
353 :class:`.Namespace`, use plain attribute access:
354
355 .. sourcecode:: mako
356
357 ${some_namespace.foo(x, y, z)}
358
359 :class:`.Namespace` also contains several built-in attributes
360 described here.
361
362 """
363
364 def __init__(self, name, context,
365 callables=None, inherits=None,
366 populate_self=True, calling_uri=None):
367 self.name = name
368 self.context = context
369 self.inherits = inherits
370 if callables is not None:
371 self.callables = dict([(c.__name__, c) for c in callables])
372
373 callables = ()
374
375 module = None
376 """The Python module referenced by this :class:`.Namespace`.
377
378 If the namespace references a :class:`.Template`, then
379 this module is the equivalent of ``template.module``,
380 i.e. the generated module for the template.
381
382 """
383
384 template = None
385 """The :class:`.Template` object referenced by this
386 :class:`.Namespace`, if any.
387
388 """
389
390 context = None
391 """The :class:`.Context` object for this :class:`.Namespace`.
392
393 Namespaces are often created with copies of contexts that
394 contain slightly different data, particularly in inheritance
395 scenarios. Using the :class:`.Context` off of a :class:`.Namespace` one
396 can traverse an entire chain of templates that inherit from
397 one-another.
398
399 """
400
401 filename = None
402 """The path of the filesystem file used for this
403 :class:`.Namespace`'s module or template.
404
405 If this is a pure module-based
406 :class:`.Namespace`, this evaluates to ``module.__file__``. If a
407 template-based namespace, it evaluates to the original
408 template file location.
409
410 """
411
412 uri = None
413 """The URI for this :class:`.Namespace`'s template.
414
415 I.e. whatever was sent to :meth:`.TemplateLookup.get_template()`.
416
417 This is the equivalent of :attr:`.Template.uri`.
418
419 """
420
421 _templateuri = None
422
423 @util.memoized_property
424 def attr(self):
425 """Access module level attributes by name.
426
427 This accessor allows templates to supply "scalar"
428 attributes which are particularly handy in inheritance
429 relationships.
430
431 .. seealso::
432
433 :ref:`inheritance_attr`
434
435 :ref:`namespace_attr_for_includes`
436
437 """
438 return _NSAttr(self)
439
440 def get_namespace(self, uri):
441 """Return a :class:`.Namespace` corresponding to the given ``uri``.
442
443 If the given ``uri`` is a relative URI (i.e. it does not
444 contain a leading slash ``/``), the ``uri`` is adjusted to
445 be relative to the ``uri`` of the namespace itself. This
446 method is therefore mostly useful off of the built-in
447 ``local`` namespace, described in :ref:`namespace_local`.
448
449 In
450 most cases, a template wouldn't need this function, and
451 should instead use the ``<%namespace>`` tag to load
452 namespaces. However, since all ``<%namespace>`` tags are
453 evaluated before the body of a template ever runs,
454 this method can be used to locate namespaces using
455 expressions that were generated within the body code of
456 the template, or to conditionally use a particular
457 namespace.
458
459 """
460 key = (self, uri)
461 if key in self.context.namespaces:
462 return self.context.namespaces[key]
463 else:
464 ns = TemplateNamespace(uri, self.context._copy(),
465 templateuri=uri,
466 calling_uri=self._templateuri)
467 self.context.namespaces[key] = ns
468 return ns
469
470 def get_template(self, uri):
471 """Return a :class:`.Template` from the given ``uri``.
472
473 The ``uri`` resolution is relative to the ``uri`` of this
474 :class:`.Namespace` object's :class:`.Template`.
475
476 """
477 return _lookup_template(self.context, uri, self._templateuri)
478
479 def get_cached(self, key, **kwargs):
480 """Return a value from the :class:`.Cache` referenced by this
481 :class:`.Namespace` object's :class:`.Template`.
482
483 The advantage to this method versus direct access to the
484 :class:`.Cache` is that the configuration parameters
485 declared in ``<%page>`` take effect here, thereby calling
486 up the same configured backend as that configured
487 by ``<%page>``.
488
489 """
490
491 return self.cache.get(key, **kwargs)
492
493 @property
494 def cache(self):
495 """Return the :class:`.Cache` object referenced
496 by this :class:`.Namespace` object's
497 :class:`.Template`.
498
499 """
500 return self.template.cache
501
502 def include_file(self, uri, **kwargs):
503 """Include a file at the given ``uri``."""
504
505 _include_file(self.context, uri, self._templateuri, **kwargs)
506
507 def _populate(self, d, l):
508 for ident in l:
509 if ident == '*':
510 for (k, v) in self._get_star():
511 d[k] = v
512 else:
513 d[ident] = getattr(self, ident)
514
515 def _get_star(self):
516 if self.callables:
517 for key in self.callables:
518 yield (key, self.callables[key])
519
520 def __getattr__(self, key):
521 if key in self.callables:
522 val = self.callables[key]
523 elif self.inherits:
524 val = getattr(self.inherits, key)
525 else:
526 raise AttributeError(
527 "Namespace '%s' has no member '%s'" %
528 (self.name, key))
529 setattr(self, key, val)
530 return val
531
532 class TemplateNamespace(Namespace):
533 """A :class:`.Namespace` specific to a :class:`.Template` instance."""
534
535 def __init__(self, name, context, template=None, templateuri=None,
536 callables=None, inherits=None,
537 populate_self=True, calling_uri=None):
538 self.name = name
539 self.context = context
540 self.inherits = inherits
541 if callables is not None:
542 self.callables = dict([(c.__name__, c) for c in callables])
543
544 if templateuri is not None:
545 self.template = _lookup_template(context, templateuri,
546 calling_uri)
547 self._templateuri = self.template.module._template_uri
548 elif template is not None:
549 self.template = template
550 self._templateuri = template.module._template_uri
551 else:
552 raise TypeError("'template' argument is required.")
553
554 if populate_self:
555 lclcallable, lclcontext = \
556 _populate_self_namespace(context, self.template,
557 self_ns=self)
558
559 @property
560 def module(self):
561 """The Python module referenced by this :class:`.Namespace`.
562
563 If the namespace references a :class:`.Template`, then
564 this module is the equivalent of ``template.module``,
565 i.e. the generated module for the template.
566
567 """
568 return self.template.module
569
570 @property
571 def filename(self):
572 """The path of the filesystem file used for this
573 :class:`.Namespace`'s module or template.
574 """
575 return self.template.filename
576
577 @property
578 def uri(self):
579 """The URI for this :class:`.Namespace`'s template.
580
581 I.e. whatever was sent to :meth:`.TemplateLookup.get_template()`.
582
583 This is the equivalent of :attr:`.Template.uri`.
584
585 """
586 return self.template.uri
587
588 def _get_star(self):
589 if self.callables:
590 for key in self.callables:
591 yield (key, self.callables[key])
592 def get(key):
593 callable_ = self.template._get_def_callable(key)
594 return compat.partial(callable_, self.context)
595 for k in self.template.module._exports:
596 yield (k, get(k))
597
598 def __getattr__(self, key):
599 if key in self.callables:
600 val = self.callables[key]
601 elif self.template.has_def(key):
602 callable_ = self.template._get_def_callable(key)
603 val = compat.partial(callable_, self.context)
604 elif self.inherits:
605 val = getattr(self.inherits, key)
606
607 else:
608 raise AttributeError(
609 "Namespace '%s' has no member '%s'" %
610 (self.name, key))
611 setattr(self, key, val)
612 return val
613
614 class ModuleNamespace(Namespace):
615 """A :class:`.Namespace` specific to a Python module instance."""
616
617 def __init__(self, name, context, module,
618 callables=None, inherits=None,
619 populate_self=True, calling_uri=None):
620 self.name = name
621 self.context = context
622 self.inherits = inherits
623 if callables is not None:
624 self.callables = dict([(c.__name__, c) for c in callables])
625
626 mod = __import__(module)
627 for token in module.split('.')[1:]:
628 mod = getattr(mod, token)
629 self.module = mod
630
631 @property
632 def filename(self):
633 """The path of the filesystem file used for this
634 :class:`.Namespace`'s module or template.
635 """
636 return self.module.__file__
637
638 def _get_star(self):
639 if self.callables:
640 for key in self.callables:
641 yield (key, self.callables[key])
642 for key in dir(self.module):
643 if key[0] != '_':
644 callable_ = getattr(self.module, key)
645 if compat.callable(callable_):
646 yield key, compat.partial(callable_, self.context)
647
648
649 def __getattr__(self, key):
650 if key in self.callables:
651 val = self.callables[key]
652 elif hasattr(self.module, key):
653 callable_ = getattr(self.module, key)
654 val = compat.partial(callable_, self.context)
655 elif self.inherits:
656 val = getattr(self.inherits, key)
657 else:
658 raise AttributeError(
659 "Namespace '%s' has no member '%s'" %
660 (self.name, key))
661 setattr(self, key, val)
662 return val
663
664 def supports_caller(func):
665 """Apply a caller_stack compatibility decorator to a plain
666 Python function.
667
668 See the example in :ref:`namespaces_python_modules`.
669
670 """
671
672 def wrap_stackframe(context, *args, **kwargs):
673 context.caller_stack._push_frame()
674 try:
675 return func(context, *args, **kwargs)
676 finally:
677 context.caller_stack._pop_frame()
678 return wrap_stackframe
679
680 def capture(context, callable_, *args, **kwargs):
681 """Execute the given template def, capturing the output into
682 a buffer.
683
684 See the example in :ref:`namespaces_python_modules`.
685
686 """
687
688 if not compat.callable(callable_):
689 raise exceptions.RuntimeException(
690 "capture() function expects a callable as "
691 "its argument (i.e. capture(func, *args, **kwargs))"
692 )
693 context._push_buffer()
694 try:
695 callable_(*args, **kwargs)
696 finally:
697 buf = context._pop_buffer()
698 return buf.getvalue()
699
700 def _decorate_toplevel(fn):
701 def decorate_render(render_fn):
702 def go(context, *args, **kw):
703 def y(*args, **kw):
704 return render_fn(context, *args, **kw)
705 try:
706 y.__name__ = render_fn.__name__[7:]
707 except TypeError:
708 # < Python 2.4
709 pass
710 return fn(y)(context, *args, **kw)
711 return go
712 return decorate_render
713
714 def _decorate_inline(context, fn):
715 def decorate_render(render_fn):
716 dec = fn(render_fn)
717 def go(*args, **kw):
718 return dec(context, *args, **kw)
719 return go
720 return decorate_render
721
722 def _include_file(context, uri, calling_uri, **kwargs):
723 """locate the template from the given uri and include it in
724 the current output."""
725
726 template = _lookup_template(context, uri, calling_uri)
727 (callable_, ctx) = _populate_self_namespace(
728 context._clean_inheritance_tokens(),
729 template)
730 callable_(ctx, **_kwargs_for_include(callable_, context._data, **kwargs))
731
732 def _inherit_from(context, uri, calling_uri):
733 """called by the _inherit method in template modules to set
734 up the inheritance chain at the start of a template's
735 execution."""
736
737 if uri is None:
738 return None
739 template = _lookup_template(context, uri, calling_uri)
740 self_ns = context['self']
741 ih = self_ns
742 while ih.inherits is not None:
743 ih = ih.inherits
744 lclcontext = context._locals({'next': ih})
745 ih.inherits = TemplateNamespace("self:%s" % template.uri,
746 lclcontext,
747 template=template,
748 populate_self=False)
749 context._data['parent'] = lclcontext._data['local'] = ih.inherits
750 callable_ = getattr(template.module, '_mako_inherit', None)
751 if callable_ is not None:
752 ret = callable_(template, lclcontext)
753 if ret:
754 return ret
755
756 gen_ns = getattr(template.module, '_mako_generate_namespaces', None)
757 if gen_ns is not None:
758 gen_ns(context)
759 return (template.callable_, lclcontext)
760
761 def _lookup_template(context, uri, relativeto):
762 lookup = context._with_template.lookup
763 if lookup is None:
764 raise exceptions.TemplateLookupException(
765 "Template '%s' has no TemplateLookup associated" %
766 context._with_template.uri)
767 uri = lookup.adjust_uri(uri, relativeto)
768 try:
769 return lookup.get_template(uri)
770 except exceptions.TopLevelLookupException:
771 raise exceptions.TemplateLookupException(str(compat.exception_as()))
772
773 def _populate_self_namespace(context, template, self_ns=None):
774 if self_ns is None:
775 self_ns = TemplateNamespace('self:%s' % template.uri,
776 context, template=template,
777 populate_self=False)
778 context._data['self'] = context._data['local'] = self_ns
779 if hasattr(template.module, '_mako_inherit'):
780 ret = template.module._mako_inherit(template, context)
781 if ret:
782 return ret
783 return (template.callable_, context)
784
785 def _render(template, callable_, args, data, as_unicode=False):
786 """create a Context and return the string
787 output of the given template and template callable."""
788
789 if as_unicode:
790 buf = util.FastEncodingBuffer(as_unicode=True)
791 elif template.bytestring_passthrough:
792 buf = compat.StringIO()
793 else:
794 buf = util.FastEncodingBuffer(
795 as_unicode=as_unicode,
796 encoding=template.output_encoding,
797 errors=template.encoding_errors)
798 context = Context(buf, **data)
799 context._outputting_as_unicode = as_unicode
800 context._set_with_template(template)
801
802 _render_context(template, callable_, context, *args,
803 **_kwargs_for_callable(callable_, data))
804 return context._pop_buffer().getvalue()
805
806 def _kwargs_for_callable(callable_, data):
807 argspec = compat.inspect_func_args(callable_)
808 # for normal pages, **pageargs is usually present
809 if argspec[2]:
810 return data
811
812 # for rendering defs from the top level, figure out the args
813 namedargs = argspec[0] + [v for v in argspec[1:3] if v is not None]
814 kwargs = {}
815 for arg in namedargs:
816 if arg != 'context' and arg in data and arg not in kwargs:
817 kwargs[arg] = data[arg]
818 return kwargs
819
820 def _kwargs_for_include(callable_, data, **kwargs):
821 argspec = compat.inspect_func_args(callable_)
822 namedargs = argspec[0] + [v for v in argspec[1:3] if v is not None]
823 for arg in namedargs:
824 if arg != 'context' and arg in data and arg not in kwargs:
825 kwargs[arg] = data[arg]
826 return kwargs
827
828 def _render_context(tmpl, callable_, context, *args, **kwargs):
829 import mako.template as template
830 # create polymorphic 'self' namespace for this
831 # template with possibly updated context
832 if not isinstance(tmpl, template.DefTemplate):
833 # if main render method, call from the base of the inheritance stack
834 (inherit, lclcontext) = _populate_self_namespace(context, tmpl)
835 _exec_template(inherit, lclcontext, args=args, kwargs=kwargs)
836 else:
837 # otherwise, call the actual rendering method specified
838 (inherit, lclcontext) = _populate_self_namespace(context, tmpl.parent)
839 _exec_template(callable_, context, args=args, kwargs=kwargs)
840
841 def _exec_template(callable_, context, args=None, kwargs=None):
842 """execute a rendering callable given the callable, a
843 Context, and optional explicit arguments
844
845 the contextual Template will be located if it exists, and
846 the error handling options specified on that Template will
847 be interpreted here.
848 """
849 template = context._with_template
850 if template is not None and \
851 (template.format_exceptions or template.error_handler):
852 try:
853 callable_(context, *args, **kwargs)
854 except Exception:
855 _render_error(template, context, compat.exception_as())
856 except:
857 e = sys.exc_info()[0]
858 _render_error(template, context, e)
859 else:
860 callable_(context, *args, **kwargs)
861
862 def _render_error(template, context, error):
863 if template.error_handler:
864 result = template.error_handler(context, error)
865 if not result:
866 compat.reraise(*sys.exc_info())
867 else:
868 error_template = exceptions.html_error_template()
869 if context._outputting_as_unicode:
870 context._buffer_stack[:] = [
871 util.FastEncodingBuffer(as_unicode=True)]
872 else:
873 context._buffer_stack[:] = [util.FastEncodingBuffer(
874 error_template.output_encoding,
875 error_template.encoding_errors)]
876
877 context._set_with_template(error_template)
878 error_template.render_context(context, error=error)