changeset 604:6d1fa718794f

Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied.
author cmlenz
date Thu, 23 Aug 2007 12:22:57 +0000
parents ab167005a363
children bc5faca93699
files genshi/template/directives.py genshi/template/eval.py genshi/template/tests/directives.py
diffstat 3 files changed, 31 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- 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)
--- 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
--- a/genshi/template/tests/directives.py
+++ b/genshi/template/tests/directives.py
@@ -1016,6 +1016,22 @@
             here are two semicolons: ;;
         </div>""", 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("""<div xmlns:py="http://genshi.edgewall.org/">
+          <span py:with="bar=foo.bar">
+            $bar
+          </span>
+        </div>""")
+        self.assertEqual("""<div>
+          <span>
+            42
+          </span>
+        </div>""", str(tmpl.generate(foo={'bar': 42})))
+
     def test_unicode_expr(self):
         tmpl = MarkupTemplate("""<div xmlns:py="http://genshi.edgewall.org/">
           <span py:with="weeks=(u'一', u'二', u'三', u'四', u'五', u'六', u'日')">
Copyright (C) 2012-2017 Edgewall Software