# HG changeset patch # User cmlenz # Date 1187871777 0 # Node ID 6d1fa718794fc00a70182fce7e2261b8484ca596 # Parent ab167005a363dc94fd0c8a5f01edd68917f3d4aa Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied. diff --git a/genshi/template/directives.py b/genshi/template/directives.py --- a/genshi/template/directives.py +++ b/genshi/template/directives.py @@ -23,7 +23,8 @@ from genshi.path import Path from genshi.template.base import TemplateRuntimeError, TemplateSyntaxError, \ EXPR, _apply_directives -from genshi.template.eval import Expression, Suite, _parse +from genshi.template.eval import Expression, Suite, ExpressionASTTransformer, \ + _parse __all__ = ['AttrsDirective', 'ChooseDirective', 'ContentDirective', 'DefDirective', 'ForDirective', 'IfDirective', 'MatchDirective', @@ -697,7 +698,8 @@ Directive.__init__(self, None, template, namespaces, lineno, offset) try: self.suite = Suite(value, template.filepath, lineno, - lookup=template.lookup) + lookup=template.lookup, + xform=ExpressionASTTransformer) except SyntaxError, err: err.msg += ' in expression "%s" of "%s" directive' % (value, self.tagname) diff --git a/genshi/template/eval.py b/genshi/template/eval.py --- a/genshi/template/eval.py +++ b/genshi/template/eval.py @@ -38,7 +38,8 @@ """Abstract base class for the `Expression` and `Suite` classes.""" __slots__ = ['source', 'code', 'ast', '_globals'] - def __init__(self, source, filename=None, lineno=-1, lookup='lenient'): + def __init__(self, source, filename=None, lineno=-1, lookup='lenient', + xform=None): """Create the code object, either from a string, or from an AST node. :param source: either a string containing the source code, or an AST @@ -49,6 +50,9 @@ :param lookup: the lookup class that defines how variables are looked up in the context. Can be either `LenientLookup` (the default), `StrictLookup`, or a custom lookup class + :param xform: the AST transformer that should be applied to the code; + if `None`, the appropriate transformation is chosen + depending on the mode """ if isinstance(source, basestring): self.source = source @@ -64,7 +68,7 @@ self.ast = node self.code = _compile(node, self.source, mode=self.mode, - filename=filename, lineno=lineno) + filename=filename, lineno=lineno, xform=xform) if lookup is None: lookup = LenientLookup elif isinstance(lookup, basestring): @@ -374,8 +378,11 @@ source = '\xef\xbb\xbf' + source.encode('utf-8') return parse(source, mode) -def _compile(node, source=None, mode='eval', filename=None, lineno=-1): - xform = {'eval': ExpressionASTTransformer}.get(mode, TemplateASTTransformer) +def _compile(node, source=None, mode='eval', filename=None, lineno=-1, + xform=None): + if xform is None: + xform = {'eval': ExpressionASTTransformer}.get(mode, + TemplateASTTransformer) tree = xform().visit(node) if isinstance(filename, unicode): # unicode file names not allowed for code objects diff --git a/genshi/template/tests/directives.py b/genshi/template/tests/directives.py --- a/genshi/template/tests/directives.py +++ b/genshi/template/tests/directives.py @@ -1016,6 +1016,22 @@ here are two semicolons: ;; """, str(tmpl.generate())) + def test_ast_transformation(self): + """ + Verify that the usual template expression AST transformations are + applied despite the code being compiled to a `Suite` object. + """ + tmpl = MarkupTemplate("""
+ + $bar + +
""") + self.assertEqual("""
+ + 42 + +
""", str(tmpl.generate(foo={'bar': 42}))) + def test_unicode_expr(self): tmpl = MarkupTemplate("""