comparison markup/template.py @ 202:4140bff0d7d2

Remove the (hopefully) last instance where directives store state in instance variables, allowing templates to be cached and reused in a threadsafe manner. Closes #39. Many thanks to Christian Boos for the patch!
author cmlenz
date Fri, 25 Aug 2006 12:43:01 +0000
parents 58284b6b0009
children 56f5e93edc48
comparison
equal deleted inserted replaced
201:0f16c907077e 202:4140bff0d7d2
108 return repr(self.frames) 108 return repr(self.frames)
109 109
110 def __setitem__(self, key, value): 110 def __setitem__(self, key, value):
111 """Set a variable in the current scope.""" 111 """Set a variable in the current scope."""
112 self.frames[0][key] = value 112 self.frames[0][key] = value
113
114 def _find(self, key, default=None):
115 """Retrieve a given variable's value and frame it was found in.
116
117 Intented for internal use by directives.
118 """
119 for frame in self.frames:
120 if key in frame:
121 return frame[key], frame
122 return default, None
113 123
114 def get(self, key, default=None): 124 def get(self, key, default=None):
115 """Get a variable's value, starting at the current scope and going 125 """Get a variable's value, starting at the current scope and going
116 upward. 126 upward.
117 """ 127 """
584 __slots__ = ['matched', 'value'] 594 __slots__ = ['matched', 'value']
585 595
586 ATTRIBUTE = 'test' 596 ATTRIBUTE = 'test'
587 597
588 def __call__(self, stream, ctxt, directives): 598 def __call__(self, stream, ctxt, directives):
599 frame = dict({'_choose.matched': False})
589 if self.expr: 600 if self.expr:
590 self.value = self.expr.evaluate(ctxt) 601 frame['_choose.value'] = self.expr.evaluate(ctxt)
591 self.matched = False 602 ctxt.push(frame)
592 ctxt.push(dict(_choose=self))
593 for event in _apply_directives(stream, ctxt, directives): 603 for event in _apply_directives(stream, ctxt, directives):
594 yield event 604 yield event
595 ctxt.pop() 605 ctxt.pop()
596 606
597 607
603 """ 613 """
604 614
605 ATTRIBUTE = 'test' 615 ATTRIBUTE = 'test'
606 616
607 def __call__(self, stream, ctxt, directives): 617 def __call__(self, stream, ctxt, directives):
608 choose = ctxt['_choose'] 618 matched, frame = ctxt._find('_choose.matched')
609 if not choose: 619 if not frame:
610 raise TemplateSyntaxError('"when" directives can only be used ' 620 raise TemplateSyntaxError('"when" directives can only be used '
611 'inside a "choose" directive', 621 'inside a "choose" directive',
612 *stream.next()[2]) 622 *stream.next()[2])
613 if choose.matched: 623 if matched:
614 return [] 624 return []
615 if not self.expr: 625 if not self.expr:
616 raise TemplateSyntaxError('"when" directive has no test condition', 626 raise TemplateSyntaxError('"when" directive has no test condition',
617 *stream.next()[2]) 627 *stream.next()[2])
618 value = self.expr.evaluate(ctxt) 628 value = self.expr.evaluate(ctxt)
619 try: 629 if '_choose.value' in frame:
620 if value == choose.value: 630 matched = (value == frame['_choose.value'])
621 choose.matched = True 631 else:
622 return _apply_directives(stream, ctxt, directives) 632 matched = bool(value)
623 except AttributeError: 633 frame['_choose.matched'] = matched
624 if value: 634 if not matched:
625 choose.matched = True 635 return []
626 return _apply_directives(stream, ctxt, directives) 636
627 return [] 637 return _apply_directives(stream, ctxt, directives)
628 638
629 639
630 class OtherwiseDirective(Directive): 640 class OtherwiseDirective(Directive):
631 """Implementation of the `py:otherwise` directive for nesting in a parent 641 """Implementation of the `py:otherwise` directive for nesting in a parent
632 with the `py:choose` directive. 642 with the `py:choose` directive.
633 643
634 See the documentation of `py:choose` for usage. 644 See the documentation of `py:choose` for usage.
635 """ 645 """
636 def __call__(self, stream, ctxt, directives): 646 def __call__(self, stream, ctxt, directives):
637 choose = ctxt['_choose'] 647 matched, frame = ctxt._find('_choose.matched')
638 if not choose: 648 if not frame:
639 raise TemplateSyntaxError('an "otherwise" directive can only be ' 649 raise TemplateSyntaxError('an "otherwise" directive can only be '
640 'used inside a "choose" directive', 650 'used inside a "choose" directive',
641 *stream.next()[2]) 651 *stream.next()[2])
642 if choose.matched: 652 if matched:
643 return [] 653 return []
644 choose.matched = True 654 frame['_choose.matched'] = True
655
645 return _apply_directives(stream, ctxt, directives) 656 return _apply_directives(stream, ctxt, directives)
646 657
647 658
648 class WithDirective(Directive): 659 class WithDirective(Directive):
649 """Implementation of the `py:with` template directive, which allows 660 """Implementation of the `py:with` template directive, which allows
Copyright (C) 2012-2017 Edgewall Software