Mercurial > genshi > mirror
comparison markup/template.py @ 23:d88358f719fa trunk
Separate match and eval filters from the include and user-supplied filters.
author | cmlenz |
---|---|
date | Tue, 20 Jun 2006 17:31:32 +0000 |
parents | 2483fe549959 |
children | b4f78c05e5c9 |
comparison
equal
deleted
inserted
replaced
22:2483fe549959 | 23:d88358f719fa |
---|---|
585 if basedir and filename: | 585 if basedir and filename: |
586 self.filepath = os.path.join(basedir, filename) | 586 self.filepath = os.path.join(basedir, filename) |
587 else: | 587 else: |
588 self.filepath = '<string>' | 588 self.filepath = '<string>' |
589 | 589 |
590 self.filters = [self._eval, self._match] | 590 self.filters = [] |
591 self.parse() | 591 self.parse() |
592 | 592 |
593 def __repr__(self): | 593 def __repr__(self): |
594 return '<%s "%s">' % (self.__class__.__name__, self.filename) | 594 return '<%s "%s">' % (self.__class__.__name__, self.filename) |
595 | 595 |
690 if patterns: | 690 if patterns: |
691 for result in _interpolate(group): | 691 for result in _interpolate(group): |
692 yield result | 692 yield result |
693 else: | 693 else: |
694 yield Stream.TEXT, group.replace('$$', '$'), \ | 694 yield Stream.TEXT, group.replace('$$', '$'), \ |
695 (lineno, offset) | 695 (filename, lineno, offset) |
696 return _interpolate(text) | 696 return _interpolate(text) |
697 _interpolate = classmethod(_interpolate) | 697 _interpolate = classmethod(_interpolate) |
698 | 698 |
699 def generate(self, ctxt=None): | 699 def generate(self, ctxt=None): |
700 """Transform the template based on the given context data.""" | 700 """Transform the template based on the given context data.""" |
701 if ctxt is None: | 701 if ctxt is None: |
702 ctxt = Context() | 702 ctxt = Context() |
703 if not hasattr(ctxt, '_match_templates'): | 703 if not hasattr(ctxt, '_match_templates'): |
704 ctxt._match_templates = [] | 704 ctxt._match_templates = [] |
705 | 705 |
706 return Stream(self._flatten(self.stream, ctxt)) | 706 stream = self._match(self._eval(self.stream, ctxt), ctxt) |
707 return Stream(self._flatten(stream, ctxt)) | |
707 | 708 |
708 def _eval(self, stream, ctxt=None): | 709 def _eval(self, stream, ctxt=None): |
709 for kind, data, pos in stream: | 710 for kind, data, pos in stream: |
710 | 711 |
711 if kind is Stream.START: | 712 if kind is Stream.START: |
724 else: | 725 else: |
725 values.append(subdata) | 726 values.append(subdata) |
726 value = filter(lambda x: x is not None, values) | 727 value = filter(lambda x: x is not None, values) |
727 if not value: | 728 if not value: |
728 continue | 729 continue |
729 new_attrib.append((name, ''.join(value))) | 730 new_attrib.append((name, u''.join(value))) |
730 yield kind, (tag, Attributes(new_attrib)), pos | 731 yield kind, (tag, Attributes(new_attrib)), pos |
731 | 732 |
732 elif kind is Template.EXPR: | 733 elif kind is Template.EXPR: |
733 result = data.evaluate(ctxt) | 734 result = data.evaluate(ctxt) |
734 if result is None: | 735 if result is None: |
736 | 737 |
737 # First check for a string, otherwise the iterable test below | 738 # First check for a string, otherwise the iterable test below |
738 # succeeds, and the string will be chopped up into individual | 739 # succeeds, and the string will be chopped up into individual |
739 # characters | 740 # characters |
740 if isinstance(result, basestring): | 741 if isinstance(result, basestring): |
741 yield Stream.TEXT, result, pos | 742 yield Stream.TEXT, unicode(result), pos |
742 else: | 743 else: |
743 # Test if the expression evaluated to an iterable, in which | 744 # Test if the expression evaluated to an iterable, in which |
744 # case we yield the individual items | 745 # case we yield the individual items |
745 try: | 746 try: |
746 yield (Template.SUB, ([], iter(result)), pos) | 747 yield (Template.SUB, ([], iter(result)), pos) |
750 yield Stream.TEXT, unicode(result), pos | 751 yield Stream.TEXT, unicode(result), pos |
751 | 752 |
752 else: | 753 else: |
753 yield kind, data, pos | 754 yield kind, data, pos |
754 | 755 |
755 def _flatten(self, stream, ctxt=None, apply_filters=True): | 756 def _flatten(self, stream, ctxt=None): |
756 if apply_filters: | 757 for filter_ in self.filters: |
757 for filter_ in self.filters: | 758 stream = filter_(iter(stream), ctxt) |
758 stream = filter_(iter(stream), ctxt) | |
759 try: | 759 try: |
760 for kind, data, pos in stream: | 760 for kind, data, pos in stream: |
761 if kind is Template.SUB: | 761 if kind is Template.SUB: |
762 # This event is a list of directives and a list of | 762 # This event is a list of directives and a list of |
763 # nested events to which those directives should be | 763 # nested events to which those directives should be |
764 # applied | 764 # applied |
765 directives, substream = data | 765 directives, substream = data |
766 directives.reverse() | 766 directives.reverse() |
767 for directive in directives: | 767 for directive in directives: |
768 substream = directive(iter(substream), ctxt) | 768 substream = directive(iter(substream), ctxt) |
769 substream = self._match(self._eval(substream, ctxt), ctxt) | |
769 for event in self._flatten(substream, ctxt): | 770 for event in self._flatten(substream, ctxt): |
770 yield event | 771 yield event |
771 continue | 772 continue |
772 else: | 773 else: |
773 yield kind, data, pos | 774 yield kind, data, pos |
806 content.append(event) | 807 content.append(event) |
807 | 808 |
808 # enable the path to keep track of the stream state | 809 # enable the path to keep track of the stream state |
809 test(*event) | 810 test(*event) |
810 | 811 |
811 content = list(self._flatten(content, ctxt, False)) | 812 content = list(self._flatten(content, ctxt)) |
812 | 813 |
813 def _apply(stream, ctxt): | 814 def _apply(stream, ctxt): |
814 stream = list(stream) | |
815 ctxt.push(select=lambda path: Stream(stream).select(path)) | 815 ctxt.push(select=lambda path: Stream(stream).select(path)) |
816 for event in template: | 816 for event in template: |
817 yield event | 817 yield event |
818 ctxt.pop() | 818 ctxt.pop() |
819 | 819 |