From 43a72450451cd637aa14ddc98d65f03656c228c2 Mon Sep 17 00:00:00 2001 From: HyeockJinKim Date: Fri, 11 Oct 2019 04:32:09 +0900 Subject: [PATCH 1/2] locals() return copy of locals dictionary Return copy of locals so that local variables does not change even if locals() values is changed Fixes #1356 --- vm/src/builtins.rs | 3 ++- vm/src/obj/objdict.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index a1153e5979..ef93be107e 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -366,7 +366,8 @@ fn builtin_len(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { } fn builtin_locals(vm: &VirtualMachine) -> PyDictRef { - vm.get_locals() + let locals = vm.get_locals(); + locals.copy(vm).into_ref(vm) } fn builtin_max(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index 73e0d8f9c5..efce28cfcd 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -279,7 +279,7 @@ impl PyDictRef { } } - fn copy(self, _vm: &VirtualMachine) -> PyDict { + pub fn copy(self, _vm: &VirtualMachine) -> PyDict { PyDict { entries: self.entries.clone(), } From cb9b9e63203455d4dbba06195c6b2b08756b5f16 Mon Sep 17 00:00:00 2001 From: HyeockJinKim Date: Fri, 11 Oct 2019 04:33:44 +0900 Subject: [PATCH 2/2] Add tests for locals --- tests/snippets/global_nonlocal.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/snippets/global_nonlocal.py b/tests/snippets/global_nonlocal.py index 21e944f5b5..b2989baabf 100644 --- a/tests/snippets/global_nonlocal.py +++ b/tests/snippets/global_nonlocal.py @@ -85,3 +85,27 @@ def f(): # nonlocal c # c = 2 +def a(): + x = 0 + locals()['x'] = 3 + assert x == 0 + +a() + +def a(): + x = 0 + del locals()['x'] + assert x == 0 + +a() + +def a(): + x = 0 + b = locals() + assert b['x'] == 0 + + del b['x'] + b = locals() + assert b['x'] == 0 + +a() \ No newline at end of file