diff options
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | cmd2/cmd2.py | 4 | ||||
-rwxr-xr-x | tests/test_cmd2.py | 9 |
3 files changed, 13 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 18ac2348..4d662cf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ * Setting the following pyscript variables: * `__name__`: __main__ * `__file__`: script path (as typed, ~ will be expanded) +* Other + * Removed undocumented `py run` command since it was replaced by `run_pyscript` a while ago ## 0.10.0 (February 7, 2020) * Enhancements diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index c7a0fa6d..3b1fbb6f 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -3120,7 +3120,9 @@ class Cmd(cmd.Cmd): self._in_py = True py_code_to_run = '' - # Locals for the Python environment we are creating + # Use self.py_locals as the locals() dictionary in the Python environment we are creating, but make + # a copy to prevent pyscripts from editing it. (e.g. locals().clear()). Only make a shallow copy since + # it's OK for py_locals to contain objects which are editable in a pyscript. localvars = dict(self.py_locals) localvars[self.py_bridge_name] = py_bridge localvars['quit'] = py_quit diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py index 41528612..dc9a3fa1 100755 --- a/tests/test_cmd2.py +++ b/tests/test_cmd2.py @@ -206,7 +206,7 @@ def test_base_shell(base_app, monkeypatch): def test_base_py(base_app): # Make sure py can't edit Cmd.py_locals. It used to be that cmd2 was passing its py_locals - # dictionary to the py environment instead of a copy. + # dictionary to the py environment instead of a shallow copy. base_app.py_locals['test_var'] = 5 out, err = run_cmd(base_app, 'py del[locals()["test_var"]]') assert not out and not err @@ -215,6 +215,13 @@ def test_base_py(base_app): out, err = run_cmd(base_app, 'py print(test_var)') assert out[0].rstrip() == '5' + # Place an editable object in py_locals. Since we make a shallow copy of py_locals, + # this object should be editable from the py environment. + base_app.py_locals['my_list'] = [] + out, err = run_cmd(base_app, 'py my_list.append(2)') + assert not out and not err + assert base_app.py_locals['my_list'][0] == 2 + # Try a print statement out, err = run_cmd(base_app, 'py print("spaces" + " in this " + "command")') assert out[0].rstrip() == 'spaces in this command' |