# HG changeset patch # User cmlenz # Date 1215448506 0 # Node ID b4c973fbe6f5b139e952050d349c503f3a0363d9 # Parent 834e8fd2d822a92d07c67eec9bcfe1977890b784 Unbuffered match templates could result in parts of the matched content being included in the output if the match template didn't actually consume it via one or more calls to the `select()` function. Closes #243. Thanks to Felix Schwarz for the report and test case. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -20,6 +20,9 @@ * Includes from templates loaded via an absolute path now include the correct file in nested directories as long if no search path has been configured (ticket #240). + * Unbuffered match templates could result in parts of the matched content + being included in the output if the match template didn't actually consume + it via one or more calls to the `select()` function (ticket #243). Version 0.5 diff --git a/genshi/template/markup.py b/genshi/template/markup.py --- a/genshi/template/markup.py +++ b/genshi/template/markup.py @@ -278,13 +278,11 @@ if 'not_buffered' not in hints: content = list(content) - if tail: - for test in [mt[0] for mt in match_templates]: - test(tail[0], namespaces, ctxt, updateonly=True) - # Make the select() function available in the body of the # match template + selected = [False] def select(path): + selected[0] = True return Stream(content).select(path, namespaces, ctxt) vars = dict(select=select) @@ -300,6 +298,19 @@ ctxt, start=idx + 1, **vars): yield event + # If the match template did not actually call select to + # consume the matched stream, the original events need to + # be consumed here or they'll get appended to the output + if not selected[0]: + for event in content: + pass + + # Let the remaining match templates know about the last + # event in the matched content, so they can update their + # internal state accordingly + for test in [mt[0] for mt in match_templates]: + test(tail[0], namespaces, ctxt, updateonly=True) + break else: # no matches diff --git a/genshi/template/plugin.py b/genshi/template/plugin.py --- a/genshi/template/plugin.py +++ b/genshi/template/plugin.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2006-2007 Edgewall Software +# Copyright (C) 2006-2008 Edgewall Software # Copyright (C) 2006 Matthew Good # All rights reserved. # diff --git a/genshi/template/tests/markup.py b/genshi/template/tests/markup.py --- a/genshi/template/tests/markup.py +++ b/genshi/template/tests/markup.py @@ -708,6 +708,25 @@ """, tmpl.generate().render()) + def test_match_without_select(self): + # See + xml = (""" + + + This replaces the other text. + + + + This gets replaced. + + """) + tmpl = MarkupTemplate(xml, filename='test.html') + self.assertEqual(""" + + This replaces the other text. + + """, tmpl.generate().render()) + def suite(): suite = unittest.TestSuite()