1# -*- coding: utf-8 -*- 2"""The runtime functions and state used by compiled templates.""" 3import sys 4from itertools import chain 5from types import MethodType 6 7from markupsafe import escape # noqa: F401 8from markupsafe import Markup 9from markupsafe import soft_unicode 10 11from ._compat import abc 12from ._compat import imap 13from ._compat import implements_iterator 14from ._compat import implements_to_string 15from ._compat import iteritems 16from ._compat import PY2 17from ._compat import string_types 18from ._compat import text_type 19from ._compat import with_metaclass 20from .exceptions import TemplateNotFound # noqa: F401 21from .exceptions import TemplateRuntimeError # noqa: F401 22from .exceptions import UndefinedError 23from .nodes import EvalContext 24from .utils import concat 25from .utils import evalcontextfunction 26from .utils import internalcode 27from .utils import missing 28from .utils import Namespace # noqa: F401 29from .utils import object_type_repr 30 31# these variables are exported to the template runtime 32exported = [ 33 "LoopContext", 34 "TemplateReference", 35 "Macro", 36 "Markup", 37 "TemplateRuntimeError", 38 "missing", 39 "concat", 40 "escape", 41 "markup_join", 42 "unicode_join", 43 "to_string", 44 "identity", 45 "TemplateNotFound", 46 "Namespace", 47 "Undefined", 48] 49 50#: the name of the function that is used to convert something into 51#: a string. We can just use the text type here. 52to_string = text_type 53 54 55def identity(x): 56 """Returns its argument. Useful for certain things in the 57 environment. 58 """ 59 return x 60 61 62def markup_join(seq): 63 """Concatenation that escapes if necessary and converts to unicode.""" 64 buf = [] 65 iterator = imap(soft_unicode, seq) 66 for arg in iterator: 67 buf.append(arg) 68 if hasattr(arg, "__html__"): 69 return Markup(u"").join(chain(buf, iterator)) 70 return concat(buf) 71 72 73def unicode_join(seq): 74 """Simple args to unicode conversion and concatenation.""" 75 return concat(imap(text_type, seq)) 76 77 78def new_context( 79 environment, 80 template_name, 81 blocks, 82 vars=None, 83 shared=None, 84 globals=None, 85 locals=None, 86): 87 """Internal helper for context creation.""" 88 if vars is None: 89 vars = {} 90 if shared: 91 parent = vars 92 else: 93 parent = dict(globals or (), **vars) 94 if locals: 95 # if the parent is shared a copy should be created because 96 # we don't want to modify the dict passed 97 if shared: 98 parent = dict(parent) 99 for key, value in iteritems(locals): 100 if value is not missing: 101 parent[key] = value 102 return environment.context_class(environment, parent, template_name, blocks) 103 104 105class TemplateReference(object): 106 """The `self` in templates.""" 107 108 def __init__(self, context): 109 self.__context = context 110 111 def __getitem__(self, name): 112 blocks = self.__context.blocks[name] 113 return BlockReference(name, self.__context, blocks, 0) 114 115 def __repr__(self): 116 return "<%s %r>" % (self.__class__.__name__, self.__context.name) 117 118 119def _get_func(x): 120 return getattr(x, "__func__", x) 121 122 123class ContextMeta(type): 124 def __new__(mcs, name, bases, d): 125 rv = type.__new__(mcs, name, bases, d) 126 if bases == (): 127 return rv 128 129 resolve = _get_func(rv.resolve) 130 default_resolve = _get_func(Context.resolve) 131 resolve_or_missing = _get_func(rv.resolve_or_missing) 132 default_resolve_or_missing = _get_func(Context.resolve_or_missing) 133 134 # If we have a changed resolve but no changed default or missing 135 # resolve we invert the call logic. 136 if ( 137 resolve is not default_resolve 138 and resolve_or_missing is default_resolve_or_missing 139 ): 140 rv._legacy_resolve_mode = True 141 elif ( 142 resolve is default_resolve 143 and resolve_or_missing is default_resolve_or_missing 144 ): 145 rv._fast_resolve_mode = True 146 147 return rv 148 149 150def resolve_or_missing(context, key, missing=missing): 151 if key in context.vars: 152 return context.vars[key] 153 if key in context.parent: 154 return context.parent[key] 155 return missing 156 157 158class Context(with_metaclass(ContextMeta)): 159 """The template context holds the variables of a template. It stores the 160 values passed to the template and also the names the template exports. 161 Creating instances is neither supported nor useful as it's created 162 automatically at various stages of the template evaluation and should not 163 be created by hand. 164 165 The context is immutable. Modifications on :attr:`parent` **must not** 166 happen and modifications on :attr:`vars` are allowed from generated 167 template code only. Template filters and global functions marked as 168 :func:`contextfunction`\\s get the active context passed as first argument 169 and are allowed to access the context read-only. 170 171 The template context supports read only dict operations (`get`, 172 `keys`, `values`, `items`, `iterkeys`, `itervalues`, `iteritems`, 173 `__getitem__`, `__contains__`). Additionally there is a :meth:`resolve` 174 method that doesn't fail with a `KeyError` but returns an 175 :class:`Undefined` object for missing variables. 176 """ 177 178 # XXX: we want to eventually make this be a deprecation warning and 179 # remove it. 180 _legacy_resolve_mode = False 181 _fast_resolve_mode = False 182 183 def __init__(self, environment, parent, name, blocks): 184 self.parent = parent 185 self.vars = {} 186 self.environment = environment 187 self.eval_ctx = EvalContext(self.environment, name) 188 self.exported_vars = set() 189 self.name = name 190 191 # create the initial mapping of blocks. Whenever template inheritance 192 # takes place the runtime will update this mapping with the new blocks 193 # from the template. 194 self.blocks = dict((k, [v]) for k, v in iteritems(blocks)) 195 196 # In case we detect the fast resolve mode we can set up an alias 197 # here that bypasses the legacy code logic. 198 if self._fast_resolve_mode: 199 self.resolve_or_missing = MethodType(resolve_or_missing, self) 200 201 def super(self, name, current): 202 """Render a parent block.""" 203 try: 204 blocks = self.blocks[name] 205 index = blocks.index(current) + 1 206 blocks[index] 207 except LookupError: 208 return self.environment.undefined( 209 "there is no parent block called %r." % name, name="super" 210 ) 211 return BlockReference(name, self, blocks, index) 212 213 def get(self, key, default=None): 214 """Returns an item from the template context, if it doesn't exist 215 `default` is returned. 216 """ 217 try: 218 return self[key] 219 except KeyError: 220 return default 221 222 def resolve(self, key): 223 """Looks up a variable like `__getitem__` or `get` but returns an 224 :class:`Undefined` object with the name of the name looked up. 225 """ 226 if self._legacy_resolve_mode: 227 rv = resolve_or_missing(self, key) 228 else: 229 rv = self.resolve_or_missing(key) 230 if rv is missing: 231 return self.environment.undefined(name=key) 232 return rv 233 234 def resolve_or_missing(self, key): 235 """Resolves a variable like :meth:`resolve` but returns the 236 special `missing` value if it cannot be found. 237 """ 238 if self._legacy_resolve_mode: 239 rv = self.resolve(key) 240 if isinstance(rv, Undefined): 241 rv = missing 242 return rv 243 return resolve_or_missing(self, key) 244 245 def get_exported(self): 246 """Get a new dict with the exported variables.""" 247 return dict((k, self.vars[k]) for k in self.exported_vars) 248 249 def get_all(self): 250 """Return the complete context as dict including the exported 251 variables. For optimizations reasons this might not return an 252 actual copy so be careful with using it. 253 """ 254 if not self.vars: 255 return self.parent 256 if not self.parent: 257 return self.vars 258 return dict(self.parent, **self.vars) 259 260 @internalcode 261 def call(__self, __obj, *args, **kwargs): # noqa: B902 262 """Call the callable with the arguments and keyword arguments 263 provided but inject the active context or environment as first 264 argument if the callable is a :func:`contextfunction` or 265 :func:`environmentfunction`. 266 """ 267 if __debug__: 268 __traceback_hide__ = True # noqa 269 270 # Allow callable classes to take a context 271 if hasattr(__obj, "__call__"): # noqa: B004 272 fn = __obj.__call__ 273 for fn_type in ( 274 "contextfunction", 275 "evalcontextfunction", 276 "environmentfunction", 277 ): 278 if hasattr(fn, fn_type): 279 __obj = fn 280 break 281 282 if callable(__obj): 283 if getattr(__obj, "contextfunction", False) is True: 284 args = (__self,) + args 285 elif getattr(__obj, "evalcontextfunction", False) is True: 286 args = (__self.eval_ctx,) + args 287 elif getattr(__obj, "environmentfunction", False) is True: 288 args = (__self.environment,) + args 289 try: 290 return __obj(*args, **kwargs) 291 except StopIteration: 292 return __self.environment.undefined( 293 "value was undefined because " 294 "a callable raised a " 295 "StopIteration exception" 296 ) 297 298 def derived(self, locals=None): 299 """Internal helper function to create a derived context. This is 300 used in situations where the system needs a new context in the same 301 template that is independent. 302 """ 303 context = new_context( 304 self.environment, self.name, {}, self.get_all(), True, None, locals 305 ) 306 context.eval_ctx = self.eval_ctx 307 context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks)) 308 return context 309 310 def _all(meth): # noqa: B902 311 def proxy(self): 312 return getattr(self.get_all(), meth)() 313 314 proxy.__doc__ = getattr(dict, meth).__doc__ 315 proxy.__name__ = meth 316 return proxy 317 318 keys = _all("keys") 319 values = _all("values") 320 items = _all("items") 321 322 # not available on python 3 323 if PY2: 324 iterkeys = _all("iterkeys") 325 itervalues = _all("itervalues") 326 iteritems = _all("iteritems") 327 del _all 328 329 def __contains__(self, name): 330 return name in self.vars or name in self.parent 331 332 def __getitem__(self, key): 333 """Lookup a variable or raise `KeyError` if the variable is 334 undefined. 335 """ 336 item = self.resolve_or_missing(key) 337 if item is missing: 338 raise KeyError(key) 339 return item 340 341 def __repr__(self): 342 return "<%s %s of %r>" % ( 343 self.__class__.__name__, 344 repr(self.get_all()), 345 self.name, 346 ) 347 348 349abc.Mapping.register(Context) 350 351 352class BlockReference(object): 353 """One block on a template reference.""" 354 355 def __init__(self, name, context, stack, depth): 356 self.name = name 357 self._context = context 358 self._stack = stack 359 self._depth = depth 360 361 @property 362 def super(self): 363 """Super the block.""" 364 if self._depth + 1 >= len(self._stack): 365 return self._context.environment.undefined( 366 "there is no parent block called %r." % self.name, name="super" 367 ) 368 return BlockReference(self.name, self._context, self._stack, self._depth + 1) 369 370 @internalcode 371 def __call__(self): 372 rv = concat(self._stack[self._depth](self._context)) 373 if self._context.eval_ctx.autoescape: 374 rv = Markup(rv) 375 return rv 376 377 378@implements_iterator 379class LoopContext: 380 """A wrapper iterable for dynamic ``for`` loops, with information 381 about the loop and iteration. 382 """ 383 384 #: Current iteration of the loop, starting at 0. 385 index0 = -1 386 387 _length = None 388 _after = missing 389 _current = missing 390 _before = missing 391 _last_changed_value = missing 392 393 def __init__(self, iterable, undefined, recurse=None, depth0=0): 394 """ 395 :param iterable: Iterable to wrap. 396 :param undefined: :class:`Undefined` class to use for next and 397 previous items. 398 :param recurse: The function to render the loop body when the 399 loop is marked recursive. 400 :param depth0: Incremented when looping recursively. 401 """ 402 self._iterable = iterable 403 self._iterator = self._to_iterator(iterable) 404 self._undefined = undefined 405 self._recurse = recurse 406 #: How many levels deep a recursive loop currently is, starting at 0. 407 self.depth0 = depth0 408 409 @staticmethod 410 def _to_iterator(iterable): 411 return iter(iterable) 412 413 @property 414 def length(self): 415 """Length of the iterable. 416 417 If the iterable is a generator or otherwise does not have a 418 size, it is eagerly evaluated to get a size. 419 """ 420 if self._length is not None: 421 return self._length 422 423 try: 424 self._length = len(self._iterable) 425 except TypeError: 426 iterable = list(self._iterator) 427 self._iterator = self._to_iterator(iterable) 428 self._length = len(iterable) + self.index + (self._after is not missing) 429 430 return self._length 431 432 def __len__(self): 433 return self.length 434 435 @property 436 def depth(self): 437 """How many levels deep a recursive loop currently is, starting at 1.""" 438 return self.depth0 + 1 439 440 @property 441 def index(self): 442 """Current iteration of the loop, starting at 1.""" 443 return self.index0 + 1 444 445 @property 446 def revindex0(self): 447 """Number of iterations from the end of the loop, ending at 0. 448 449 Requires calculating :attr:`length`. 450 """ 451 return self.length - self.index 452 453 @property 454 def revindex(self): 455 """Number of iterations from the end of the loop, ending at 1. 456 457 Requires calculating :attr:`length`. 458 """ 459 return self.length - self.index0 460 461 @property 462 def first(self): 463 """Whether this is the first iteration of the loop.""" 464 return self.index0 == 0 465 466 def _peek_next(self): 467 """Return the next element in the iterable, or :data:`missing` 468 if the iterable is exhausted. Only peeks one item ahead, caching 469 the result in :attr:`_last` for use in subsequent checks. The 470 cache is reset when :meth:`__next__` is called. 471 """ 472 if self._after is not missing: 473 return self._after 474 475 self._after = next(self._iterator, missing) 476 return self._after 477 478 @property 479 def last(self): 480 """Whether this is the last iteration of the loop. 481 482 Causes the iterable to advance early. See 483 :func:`itertools.groupby` for issues this can cause. 484 The :func:`groupby` filter avoids that issue. 485 """ 486 return self._peek_next() is missing 487 488 @property 489 def previtem(self): 490 """The item in the previous iteration. Undefined during the 491 first iteration. 492 """ 493 if self.first: 494 return self._undefined("there is no previous item") 495 496 return self._before 497 498 @property 499 def nextitem(self): 500 """The item in the next iteration. Undefined during the last 501 iteration. 502 503 Causes the iterable to advance early. See 504 :func:`itertools.groupby` for issues this can cause. 505 The :func:`groupby` filter avoids that issue. 506 """ 507 rv = self._peek_next() 508 509 if rv is missing: 510 return self._undefined("there is no next item") 511 512 return rv 513 514 def cycle(self, *args): 515 """Return a value from the given args, cycling through based on 516 the current :attr:`index0`. 517 518 :param args: One or more values to cycle through. 519 """ 520 if not args: 521 raise TypeError("no items for cycling given") 522 523 return args[self.index0 % len(args)] 524 525 def changed(self, *value): 526 """Return ``True`` if previously called with a different value 527 (including when called for the first time). 528 529 :param value: One or more values to compare to the last call. 530 """ 531 if self._last_changed_value != value: 532 self._last_changed_value = value 533 return True 534 535 return False 536 537 def __iter__(self): 538 return self 539 540 def __next__(self): 541 if self._after is not missing: 542 rv = self._after 543 self._after = missing 544 else: 545 rv = next(self._iterator) 546 547 self.index0 += 1 548 self._before = self._current 549 self._current = rv 550 return rv, self 551 552 @internalcode 553 def __call__(self, iterable): 554 """When iterating over nested data, render the body of the loop 555 recursively with the given inner iterable data. 556 557 The loop must have the ``recursive`` marker for this to work. 558 """ 559 if self._recurse is None: 560 raise TypeError( 561 "The loop must have the 'recursive' marker to be called recursively." 562 ) 563 564 return self._recurse(iterable, self._recurse, depth=self.depth) 565 566 def __repr__(self): 567 return "<%s %d/%d>" % (self.__class__.__name__, self.index, self.length) 568 569 570class Macro(object): 571 """Wraps a macro function.""" 572 573 def __init__( 574 self, 575 environment, 576 func, 577 name, 578 arguments, 579 catch_kwargs, 580 catch_varargs, 581 caller, 582 default_autoescape=None, 583 ): 584 self._environment = environment 585 self._func = func 586 self._argument_count = len(arguments) 587 self.name = name 588 self.arguments = arguments 589 self.catch_kwargs = catch_kwargs 590 self.catch_varargs = catch_varargs 591 self.caller = caller 592 self.explicit_caller = "caller" in arguments 593 if default_autoescape is None: 594 default_autoescape = environment.autoescape 595 self._default_autoescape = default_autoescape 596 597 @internalcode 598 @evalcontextfunction 599 def __call__(self, *args, **kwargs): 600 # This requires a bit of explanation, In the past we used to 601 # decide largely based on compile-time information if a macro is 602 # safe or unsafe. While there was a volatile mode it was largely 603 # unused for deciding on escaping. This turns out to be 604 # problematic for macros because whether a macro is safe depends not 605 # on the escape mode when it was defined, but rather when it was used. 606 # 607 # Because however we export macros from the module system and 608 # there are historic callers that do not pass an eval context (and 609 # will continue to not pass one), we need to perform an instance 610 # check here. 611 # 612 # This is considered safe because an eval context is not a valid 613 # argument to callables otherwise anyway. Worst case here is 614 # that if no eval context is passed we fall back to the compile 615 # time autoescape flag. 616 if args and isinstance(args[0], EvalContext): 617 autoescape = args[0].autoescape 618 args = args[1:] 619 else: 620 autoescape = self._default_autoescape 621 622 # try to consume the positional arguments 623 arguments = list(args[: self._argument_count]) 624 off = len(arguments) 625 626 # For information why this is necessary refer to the handling 627 # of caller in the `macro_body` handler in the compiler. 628 found_caller = False 629 630 # if the number of arguments consumed is not the number of 631 # arguments expected we start filling in keyword arguments 632 # and defaults. 633 if off != self._argument_count: 634 for name in self.arguments[len(arguments) :]: 635 try: 636 value = kwargs.pop(name) 637 except KeyError: 638 value = missing 639 if name == "caller": 640 found_caller = True 641 arguments.append(value) 642 else: 643 found_caller = self.explicit_caller 644 645 # it's important that the order of these arguments does not change 646 # if not also changed in the compiler's `function_scoping` method. 647 # the order is caller, keyword arguments, positional arguments! 648 if self.caller and not found_caller: 649 caller = kwargs.pop("caller", None) 650 if caller is None: 651 caller = self._environment.undefined("No caller defined", name="caller") 652 arguments.append(caller) 653 654 if self.catch_kwargs: 655 arguments.append(kwargs) 656 elif kwargs: 657 if "caller" in kwargs: 658 raise TypeError( 659 "macro %r was invoked with two values for " 660 "the special caller argument. This is " 661 "most likely a bug." % self.name 662 ) 663 raise TypeError( 664 "macro %r takes no keyword argument %r" 665 % (self.name, next(iter(kwargs))) 666 ) 667 if self.catch_varargs: 668 arguments.append(args[self._argument_count :]) 669 elif len(args) > self._argument_count: 670 raise TypeError( 671 "macro %r takes not more than %d argument(s)" 672 % (self.name, len(self.arguments)) 673 ) 674 675 return self._invoke(arguments, autoescape) 676 677 def _invoke(self, arguments, autoescape): 678 """This method is being swapped out by the async implementation.""" 679 rv = self._func(*arguments) 680 if autoescape: 681 rv = Markup(rv) 682 return rv 683 684 def __repr__(self): 685 return "<%s %s>" % ( 686 self.__class__.__name__, 687 self.name is None and "anonymous" or repr(self.name), 688 ) 689 690 691@implements_to_string 692class Undefined(object): 693 """The default undefined type. This undefined type can be printed and 694 iterated over, but every other access will raise an :exc:`UndefinedError`: 695 696 >>> foo = Undefined(name='foo') 697 >>> str(foo) 698 '' 699 >>> not foo 700 True 701 >>> foo + 42 702 Traceback (most recent call last): 703 ... 704 jinja2.exceptions.UndefinedError: 'foo' is undefined 705 """ 706 707 __slots__ = ( 708 "_undefined_hint", 709 "_undefined_obj", 710 "_undefined_name", 711 "_undefined_exception", 712 ) 713 714 def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError): 715 self._undefined_hint = hint 716 self._undefined_obj = obj 717 self._undefined_name = name 718 self._undefined_exception = exc 719 720 @property 721 def _undefined_message(self): 722 """Build a message about the undefined value based on how it was 723 accessed. 724 """ 725 if self._undefined_hint: 726 return self._undefined_hint 727 728 if self._undefined_obj is missing: 729 return "%r is undefined" % self._undefined_name 730 731 if not isinstance(self._undefined_name, string_types): 732 return "%s has no element %r" % ( 733 object_type_repr(self._undefined_obj), 734 self._undefined_name, 735 ) 736 737 return "%r has no attribute %r" % ( 738 object_type_repr(self._undefined_obj), 739 self._undefined_name, 740 ) 741 742 @internalcode 743 def _fail_with_undefined_error(self, *args, **kwargs): 744 """Raise an :exc:`UndefinedError` when operations are performed 745 on the undefined value. 746 """ 747 raise self._undefined_exception(self._undefined_message) 748 749 @internalcode 750 def __getattr__(self, name): 751 if name[:2] == "__": 752 raise AttributeError(name) 753 return self._fail_with_undefined_error() 754 755 __add__ = ( 756 __radd__ 757 ) = ( 758 __mul__ 759 ) = ( 760 __rmul__ 761 ) = ( 762 __div__ 763 ) = ( 764 __rdiv__ 765 ) = ( 766 __truediv__ 767 ) = ( 768 __rtruediv__ 769 ) = ( 770 __floordiv__ 771 ) = ( 772 __rfloordiv__ 773 ) = ( 774 __mod__ 775 ) = ( 776 __rmod__ 777 ) = ( 778 __pos__ 779 ) = ( 780 __neg__ 781 ) = ( 782 __call__ 783 ) = ( 784 __getitem__ 785 ) = ( 786 __lt__ 787 ) = ( 788 __le__ 789 ) = ( 790 __gt__ 791 ) = ( 792 __ge__ 793 ) = ( 794 __int__ 795 ) = ( 796 __float__ 797 ) = ( 798 __complex__ 799 ) = __pow__ = __rpow__ = __sub__ = __rsub__ = _fail_with_undefined_error 800 801 def __eq__(self, other): 802 return type(self) is type(other) 803 804 def __ne__(self, other): 805 return not self.__eq__(other) 806 807 def __hash__(self): 808 return id(type(self)) 809 810 def __str__(self): 811 return u"" 812 813 def __len__(self): 814 return 0 815 816 def __iter__(self): 817 if 0: 818 yield None 819 820 def __nonzero__(self): 821 return False 822 823 __bool__ = __nonzero__ 824 825 def __repr__(self): 826 return "Undefined" 827 828 829def make_logging_undefined(logger=None, base=None): 830 """Given a logger object this returns a new undefined class that will 831 log certain failures. It will log iterations and printing. If no 832 logger is given a default logger is created. 833 834 Example:: 835 836 logger = logging.getLogger(__name__) 837 LoggingUndefined = make_logging_undefined( 838 logger=logger, 839 base=Undefined 840 ) 841 842 .. versionadded:: 2.8 843 844 :param logger: the logger to use. If not provided, a default logger 845 is created. 846 :param base: the base class to add logging functionality to. This 847 defaults to :class:`Undefined`. 848 """ 849 if logger is None: 850 import logging 851 852 logger = logging.getLogger(__name__) 853 logger.addHandler(logging.StreamHandler(sys.stderr)) 854 if base is None: 855 base = Undefined 856 857 def _log_message(undef): 858 if undef._undefined_hint is None: 859 if undef._undefined_obj is missing: 860 hint = "%s is undefined" % undef._undefined_name 861 elif not isinstance(undef._undefined_name, string_types): 862 hint = "%s has no element %s" % ( 863 object_type_repr(undef._undefined_obj), 864 undef._undefined_name, 865 ) 866 else: 867 hint = "%s has no attribute %s" % ( 868 object_type_repr(undef._undefined_obj), 869 undef._undefined_name, 870 ) 871 else: 872 hint = undef._undefined_hint 873 logger.warning("Template variable warning: %s", hint) 874 875 class LoggingUndefined(base): 876 def _fail_with_undefined_error(self, *args, **kwargs): 877 try: 878 return base._fail_with_undefined_error(self, *args, **kwargs) 879 except self._undefined_exception as e: 880 logger.error("Template variable error: %s", str(e)) 881 raise e 882 883 def __str__(self): 884 rv = base.__str__(self) 885 _log_message(self) 886 return rv 887 888 def __iter__(self): 889 rv = base.__iter__(self) 890 _log_message(self) 891 return rv 892 893 if PY2: 894 895 def __nonzero__(self): 896 rv = base.__nonzero__(self) 897 _log_message(self) 898 return rv 899 900 def __unicode__(self): 901 rv = base.__unicode__(self) 902 _log_message(self) 903 return rv 904 905 else: 906 907 def __bool__(self): 908 rv = base.__bool__(self) 909 _log_message(self) 910 return rv 911 912 return LoggingUndefined 913 914 915# No @implements_to_string decorator here because __str__ 916# is not overwritten from Undefined in this class. 917# This would cause a recursion error in Python 2. 918class ChainableUndefined(Undefined): 919 """An undefined that is chainable, where both ``__getattr__`` and 920 ``__getitem__`` return itself rather than raising an 921 :exc:`UndefinedError`. 922 923 >>> foo = ChainableUndefined(name='foo') 924 >>> str(foo.bar['baz']) 925 '' 926 >>> foo.bar['baz'] + 42 927 Traceback (most recent call last): 928 ... 929 jinja2.exceptions.UndefinedError: 'foo' is undefined 930 931 .. versionadded:: 2.11.0 932 """ 933 934 __slots__ = () 935 936 def __html__(self): 937 return self.__str__() 938 939 def __getattr__(self, _): 940 return self 941 942 __getitem__ = __getattr__ 943 944 945@implements_to_string 946class DebugUndefined(Undefined): 947 """An undefined that returns the debug info when printed. 948 949 >>> foo = DebugUndefined(name='foo') 950 >>> str(foo) 951 '{{ foo }}' 952 >>> not foo 953 True 954 >>> foo + 42 955 Traceback (most recent call last): 956 ... 957 jinja2.exceptions.UndefinedError: 'foo' is undefined 958 """ 959 960 __slots__ = () 961 962 def __str__(self): 963 if self._undefined_hint is None: 964 if self._undefined_obj is missing: 965 return u"{{ %s }}" % self._undefined_name 966 return "{{ no such element: %s[%r] }}" % ( 967 object_type_repr(self._undefined_obj), 968 self._undefined_name, 969 ) 970 return u"{{ undefined value printed: %s }}" % self._undefined_hint 971 972 973@implements_to_string 974class StrictUndefined(Undefined): 975 """An undefined that barks on print and iteration as well as boolean 976 tests and all kinds of comparisons. In other words: you can do nothing 977 with it except checking if it's defined using the `defined` test. 978 979 >>> foo = StrictUndefined(name='foo') 980 >>> str(foo) 981 Traceback (most recent call last): 982 ... 983 jinja2.exceptions.UndefinedError: 'foo' is undefined 984 >>> not foo 985 Traceback (most recent call last): 986 ... 987 jinja2.exceptions.UndefinedError: 'foo' is undefined 988 >>> foo + 42 989 Traceback (most recent call last): 990 ... 991 jinja2.exceptions.UndefinedError: 'foo' is undefined 992 """ 993 994 __slots__ = () 995 __iter__ = ( 996 __str__ 997 ) = ( 998 __len__ 999 ) = ( 1000 __nonzero__ 1001 ) = __eq__ = __ne__ = __bool__ = __hash__ = Undefined._fail_with_undefined_error 1002 1003 1004# remove remaining slots attributes, after the metaclass did the magic they 1005# are unneeded and irritating as they contain wrong data for the subclasses. 1006del ( 1007 Undefined.__slots__, 1008 ChainableUndefined.__slots__, 1009 DebugUndefined.__slots__, 1010 StrictUndefined.__slots__, 1011) 1012