#4617: Previously it was illegal to delete a name from the local
namespace if it occurs as a free variable in a nested block. This limitation
of the compiler has been lifted, and a new opcode introduced (DELETE_DEREF).
This sample was valid in 2.6, but fails to compile in 3.x without this change::
>>> def f():
... def print_error():
... print(e)
... try:
... something
... except Exception as e:
... print_error()
... # implicit "del e" here
This sample has always been invalid in Python, and now works::
>>> def outer(x):
... def inner():
... return x
... inner()
... del x
There is no need to bump the PYC magic number: the new opcode is used
for code that did not compile before.
diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py
index 2ac34cf..0e5a8e9 100644
--- a/Lib/test/test_scope.py
+++ b/Lib/test/test_scope.py
@@ -218,13 +218,6 @@
""")
check_syntax_error(self, """if 1:
- def f(x):
- def g():
- return x
- del x # can't del name
- """)
-
- check_syntax_error(self, """if 1:
def f():
def g():
from sys import *
@@ -272,6 +265,28 @@
self.assertRaises(UnboundLocalError, errorInOuter)
self.assertRaises(NameError, errorInInner)
+ def testUnboundLocal_AfterDel(self):
+ # #4617: It is now legal to delete a cell variable.
+ # The following functions must obviously compile,
+ # and give the correct error when accessing the deleted name.
+ def errorInOuter():
+ y = 1
+ del y
+ print(y)
+ def inner():
+ return y
+
+ def errorInInner():
+ def inner():
+ return y
+ y = 1
+ del y
+ inner()
+
+ self.assertRaises(UnboundLocalError, errorInOuter)
+ self.assertRaises(NameError, errorInInner)
+
+ def testUnboundLocal_AugAssign(self):
# test for bug #1501934: incorrect LOAD/STORE_GLOBAL generation
exec("""if 1:
global_x = 1