# HG changeset patch
# User cmlenz
# Date 1163152844 0
# Node ID 4ff2338e89cd10208abe055dbe7a112abe40908b
# Parent 6c8b7a1fb50defd6458a79026adbe984334adb56
Remove automatic calling of expression evaluation results if they are callable. See [http://groups.google.com/group/genshi/browse_thread/thread/f515986760918d41 this mailing list thread].
diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -26,6 +26,8 @@
immediate children.
* Split up the `genshi.template` module into multiple modules inside the new
`genshi.template` package.
+ * Results of expression evaluation are no longer implicitly called if they
+ are callable.
Version 0.3.4
http://svn.edgewall.org/repos/genshi/tags/0.3.4/
diff --git a/UPGRADE.txt b/UPGRADE.txt
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -10,6 +10,10 @@
leftover traces of the `template.py` file on the installation path.
This is not necessary when Genshi was installed as a Python egg.
+Results of evaluating template expressions are no longer implicitly
+called if they are callable. If you have been using that feature, you
+will need to add the parenthesis to actually call the function.
+
Upgrading from Markup
---------------------
diff --git a/genshi/template/directives.py b/genshi/template/directives.py
--- a/genshi/template/directives.py
+++ b/genshi/template/directives.py
@@ -155,13 +155,13 @@
If a function does not require parameters, the parenthesis can be omitted
- both when defining and when calling it:
+ in the definition:
>>> tmpl = MarkupTemplate('''
...
... Hello, world!
...
- ... ${helloworld}
+ ... ${helloworld()}
...
''')
>>> print tmpl.generate(bar='Bye')
@@ -589,7 +589,7 @@
frame = {}
ctxt.push(frame)
for targets, expr in self.vars:
- value = expr.evaluate(ctxt, nocall=True)
+ value = expr.evaluate(ctxt)
for assign in targets:
assign(frame, value)
for event in _apply_directives(stream, ctxt, directives):
diff --git a/genshi/template/eval.py b/genshi/template/eval.py
--- a/genshi/template/eval.py
+++ b/genshi/template/eval.py
@@ -95,22 +95,17 @@
def __repr__(self):
return 'Expression(%r)' % self.source
- def evaluate(self, data, nocall=False):
+ def evaluate(self, data):
"""Evaluate the expression against the given data dictionary.
@param data: a mapping containing the data to evaluate against
- @param nocall: if true, the result of the evaluation is not called if
- if it is a callable
@return: the result of the evaluation
"""
- retval = eval(self.code, {'data': data,
- '_lookup_name': _lookup_name,
- '_lookup_attr': _lookup_attr,
- '_lookup_item': _lookup_item},
- {'data': data})
- if not nocall and type(retval) is not Undefined and callable(retval):
- retval = retval()
- return retval
+ return eval(self.code, {'data': data,
+ '_lookup_name': _lookup_name,
+ '_lookup_attr': _lookup_attr,
+ '_lookup_item': _lookup_item},
+ {'data': data})
class Undefined(object):
diff --git a/genshi/template/tests/eval.py b/genshi/template/tests/eval.py
--- a/genshi/template/tests/eval.py
+++ b/genshi/template/tests/eval.py
@@ -32,10 +32,9 @@
def test_name_lookup(self):
self.assertEqual('bar', Expression('foo').evaluate({'foo': 'bar'}))
- self.assertEqual(id, Expression('id').evaluate({}, nocall=True))
+ self.assertEqual(id, Expression('id').evaluate({}))
self.assertEqual('bar', Expression('id').evaluate({'id': 'bar'}))
- self.assertEqual(None, Expression('id').evaluate({'id': None},
- nocall=True))
+ self.assertEqual(None, Expression('id').evaluate({'id': None}))
def test_str_literal(self):
self.assertEqual('foo', Expression('"foo"').evaluate({}))
@@ -217,14 +216,8 @@
def test_call_dstar_args(self):
def foo(x):
return x
- self.assertEqual(42, Expression("foo(**bar)").evaluate({'foo': foo,
- 'bar': {"x": 42}}))
-
- def test_call_function_without_params(self):
- self.assertEqual(42, Expression("foo").evaluate({'foo': lambda: 42}))
- data = {'foo': 'bar'}
- self.assertEqual('BAR', Expression("foo.upper").evaluate(data))
- data = {'foo': {'bar': range(42)}}
+ expr = Expression("foo(**bar)")
+ self.assertEqual(42, expr.evaluate({'foo': foo, 'bar': {"x": 42}}))
def test_lambda(self):
# Define a custom `sorted` function cause the builtin isn't available