# HG changeset patch # User cmlenz # Date 1163152844 0 # Node ID 35189e9602521e132638a61ec92d43da3827453c # Parent b517929eb334a0f98a678300cc12aed0470ed2eb 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