summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_scope.py84
-rw-r--r--Lib/test/test_syntax.py40
2 files changed, 124 insertions, 0 deletions
diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py
index b9dc711..5fe1bc7 100644
--- a/Lib/test/test_scope.py
+++ b/Lib/test/test_scope.py
@@ -555,6 +555,90 @@ self.assert_(X.passed)
f(4)()
+ def testNonLocalFunction(self):
+
+ def f(x):
+ def inc():
+ nonlocal x
+ x += 1
+ return x
+ def dec():
+ nonlocal x
+ x -= 1
+ return x
+ return inc, dec
+
+ inc, dec = f(0)
+ self.assertEqual(inc(), 1)
+ self.assertEqual(inc(), 2)
+ self.assertEqual(dec(), 1)
+ self.assertEqual(dec(), 0)
+
+ def testNonLocalMethod(self):
+
+ def f(x):
+ class c:
+ def inc(self):
+ nonlocal x
+ x += 1
+ return x
+ def dec(self):
+ nonlocal x
+ x -= 1
+ return x
+ return c()
+
+ c = f(0)
+ self.assertEqual(c.inc(), 1)
+ self.assertEqual(c.inc(), 2)
+ self.assertEqual(c.dec(), 1)
+ self.assertEqual(c.dec(), 0)
+
+ def testNonLocalClass(self):
+
+ def f(x):
+ class c:
+ nonlocal x
+ x += 1
+ def get(self):
+ return x
+ return c()
+
+ c = f(0)
+ self.assertEqual(c.get(), 1)
+ self.assert_("x" not in c.__class__.__dict__)
+
+
+ def testNonLocalGenerator(self):
+
+ def f(x):
+ def g(y):
+ nonlocal x
+ for i in range(y):
+ x += 1
+ yield x
+ return g
+
+ g = f(0)
+ self.assertEqual(list(g(5)), [1, 2, 3, 4, 5])
+
+ def testNestedNonLocal(self):
+
+ def f(x):
+ def g():
+ nonlocal x
+ x -= 2
+ def h():
+ nonlocal x
+ x += 4
+ return x
+ return h
+ return g
+
+ g = f(1)
+ h = g()
+ self.assertEqual(h(), 3)
+
def test_main():
run_unittest(ScopeTests)
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py
index 8999e3a..f37b666 100644
--- a/Lib/test/test_syntax.py
+++ b/Lib/test/test_syntax.py
@@ -367,6 +367,46 @@ build. The number of blocks must be greater than CO_MAXBLOCKS. SF #1565514
...
SystemError: too many statically nested blocks
+Misuse of the nonlocal statement can lead to a few unique syntax errors.
+
+ >>> def f(x):
+ ... nonlocal x
+ Traceback (most recent call last):
+ ...
+ SyntaxError: name 'x' is local and nonlocal
+
+ >>> def f():
+ ... global x
+ ... nonlocal x
+ Traceback (most recent call last):
+ ...
+ SyntaxError: name 'x' is nonlocal and global
+
+ >>> def f():
+ ... nonlocal x
+ Traceback (most recent call last):
+ ...
+ SyntaxError: no binding for nonlocal 'x' found
+
+TODO(jhylton): Figure out how to test SyntaxWarning with doctest.
+
+## >>> def f(x):
+## ... def f():
+## ... print(x)
+## ... nonlocal x
+## Traceback (most recent call last):
+## ...
+## SyntaxWarning: name 'x' is assigned to before nonlocal declaration
+
+## >>> def f():
+## ... x = 1
+## ... nonlocal x
+## Traceback (most recent call last):
+## ...
+## SyntaxWarning: name 'x' is assigned to before nonlocal declaration
+
+
+
"""
import re