From 9201f46cc8e92231f0f6c92e4d56befbc150f72c Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 26 Oct 2018 16:48:07 +1100 Subject: py/compile: Fix case of eager implicit conversion of local to nonlocal. This ensures that implicit variables are only converted to implicit closed-over variables (nonlocals) at the very end of the function scope. If variables are closed-over when first used (read from, as was done prior to this commit) then this can be incorrect because the variable may be assigned to later on in the function which means they are just a plain local, not closed over. Fixes issue #4272. --- tests/basics/scope_implicit.py | 31 +++++++++++++++++++++++++++++++ tests/run-tests | 1 + 2 files changed, 32 insertions(+) create mode 100644 tests/basics/scope_implicit.py (limited to 'tests') diff --git a/tests/basics/scope_implicit.py b/tests/basics/scope_implicit.py new file mode 100644 index 000000000..aecda7715 --- /dev/null +++ b/tests/basics/scope_implicit.py @@ -0,0 +1,31 @@ +# test implicit scoping rules + +# implicit nonlocal, with variable defined after closure +def f(): + def g(): + return x # implicit nonlocal + x = 3 # variable defined after function that closes over it + return g +print(f()()) + +# implicit nonlocal at inner level, with variable defined after closure +def f(): + def g(): + def h(): + return x # implicit nonlocal + return h + x = 4 # variable defined after function that closes over it + return g +print(f()()()) + +# local variable which should not be implicitly made nonlocal +def f(): + x = 0 + def g(): + x # local because next statement assigns to it + x = 1 + g() +try: + f() +except NameError: + print('NameError') diff --git a/tests/run-tests b/tests/run-tests index d72ae9dc4..62af90f28 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -358,6 +358,7 @@ def run_tests(pyb, tests, args, base_path="."): skip_tests.add('basics/del_deref.py') # requires checking for unbound local skip_tests.add('basics/del_local.py') # requires checking for unbound local skip_tests.add('basics/exception_chain.py') # raise from is not supported + skip_tests.add('basics/scope_implicit.py') # requires checking for unbound local skip_tests.add('basics/try_finally_return2.py') # requires raise_varargs skip_tests.add('basics/unboundlocal.py') # requires checking for unbound local skip_tests.add('misc/features.py') # requires raise_varargs -- cgit v1.2.3