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) 879