changeset 165:54a4be707664 trunk

Fix handling of keyword arguments in `py:def` directive. Thanks to Christian Boos for reporting the problem and providing the basic patch for this change.
author cmlenz
date Thu, 17 Aug 2006 14:02:58 +0000
parents 1f6cb675a66c
children d43f50402cf2
files markup/eval.py markup/template.py markup/tests/template.py
diffstat 3 files changed, 33 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/markup/eval.py
+++ b/markup/eval.py
@@ -65,12 +65,15 @@
     __slots__ = ['source', 'code']
 
     def __init__(self, source, filename=None, lineno=-1):
-        """Create the expression.
-        
-        @param source: the expression as string
-        """
-        self.source = source
-        self.code = _compile(self, filename, lineno)
+        if isinstance(source, basestring):
+            self.source = source
+            self.code = _compile(parse(source, 'eval'), source,
+                                 filename=filename, lineno=lineno)
+        else:
+            assert isinstance(source, ast.Node)
+            self.source = '?'
+            self.code = _compile(ast.Expression(source), filename=filename,
+                                 lineno=lineno)
 
     def __repr__(self):
         return '<Expression "%s">' % self.source
@@ -92,8 +95,8 @@
         return retval
 
 
-def _compile(expr, filename=None, lineno=-1):
-    tree = ExpressionASTTransformer().visit(parse(expr.source, 'eval'))
+def _compile(node, source=None, filename=None, lineno=-1):
+    tree = ExpressionASTTransformer().visit(node)
     if isinstance(filename, unicode):
         # unicode file names not allowed for code objects
         filename = filename.encode('utf-8', 'replace')
@@ -111,8 +114,9 @@
     # clone the code object while adjusting the line number
     return new.code(0, code.co_nlocals, code.co_stacksize,
                     code.co_flags | 0x0040, code.co_code, code.co_consts,
-                    code.co_names, code.co_varnames, filename, repr(expr),
-                    lineno, code.co_lnotab, (), ())
+                    code.co_names, code.co_varnames, filename,
+                    '<Expression "%s">' % (str(source) or '?'), lineno,
+                    code.co_lnotab, (), ())
 
 def _lookup_name(data, name, locals_=None):
     val = None
--- a/markup/template.py
+++ b/markup/template.py
@@ -306,7 +306,8 @@
             for arg in ast.args:
                 if isinstance(arg, compiler.ast.Keyword):
                     self.args.append(arg.name)
-                    self.defaults[arg.name] = arg.expr.value
+                    self.defaults[arg.name] = Expression(arg.expr, filename,
+                                                         lineno)
                 else:
                     self.args.append(arg.name)
         else:
@@ -322,7 +323,11 @@
                 if args:
                     scope[name] = args.pop(0)
                 else:
-                    scope[name] = kwargs.pop(name, self.defaults.get(name))
+                    if name in kwargs:
+                        val = kwargs.pop(name)
+                    else:
+                        val = self.defaults.get(name).evaluate(ctxt)
+                    scope[name] = val
             ctxt.push(scope)
             for event in _apply_directives(stream, ctxt, directives):
                 yield event
--- a/markup/tests/template.py
+++ b/markup/tests/template.py
@@ -203,6 +203,18 @@
           <strong>foo</strong>
         </doc>""", str(tmpl.generate(semantic=True)))
 
+    def test_function_with_default_arg(self):
+        """
+        Verify that keyword arguments work with `py:def` directives.
+        """
+        tmpl = Template("""<doc xmlns:py="http://markup.edgewall.org/">
+          <b py:def="echo(what, bold=False)" py:strip="not bold">${what}</b>
+          ${echo('foo')}
+        </doc>""")
+        self.assertEqual("""<doc>
+          foo
+        </doc>""", str(tmpl.generate()))
+
 
 class ForDirectiveTestCase(unittest.TestCase):
     """Tests for the `py:for` template directive."""
Copyright (C) 2012-2017 Edgewall Software