Mercurial > genshi > genshi-test
changeset 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 | 0619a27f5e67 |
children | 5b422db07359 |
files | markup/template.py markup/tests/template.py |
diffstat | 2 files changed, 27 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/markup/template.py +++ b/markup/template.py @@ -915,7 +915,7 @@ ctxt = Context(**kwargs) stream = self.stream - for filter_ in [self._eval, self._match, self._flatten] + self.filters: + for filter_ in [self._flatten, self._eval, self._match] + self.filters: stream = filter_(iter(stream), ctxt) return Stream(stream) @@ -923,7 +923,7 @@ """Internal stream filter that evaluates any expressions in `START` and `TEXT` events. """ - filters = (self._eval, self._match, self._flatten) + filters = (self._flatten, self._eval) for kind, data, pos in stream: @@ -983,9 +983,7 @@ # events to which those directives should be applied directives, substream = data substream = _apply_directives(substream, ctxt, directives) - for filter_ in (self._eval, self._match, self._flatten): - substream = filter_(substream, ctxt) - for event in substream: + for event in self._flatten(substream, ctxt): yield event else: yield kind, data, pos @@ -1009,10 +1007,17 @@ enumerate(match_templates): if test(kind, data, pos, ctxt) is True: + + # Let the remaining match templates know about the event so + # they get a chance to update their internal state + for test in [mt[0] for mt in match_templates[idx + 1:]]: + test(kind, data, pos, ctxt) + # Consume and store all events until an end event # corresponding to this start event is encountered content = [(kind, data, pos)] depth = 1 + stream = self._match(stream, ctxt) while depth > 0: kind, data, pos = stream.next() if kind is START: @@ -1020,12 +1025,14 @@ elif kind is END: depth -= 1 content.append((kind, data, pos)) - test(kind, data, pos, ctxt) - content = list(self._flatten(content, ctxt)) - select = lambda path: Stream(content).select(path) + # Make the select() function available in the body of the + # match template + def select(path): + return Stream(content).select(path) ctxt.push(dict(select=select)) + # Recursively process the output template = _apply_directives(template, ctxt, directives) for event in self._match(self._eval(template, ctxt), ctxt, match_templates[:idx] +
--- a/markup/tests/template.py +++ b/markup/tests/template.py @@ -330,6 +330,18 @@ </html>""") self.assertRaises(TypeError, list, tmpl.generate(badfunc=badfunc)) + def test_def_in_matched(self): + tmpl = Template("""<doc xmlns:py="http://markup.edgewall.org/"> + <head py:match="head">${select('*')}</head> + <head> + <py:def function="maketitle(test)"><b py:replace="test" /></py:def> + <title>${maketitle(True)}</title> + </head> + </doc>""") + self.assertEqual("""<doc> + <head><title>True</title></head> + </doc>""", str(tmpl.generate())) + class ForDirectiveTestCase(unittest.TestCase): """Tests for the `py:for` template directive."""