changeset 587:587910938507 stable-0.4.x

Ported [700] to 0.4.x branch.
author cmlenz
date Wed, 08 Aug 2007 22:27:26 +0000
parents 60a906b93acd
children a8bfe7828ce6
files genshi/template/eval.py genshi/template/tests/eval.py
diffstat 2 files changed, 62 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/genshi/template/eval.py
+++ b/genshi/template/eval.py
@@ -688,6 +688,8 @@
             return ASTTransformer.visitAugAssign(self, node)
 
     def visitClass(self, node):
+        if self.locals:
+            self.locals[-1].add(node.name)
         self.locals.append(set())
         node = ASTTransformer.visitClass(self, node)
         self.locals.pop()
@@ -700,6 +702,8 @@
         return node
 
     def visitFunction(self, node):
+        if self.locals:
+            self.locals[-1].add(node.name)
         self.locals.append(set(node.argnames))
         node = ASTTransformer.visitFunction(self, node)
         self.locals.pop()
@@ -726,12 +730,11 @@
     def visitName(self, node):
         # If the name refers to a local inside a lambda, list comprehension, or
         # generator expression, leave it alone
-        for frame in self.locals:
-            if node.name in frame:
-                return node
-        # Otherwise, translate the name ref into a context lookup
-        func_args = [ast.Name('data'), ast.Const(node.name)]
-        return ast.CallFunc(ast.Name('_lookup_name'), func_args)
+        if node.name not in flatten(self.locals):
+            # Otherwise, translate the name ref into a context lookup
+            func_args = [ast.Name('data'), ast.Const(node.name)]
+            node = ast.CallFunc(ast.Name('_lookup_name'), func_args)
+        return node
 
 
 class ExpressionASTTransformer(TemplateASTTransformer):
--- a/genshi/template/tests/eval.py
+++ b/genshi/template/tests/eval.py
@@ -449,7 +449,8 @@
         self.assertEqual(None, data['donothing']())
 
     def test_def_with_multiple_statements(self):
-        suite = Suite("""def donothing():
+        suite = Suite("""
+def donothing():
     if True:
         return foo
 """)
@@ -458,6 +459,35 @@
         assert 'donothing' in data
         self.assertEqual('bar', data['donothing']())
 
+    def test_def_using_nonlocal(self):
+        suite = Suite("""
+values = []
+def add(value):
+    if value not in values:
+        values.append(value)
+add('foo')
+add('bar')
+""")
+        data = {}
+        suite.execute(data)
+        self.assertEqual(['foo', 'bar'], data['values'])
+
+    def test_def_nested(self):
+        suite = Suite("""
+def doit():
+    values = []
+    def add(value):
+        if value not in values:
+            values.append(value)
+    add('foo')
+    add('bar')
+    return values
+x = doit()
+""")
+        data = {}
+        suite.execute(data)
+        self.assertEqual(['foo', 'bar'], data['x'])
+
     def test_delete(self):
         suite = Suite("""foo = 42
 del foo
@@ -472,6 +502,28 @@
         suite.execute(data)
         assert 'plain' in data
 
+    def test_class_in_def(self):
+        suite = Suite("""
+def create():
+    class Foobar(object):
+        def __str__(self):
+            return 'foobar'
+    return Foobar()
+x = create()
+""")
+        data = {}
+        suite.execute(data)
+        self.assertEqual('foobar', str(data['x']))
+
+    def test_class_with_methods(self):
+        suite = Suite("""class plain(object):
+    def donothing():
+        pass
+""")
+        data = {}
+        suite.execute(data)
+        assert 'plain' in data
+
     def test_import(self):
         suite = Suite("from itertools import ifilter")
         data = {}
Copyright (C) 2012-2017 Edgewall Software