| OLD | NEW |
| 1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
| 2 """ | 2 """ |
| 3 jinja2.runtime | 3 jinja2.runtime |
| 4 ~~~~~~~~~~~~~~ | 4 ~~~~~~~~~~~~~~ |
| 5 | 5 |
| 6 Runtime helpers. | 6 Runtime helpers. |
| 7 | 7 |
| 8 :copyright: (c) 2010 by the Jinja Team. | 8 :copyright: (c) 2010 by the Jinja Team. |
| 9 :license: BSD. | 9 :license: BSD. |
| 10 """ | 10 """ |
| 11 import sys |
| 12 |
| 11 from itertools import chain | 13 from itertools import chain |
| 12 from jinja2.nodes import EvalContext, _context_function_types | 14 from jinja2.nodes import EvalContext, _context_function_types |
| 13 from jinja2.utils import Markup, soft_unicode, escape, missing, concat, \ | 15 from jinja2.utils import Markup, soft_unicode, escape, missing, concat, \ |
| 14 internalcode, object_type_repr | 16 internalcode, object_type_repr |
| 15 from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \ | 17 from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \ |
| 16 TemplateNotFound | 18 TemplateNotFound |
| 17 from jinja2._compat import next, imap, text_type, iteritems, \ | 19 from jinja2._compat import imap, text_type, iteritems, \ |
| 18 implements_iterator, implements_to_string, string_types, PY2 | 20 implements_iterator, implements_to_string, string_types, PY2 |
| 19 | 21 |
| 20 | 22 |
| 21 # these variables are exported to the template runtime | 23 # these variables are exported to the template runtime |
| 22 __all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup', | 24 __all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup', |
| 23 'TemplateRuntimeError', 'missing', 'concat', 'escape', | 25 'TemplateRuntimeError', 'missing', 'concat', 'escape', |
| 24 'markup_join', 'unicode_join', 'to_string', 'identity', | 26 'markup_join', 'unicode_join', 'to_string', 'identity', |
| 25 'TemplateNotFound'] | 27 'TemplateNotFound', 'make_logging_undefined'] |
| 26 | 28 |
| 27 #: the name of the function that is used to convert something into | 29 #: the name of the function that is used to convert something into |
| 28 #: a string. We can just use the text type here. | 30 #: a string. We can just use the text type here. |
| 29 to_string = text_type | 31 to_string = text_type |
| 30 | 32 |
| 31 #: the identity function. Useful for certain things in the environment | 33 #: the identity function. Useful for certain things in the environment |
| 32 identity = lambda x: x | 34 identity = lambda x: x |
| 33 | 35 |
| 34 _last_iteration = object() | 36 _last_iteration = object() |
| 35 | 37 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 60 else: | 62 else: |
| 61 parent = dict(globals or (), **vars) | 63 parent = dict(globals or (), **vars) |
| 62 if locals: | 64 if locals: |
| 63 # if the parent is shared a copy should be created because | 65 # if the parent is shared a copy should be created because |
| 64 # we don't want to modify the dict passed | 66 # we don't want to modify the dict passed |
| 65 if shared: | 67 if shared: |
| 66 parent = dict(parent) | 68 parent = dict(parent) |
| 67 for key, value in iteritems(locals): | 69 for key, value in iteritems(locals): |
| 68 if key[:2] == 'l_' and value is not missing: | 70 if key[:2] == 'l_' and value is not missing: |
| 69 parent[key[2:]] = value | 71 parent[key[2:]] = value |
| 70 return Context(environment, parent, template_name, blocks) | 72 return environment.context_class(environment, parent, template_name, |
| 73 blocks) |
| 71 | 74 |
| 72 | 75 |
| 73 class TemplateReference(object): | 76 class TemplateReference(object): |
| 74 """The `self` in templates.""" | 77 """The `self` in templates.""" |
| 75 | 78 |
| 76 def __init__(self, context): | 79 def __init__(self, context): |
| 77 self.__context = context | 80 self.__context = context |
| 78 | 81 |
| 79 def __getitem__(self, name): | 82 def __getitem__(self, name): |
| 80 blocks = self.__context.blocks[name] | 83 blocks = self.__context.blocks[name] |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 return dict(self.parent, **self.vars) | 167 return dict(self.parent, **self.vars) |
| 165 | 168 |
| 166 @internalcode | 169 @internalcode |
| 167 def call(__self, __obj, *args, **kwargs): | 170 def call(__self, __obj, *args, **kwargs): |
| 168 """Call the callable with the arguments and keyword arguments | 171 """Call the callable with the arguments and keyword arguments |
| 169 provided but inject the active context or environment as first | 172 provided but inject the active context or environment as first |
| 170 argument if the callable is a :func:`contextfunction` or | 173 argument if the callable is a :func:`contextfunction` or |
| 171 :func:`environmentfunction`. | 174 :func:`environmentfunction`. |
| 172 """ | 175 """ |
| 173 if __debug__: | 176 if __debug__: |
| 174 __traceback_hide__ = True | 177 __traceback_hide__ = True # noqa |
| 175 | 178 |
| 176 # Allow callable classes to take a context | 179 # Allow callable classes to take a context |
| 177 fn = __obj.__call__ | 180 fn = __obj.__call__ |
| 178 for fn_type in ('contextfunction', | 181 for fn_type in ('contextfunction', |
| 179 'evalcontextfunction', | 182 'evalcontextfunction', |
| 180 'environmentfunction'): | 183 'environmentfunction'): |
| 181 if hasattr(fn, fn_type): | 184 if hasattr(fn, fn_type): |
| 182 __obj = fn | 185 __obj = fn |
| 183 break | 186 break |
| 184 | 187 |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 # the the loop without or with too many arguments. | 335 # the the loop without or with too many arguments. |
| 333 __call__ = loop | 336 __call__ = loop |
| 334 del loop | 337 del loop |
| 335 | 338 |
| 336 @property | 339 @property |
| 337 def length(self): | 340 def length(self): |
| 338 if self._length is None: | 341 if self._length is None: |
| 339 # if was not possible to get the length of the iterator when | 342 # if was not possible to get the length of the iterator when |
| 340 # the loop context was created (ie: iterating over a generator) | 343 # the loop context was created (ie: iterating over a generator) |
| 341 # we have to convert the iterable into a sequence and use the | 344 # we have to convert the iterable into a sequence and use the |
| 342 # length of that. | 345 # length of that + the number of iterations so far. |
| 343 iterable = tuple(self._iterator) | 346 iterable = tuple(self._iterator) |
| 344 self._iterator = iter(iterable) | 347 self._iterator = iter(iterable) |
| 345 self._length = len(iterable) + self.index0 + 1 | 348 iterations_done = self.index0 + 2 |
| 349 self._length = len(iterable) + iterations_done |
| 346 return self._length | 350 return self._length |
| 347 | 351 |
| 348 def __repr__(self): | 352 def __repr__(self): |
| 349 return '<%s %r/%r>' % ( | 353 return '<%s %r/%r>' % ( |
| 350 self.__class__.__name__, | 354 self.__class__.__name__, |
| 351 self.index, | 355 self.index, |
| 352 self.length | 356 self.length |
| 353 ) | 357 ) |
| 354 | 358 |
| 355 | 359 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 def __repr__(self): | 438 def __repr__(self): |
| 435 return '<%s %s>' % ( | 439 return '<%s %s>' % ( |
| 436 self.__class__.__name__, | 440 self.__class__.__name__, |
| 437 self.name is None and 'anonymous' or repr(self.name) | 441 self.name is None and 'anonymous' or repr(self.name) |
| 438 ) | 442 ) |
| 439 | 443 |
| 440 | 444 |
| 441 @implements_to_string | 445 @implements_to_string |
| 442 class Undefined(object): | 446 class Undefined(object): |
| 443 """The default undefined type. This undefined type can be printed and | 447 """The default undefined type. This undefined type can be printed and |
| 444 iterated over, but every other access will raise an :exc:`UndefinedError`: | 448 iterated over, but every other access will raise an :exc:`jinja2.exceptions.
UndefinedError`: |
| 445 | 449 |
| 446 >>> foo = Undefined(name='foo') | 450 >>> foo = Undefined(name='foo') |
| 447 >>> str(foo) | 451 >>> str(foo) |
| 448 '' | 452 '' |
| 449 >>> not foo | 453 >>> not foo |
| 450 True | 454 True |
| 451 >>> foo + 42 | 455 >>> foo + 42 |
| 452 Traceback (most recent call last): | 456 Traceback (most recent call last): |
| 453 ... | 457 ... |
| 454 UndefinedError: 'foo' is undefined | 458 jinja2.exceptions.UndefinedError: 'foo' is undefined |
| 455 """ | 459 """ |
| 456 __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name', | 460 __slots__ = ('_undefined_hint', '_undefined_obj', '_undefined_name', |
| 457 '_undefined_exception') | 461 '_undefined_exception') |
| 458 | 462 |
| 459 def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError): | 463 def __init__(self, hint=None, obj=missing, name=None, exc=UndefinedError): |
| 460 self._undefined_hint = hint | 464 self._undefined_hint = hint |
| 461 self._undefined_obj = obj | 465 self._undefined_obj = obj |
| 462 self._undefined_name = name | 466 self._undefined_name = name |
| 463 self._undefined_exception = exc | 467 self._undefined_exception = exc |
| 464 | 468 |
| 465 @internalcode | 469 @internalcode |
| 466 def _fail_with_undefined_error(self, *args, **kwargs): | 470 def _fail_with_undefined_error(self, *args, **kwargs): |
| 467 """Regular callback function for undefined objects that raises an | 471 """Regular callback function for undefined objects that raises an |
| 468 `UndefinedError` on call. | 472 `jinja2.exceptions.UndefinedError` on call. |
| 469 """ | 473 """ |
| 470 if self._undefined_hint is None: | 474 if self._undefined_hint is None: |
| 471 if self._undefined_obj is missing: | 475 if self._undefined_obj is missing: |
| 472 hint = '%r is undefined' % self._undefined_name | 476 hint = '%r is undefined' % self._undefined_name |
| 473 elif not isinstance(self._undefined_name, string_types): | 477 elif not isinstance(self._undefined_name, string_types): |
| 474 hint = '%s has no element %r' % ( | 478 hint = '%s has no element %r' % ( |
| 475 object_type_repr(self._undefined_obj), | 479 object_type_repr(self._undefined_obj), |
| 476 self._undefined_name | 480 self._undefined_name |
| 477 ) | 481 ) |
| 478 else: | 482 else: |
| 479 hint = '%r has no attribute %r' % ( | 483 hint = '%r has no attribute %r' % ( |
| 480 object_type_repr(self._undefined_obj), | 484 object_type_repr(self._undefined_obj), |
| 481 self._undefined_name | 485 self._undefined_name |
| 482 ) | 486 ) |
| 483 else: | 487 else: |
| 484 hint = self._undefined_hint | 488 hint = self._undefined_hint |
| 485 raise self._undefined_exception(hint) | 489 raise self._undefined_exception(hint) |
| 486 | 490 |
| 487 @internalcode | 491 @internalcode |
| 488 def __getattr__(self, name): | 492 def __getattr__(self, name): |
| 489 if name[:2] == '__': | 493 if name[:2] == '__': |
| 490 raise AttributeError(name) | 494 raise AttributeError(name) |
| 491 return self._fail_with_undefined_error() | 495 return self._fail_with_undefined_error() |
| 492 | 496 |
| 493 __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \ | 497 __add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \ |
| 494 __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \ | 498 __truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \ |
| 495 __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \ | 499 __mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \ |
| 496 __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \ | 500 __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \ |
| 497 __float__ = __complex__ = __pow__ = __rpow__ = \ | 501 __float__ = __complex__ = __pow__ = __rpow__ = \ |
| 498 _fail_with_undefined_error | 502 _fail_with_undefined_error |
| 499 | 503 |
| 500 def __eq__(self, other): | 504 def __eq__(self, other): |
| 501 return type(self) is type(other) | 505 return type(self) is type(other) |
| 502 | 506 |
| 503 def __ne__(self, other): | 507 def __ne__(self, other): |
| 504 return not self.__eq__(other) | 508 return not self.__eq__(other) |
| 505 | 509 |
| 506 def __hash__(self): | 510 def __hash__(self): |
| 507 return id(type(self)) | 511 return id(type(self)) |
| 508 | 512 |
| 509 def __str__(self): | 513 def __str__(self): |
| 510 return u'' | 514 return u'' |
| 511 | 515 |
| 512 def __len__(self): | 516 def __len__(self): |
| 513 return 0 | 517 return 0 |
| 514 | 518 |
| 515 def __iter__(self): | 519 def __iter__(self): |
| 516 if 0: | 520 if 0: |
| 517 yield None | 521 yield None |
| 518 | 522 |
| 519 def __nonzero__(self): | 523 def __nonzero__(self): |
| 520 return False | 524 return False |
| 525 __bool__ = __nonzero__ |
| 521 | 526 |
| 522 def __repr__(self): | 527 def __repr__(self): |
| 523 return 'Undefined' | 528 return 'Undefined' |
| 524 | 529 |
| 525 | 530 |
| 531 def make_logging_undefined(logger=None, base=None): |
| 532 """Given a logger object this returns a new undefined class that will |
| 533 log certain failures. It will log iterations and printing. If no |
| 534 logger is given a default logger is created. |
| 535 |
| 536 Example:: |
| 537 |
| 538 logger = logging.getLogger(__name__) |
| 539 LoggingUndefined = make_logging_undefined( |
| 540 logger=logger, |
| 541 base=Undefined |
| 542 ) |
| 543 |
| 544 .. versionadded:: 2.8 |
| 545 |
| 546 :param logger: the logger to use. If not provided, a default logger |
| 547 is created. |
| 548 :param base: the base class to add logging functionality to. This |
| 549 defaults to :class:`Undefined`. |
| 550 """ |
| 551 if logger is None: |
| 552 import logging |
| 553 logger = logging.getLogger(__name__) |
| 554 logger.addHandler(logging.StreamHandler(sys.stderr)) |
| 555 if base is None: |
| 556 base = Undefined |
| 557 |
| 558 def _log_message(undef): |
| 559 if undef._undefined_hint is None: |
| 560 if undef._undefined_obj is missing: |
| 561 hint = '%s is undefined' % undef._undefined_name |
| 562 elif not isinstance(undef._undefined_name, string_types): |
| 563 hint = '%s has no element %s' % ( |
| 564 object_type_repr(undef._undefined_obj), |
| 565 undef._undefined_name) |
| 566 else: |
| 567 hint = '%s has no attribute %s' % ( |
| 568 object_type_repr(undef._undefined_obj), |
| 569 undef._undefined_name) |
| 570 else: |
| 571 hint = undef._undefined_hint |
| 572 logger.warning('Template variable warning: %s', hint) |
| 573 |
| 574 class LoggingUndefined(base): |
| 575 |
| 576 def _fail_with_undefined_error(self, *args, **kwargs): |
| 577 try: |
| 578 return base._fail_with_undefined_error(self, *args, **kwargs) |
| 579 except self._undefined_exception as e: |
| 580 logger.error('Template variable error: %s', str(e)) |
| 581 raise e |
| 582 |
| 583 def __str__(self): |
| 584 rv = base.__str__(self) |
| 585 _log_message(self) |
| 586 return rv |
| 587 |
| 588 def __iter__(self): |
| 589 rv = base.__iter__(self) |
| 590 _log_message(self) |
| 591 return rv |
| 592 |
| 593 if PY2: |
| 594 def __nonzero__(self): |
| 595 rv = base.__nonzero__(self) |
| 596 _log_message(self) |
| 597 return rv |
| 598 |
| 599 def __unicode__(self): |
| 600 rv = base.__unicode__(self) |
| 601 _log_message(self) |
| 602 return rv |
| 603 else: |
| 604 def __bool__(self): |
| 605 rv = base.__bool__(self) |
| 606 _log_message(self) |
| 607 return rv |
| 608 |
| 609 return LoggingUndefined |
| 610 |
| 611 |
| 526 @implements_to_string | 612 @implements_to_string |
| 527 class DebugUndefined(Undefined): | 613 class DebugUndefined(Undefined): |
| 528 """An undefined that returns the debug info when printed. | 614 """An undefined that returns the debug info when printed. |
| 529 | 615 |
| 530 >>> foo = DebugUndefined(name='foo') | 616 >>> foo = DebugUndefined(name='foo') |
| 531 >>> str(foo) | 617 >>> str(foo) |
| 532 '{{ foo }}' | 618 '{{ foo }}' |
| 533 >>> not foo | 619 >>> not foo |
| 534 True | 620 True |
| 535 >>> foo + 42 | 621 >>> foo + 42 |
| 536 Traceback (most recent call last): | 622 Traceback (most recent call last): |
| 537 ... | 623 ... |
| 538 UndefinedError: 'foo' is undefined | 624 jinja2.exceptions.UndefinedError: 'foo' is undefined |
| 539 """ | 625 """ |
| 540 __slots__ = () | 626 __slots__ = () |
| 541 | 627 |
| 542 def __str__(self): | 628 def __str__(self): |
| 543 if self._undefined_hint is None: | 629 if self._undefined_hint is None: |
| 544 if self._undefined_obj is missing: | 630 if self._undefined_obj is missing: |
| 545 return u'{{ %s }}' % self._undefined_name | 631 return u'{{ %s }}' % self._undefined_name |
| 546 return '{{ no such element: %s[%r] }}' % ( | 632 return '{{ no such element: %s[%r] }}' % ( |
| 547 object_type_repr(self._undefined_obj), | 633 object_type_repr(self._undefined_obj), |
| 548 self._undefined_name | 634 self._undefined_name |
| 549 ) | 635 ) |
| 550 return u'{{ undefined value printed: %s }}' % self._undefined_hint | 636 return u'{{ undefined value printed: %s }}' % self._undefined_hint |
| 551 | 637 |
| 552 | 638 |
| 553 @implements_to_string | 639 @implements_to_string |
| 554 class StrictUndefined(Undefined): | 640 class StrictUndefined(Undefined): |
| 555 """An undefined that barks on print and iteration as well as boolean | 641 """An undefined that barks on print and iteration as well as boolean |
| 556 tests and all kinds of comparisons. In other words: you can do nothing | 642 tests and all kinds of comparisons. In other words: you can do nothing |
| 557 with it except checking if it's defined using the `defined` test. | 643 with it except checking if it's defined using the `defined` test. |
| 558 | 644 |
| 559 >>> foo = StrictUndefined(name='foo') | 645 >>> foo = StrictUndefined(name='foo') |
| 560 >>> str(foo) | 646 >>> str(foo) |
| 561 Traceback (most recent call last): | 647 Traceback (most recent call last): |
| 562 ... | 648 ... |
| 563 UndefinedError: 'foo' is undefined | 649 jinja2.exceptions.UndefinedError: 'foo' is undefined |
| 564 >>> not foo | 650 >>> not foo |
| 565 Traceback (most recent call last): | 651 Traceback (most recent call last): |
| 566 ... | 652 ... |
| 567 UndefinedError: 'foo' is undefined | 653 jinja2.exceptions.UndefinedError: 'foo' is undefined |
| 568 >>> foo + 42 | 654 >>> foo + 42 |
| 569 Traceback (most recent call last): | 655 Traceback (most recent call last): |
| 570 ... | 656 ... |
| 571 UndefinedError: 'foo' is undefined | 657 jinja2.exceptions.UndefinedError: 'foo' is undefined |
| 572 """ | 658 """ |
| 573 __slots__ = () | 659 __slots__ = () |
| 574 __iter__ = __str__ = __len__ = __nonzero__ = __eq__ = \ | 660 __iter__ = __str__ = __len__ = __nonzero__ = __eq__ = \ |
| 575 __ne__ = __bool__ = __hash__ = \ | 661 __ne__ = __bool__ = __hash__ = \ |
| 576 Undefined._fail_with_undefined_error | 662 Undefined._fail_with_undefined_error |
| 577 | 663 |
| 578 | 664 |
| 579 # remove remaining slots attributes, after the metaclass did the magic they | 665 # remove remaining slots attributes, after the metaclass did the magic they |
| 580 # are unneeded and irritating as they contain wrong data for the subclasses. | 666 # are unneeded and irritating as they contain wrong data for the subclasses. |
| 581 del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__ | 667 del Undefined.__slots__, DebugUndefined.__slots__, StrictUndefined.__slots__ |
| OLD | NEW |