rendered paste bodyIndex: markup/tests/eval.py===================================================================--- markup/tests/eval.py (revision 246)+++ markup/tests/eval.py (working copy)@@ -240,6 +240,29 @@ expr = Expression("[i['name'] for i in items if i['value'] > 1]") self.assertEqual(['b'], expr.evaluate({'items': items})) + def test_generator_expression(self):+ # TODO skip test on Python 2.3+ expr = Expression("list(n for n in numbers if n < 2)")+ self.assertEqual([0, 1], expr.evaluate({'numbers': range(5)}))++ expr = Expression("list((i, n + 1) for i, n in enumerate(numbers))")+ self.assertEqual([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)],+ expr.evaluate({'numbers': range(5)}))++ expr = Expression("list(offset + n for n in numbers)")+ self.assertEqual([2, 3, 4, 5, 6],+ expr.evaluate({'numbers': range(5), 'offset': 2}))++ def test_generator_expression_with_getattr(self):+ items = [{'name': 'a', 'value': 1}, {'name': 'b', 'value': 2}]+ expr = Expression("list(i.name for i in items if i.value > 1)")+ self.assertEqual(['b'], expr.evaluate({'items': items}))++ def test_generator_expression_with_getitem(self):+ items = [{'name': 'a', 'value': 1}, {'name': 'b', 'value': 2}]+ expr = Expression("list(i['name'] for i in items if i['value'] > 1)")+ self.assertEqual(['b'], expr.evaluate({'items': items}))+ def test_error_access_undefined(self): expr = Expression("nothing", filename='index.html', lineno=50) self.assertEqual(Undefined, type(expr.evaluate({})))Index: markup/eval.py===================================================================--- markup/eval.py (revision 246)+++ markup/eval.py (working copy)@@ -331,7 +331,27 @@ node.test = self.visit(node.test, *args, **kwargs) return node + def visitGenExpr(self, node, *args, **kwargs):+ node.code = self.visit(node.code, *args, **kwargs)+ node.filename = '<string>' # workaround for bug in pycodegen+ return node + def visitGenExprFor(self, node, *args, **kwargs):+ node.assign = self.visit(node.assign, *args, **kwargs)+ node.iter = self.visit(node.iter, *args, **kwargs)+ node.ifs = map(lambda x: self.visit(x, *args, **kwargs), node.ifs)+ return node++ def visitGenExprIf(self, node, *args, **kwargs):+ node.test = self.visit(node.test, locals_=True, *args, **kwargs)+ return node++ def visitGenExprInner(self, node, *args, **kwargs):+ node.expr = self.visit(node.expr, locals_=True, *args, **kwargs)+ node.quals = map(lambda x: self.visit(x, *args, **kwargs), node.quals)+ return node++ class ExpressionASTTransformer(ASTTransformer): """Concrete AST transformer that implements the AST transformations needed for template expressions.