Mercurial > genshi > mirror
changeset 154:8bd5c8cd33e0 trunk
* Make sure `py:def` macros don't go out of scope if they are defined inside another directive.
* Cleaned up the `DefDirective` implementation a bit.
author | cmlenz |
---|---|
date | Wed, 16 Aug 2006 14:04:30 +0000 |
parents | fc2ff46d1ae3 |
children | 9a5aedda1099 |
files | markup/template.py markup/tests/template.py |
diffstat | 2 files changed, 43 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/markup/template.py +++ b/markup/template.py @@ -290,7 +290,7 @@ </p> </div> """ - __slots__ = ['name', 'args', 'defaults', 'stream', 'directives'] + __slots__ = ['name', 'args', 'defaults'] ATTRIBUTE = 'function' @@ -309,27 +309,33 @@ self.args.append(arg.name) else: self.name = ast.name - self.stream, self.directives = [], [] def __call__(self, stream, ctxt, directives): - self.stream = list(stream) - self.directives = directives - ctxt[self.name] = lambda *args, **kwargs: self._exec(ctxt, *args, - **kwargs) - return [] + stream = list(stream) - def _exec(self, ctxt, *args, **kwargs): - scope = {} - args = list(args) # make mutable - for name in self.args: - if args: - scope[name] = args.pop(0) - else: - scope[name] = kwargs.pop(name, self.defaults.get(name)) - ctxt.push(scope) - for event in _apply_directives(self.stream, ctxt, self.directives): - yield event - ctxt.pop() + def function(*args, **kwargs): + scope = {} + args = list(args) # make mutable + for name in self.args: + if args: + scope[name] = args.pop(0) + else: + scope[name] = kwargs.pop(name, self.defaults.get(name)) + ctxt.push(scope) + for event in _apply_directives(stream, ctxt, directives): + yield event + ctxt.pop() + try: + function.__name__ = self.name + except TypeError: + # Function name can't be set in Python 2.3 + pass + + # Store the function reference in the bottom context frame so that it + # doesn't get popped off before processing the template has finished + ctxt.frames[-1][self.name] = function + + return [] class ForDirective(Directive):
--- a/markup/tests/template.py +++ b/markup/tests/template.py @@ -185,6 +185,24 @@ <b>foo</b> </doc>""", str(tmpl.generate())) + def test_nested_defs(self): + """ + Verify that a template function defined inside a conditional block can + be called from outside that block. + """ + tmpl = Template("""<doc xmlns:py="http://markup.edgewall.org/"> + <py:if test="semantic"> + <strong py:def="echo(what)">${what}</strong> + </py:if> + <py:if test="not semantic"> + <b py:def="echo(what)">${what}</b> + </py:if> + ${echo('foo')} + </doc>""") + self.assertEqual("""<doc> + <strong>foo</strong> + </doc>""", str(tmpl.generate(semantic=True))) + class ForDirectiveTestCase(unittest.TestCase): """Tests for the `py:for` template directive."""