Mercurial > genshi > genshi-test
comparison markup/template.py @ 208:835203f3b8fd
Cleanup the application of template processing steps (flatten, eval, match) so that they are only performed when necessary. Results in a small performance boost, and also fixes #35.
author | cmlenz |
---|---|
date | Tue, 29 Aug 2006 15:44:54 +0000 |
parents | d122ff386411 |
children | c0c70dc5bf95 |
comparison
equal
deleted
inserted
replaced
207:0619a27f5e67 | 208:835203f3b8fd |
---|---|
913 assert isinstance(ctxt, Context) | 913 assert isinstance(ctxt, Context) |
914 else: | 914 else: |
915 ctxt = Context(**kwargs) | 915 ctxt = Context(**kwargs) |
916 | 916 |
917 stream = self.stream | 917 stream = self.stream |
918 for filter_ in [self._eval, self._match, self._flatten] + self.filters: | 918 for filter_ in [self._flatten, self._eval, self._match] + self.filters: |
919 stream = filter_(iter(stream), ctxt) | 919 stream = filter_(iter(stream), ctxt) |
920 return Stream(stream) | 920 return Stream(stream) |
921 | 921 |
922 def _eval(self, stream, ctxt=None): | 922 def _eval(self, stream, ctxt=None): |
923 """Internal stream filter that evaluates any expressions in `START` and | 923 """Internal stream filter that evaluates any expressions in `START` and |
924 `TEXT` events. | 924 `TEXT` events. |
925 """ | 925 """ |
926 filters = (self._eval, self._match, self._flatten) | 926 filters = (self._flatten, self._eval) |
927 | 927 |
928 for kind, data, pos in stream: | 928 for kind, data, pos in stream: |
929 | 929 |
930 if kind is START and data[1]: | 930 if kind is START and data[1]: |
931 # Attributes may still contain expressions in start tags at | 931 # Attributes may still contain expressions in start tags at |
981 if kind is SUB: | 981 if kind is SUB: |
982 # This event is a list of directives and a list of nested | 982 # This event is a list of directives and a list of nested |
983 # events to which those directives should be applied | 983 # events to which those directives should be applied |
984 directives, substream = data | 984 directives, substream = data |
985 substream = _apply_directives(substream, ctxt, directives) | 985 substream = _apply_directives(substream, ctxt, directives) |
986 for filter_ in (self._eval, self._match, self._flatten): | 986 for event in self._flatten(substream, ctxt): |
987 substream = filter_(substream, ctxt) | |
988 for event in substream: | |
989 yield event | 987 yield event |
990 else: | 988 else: |
991 yield kind, data, pos | 989 yield kind, data, pos |
992 | 990 |
993 def _match(self, stream, ctxt=None, match_templates=None): | 991 def _match(self, stream, ctxt=None, match_templates=None): |
1007 | 1005 |
1008 for idx, (test, path, template, directives) in \ | 1006 for idx, (test, path, template, directives) in \ |
1009 enumerate(match_templates): | 1007 enumerate(match_templates): |
1010 | 1008 |
1011 if test(kind, data, pos, ctxt) is True: | 1009 if test(kind, data, pos, ctxt) is True: |
1010 | |
1011 # Let the remaining match templates know about the event so | |
1012 # they get a chance to update their internal state | |
1013 for test in [mt[0] for mt in match_templates[idx + 1:]]: | |
1014 test(kind, data, pos, ctxt) | |
1015 | |
1012 # Consume and store all events until an end event | 1016 # Consume and store all events until an end event |
1013 # corresponding to this start event is encountered | 1017 # corresponding to this start event is encountered |
1014 content = [(kind, data, pos)] | 1018 content = [(kind, data, pos)] |
1015 depth = 1 | 1019 depth = 1 |
1020 stream = self._match(stream, ctxt) | |
1016 while depth > 0: | 1021 while depth > 0: |
1017 kind, data, pos = stream.next() | 1022 kind, data, pos = stream.next() |
1018 if kind is START: | 1023 if kind is START: |
1019 depth += 1 | 1024 depth += 1 |
1020 elif kind is END: | 1025 elif kind is END: |
1021 depth -= 1 | 1026 depth -= 1 |
1022 content.append((kind, data, pos)) | 1027 content.append((kind, data, pos)) |
1023 test(kind, data, pos, ctxt) | 1028 |
1024 | 1029 # Make the select() function available in the body of the |
1025 content = list(self._flatten(content, ctxt)) | 1030 # match template |
1026 select = lambda path: Stream(content).select(path) | 1031 def select(path): |
1032 return Stream(content).select(path) | |
1027 ctxt.push(dict(select=select)) | 1033 ctxt.push(dict(select=select)) |
1028 | 1034 |
1035 # Recursively process the output | |
1029 template = _apply_directives(template, ctxt, directives) | 1036 template = _apply_directives(template, ctxt, directives) |
1030 for event in self._match(self._eval(template, ctxt), | 1037 for event in self._match(self._eval(template, ctxt), |
1031 ctxt, match_templates[:idx] + | 1038 ctxt, match_templates[:idx] + |
1032 match_templates[idx + 1:]): | 1039 match_templates[idx + 1:]): |
1033 yield event | 1040 yield event |