# HG changeset patch # User mgood # Date 1249850339 0 # Node ID 9cabfbc4ac5cf74ddfae8cbbc933c97b936d6edb # Parent 0af77f663a6511ee4af8a95c7a5baf076ac50590 Fix nested list comprehensions & generator expressions (fixes #327) diff --git a/genshi/template/eval.py b/genshi/template/eval.py --- a/genshi/template/eval.py +++ b/genshi/template/eval.py @@ -558,15 +558,13 @@ # GeneratorExp(expr elt, comprehension* generators) def visit_GeneratorExp(self, node): gens = [] - # need to visit them in inverse order - for generator in node.generators[::-1]: + for generator in node.generators: # comprehension = (expr target, expr iter, expr* ifs) self.locals.append(set()) gen = _new(_ast.comprehension, self.visit(generator.target), - self.visit(generator.iter), - [self.visit(if_) for if_ in generator.ifs]) + self.visit(generator.iter), + [self.visit(if_) for if_ in generator.ifs]) gens.append(gen) - gens.reverse() # use node.__class__ to make it reusable as ListComp ret = _new(node.__class__, self.visit(node.elt), gens) 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 @@ -258,6 +258,14 @@ self.assertEqual([2, 3, 4, 5, 6], expr.evaluate({'numbers': range(5), 'offset': 2})) + expr = Expression("[n for group in groups for n in group]") + self.assertEqual([0, 1, 0, 1, 2], + expr.evaluate({'groups': [range(2), range(3)]})) + + expr = Expression("[(a, b) for a in x for b in y]") + self.assertEqual([('x0', 'y0'), ('x0', 'y1'), ('x1', 'y0'), ('x1', 'y1')], + expr.evaluate({'x': ['x0', 'x1'], 'y': ['y0', 'y1']})) + def test_list_comprehension_with_getattr(self): items = [{'name': 'a', 'value': 1}, {'name': 'b', 'value': 2}] expr = Expression("[i.name for i in items if i.value > 1]") @@ -280,6 +288,14 @@ self.assertEqual([2, 3, 4, 5, 6], expr.evaluate({'numbers': range(5), 'offset': 2})) + expr = Expression("list(n for group in groups for n in group)") + self.assertEqual([0, 1, 0, 1, 2], + expr.evaluate({'groups': [range(2), range(3)]})) + + expr = Expression("list((a, b) for a in x for b in y)") + self.assertEqual([('x0', 'y0'), ('x0', 'y1'), ('x1', 'y0'), ('x1', 'y1')], + expr.evaluate({'x': ['x0', 'x1'], 'y': ['y0', 'y1']})) + 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)")