Mercurial > genshi > genshi-test
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 |