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 |