Allow function definition locals() to be modified in the shell
This still requires more testing, especially for the different shells.
For the IPython shell, this requires not making a copy of locals(), but this also causes the IPython shell to pollute the locals() namespace with all its internal variables (like _0 and so on), so a better fix is needed.
Fixes #26.
Probably going to just revert the change to the IPython shell, meaning this won't work there (but it will work in the inline shell). Unless IPython has a method to turn this off, we would have to manually remove them every time IPython is started. It would also break any code that happens to use the same variable names as the ones IPython injects (which includes _, which is not uncommon).
So based on some (very basic) testing:
- Internal shell and classic shell work great. Even though they both use the
_magic variable, they don't seem to actually inject it into the locals.- ~Only downside of the internal shell is that variables aren't updated automatically in the variables view until you step the debugger. This should be fixable by making it update whenever a command is executed.~ EDIT: fixed
- IPython would work if we remove that copy() line, but that also makes it inject all the IPython magic variables every time it is started (of which there are a lot).
- IPython kernel works and also injects the magic variables. I will probably fix this to also copy() like IPython. As an aside, IPython kernel seems to be broken for me. When I exit the kernel, pudb restarts in a broken terminal state, which can only be fixed by exiting pudb and typing the
resetcommand. - bpython works, but injects the
helpvariable into the locals. I'm surprised that's the only variable it injects. This is probably fine to just leave alone - ptpython doesn't work. It would work if we removed the
copy()line, but this would also make it inject its magic variables (only_0and so on). - ptipython doesn't work at all. As in, it's broken even in
main. When you try to access a local variable in ptpython, it doesn't see it. I don't know why because it looks likelocalsis being passed through correctly, so it seems like the problem is likely upstream. Does anyone even use ptipython? It seems defunct now that IPython itself uses prompt-toolkit, which has been the case for a while.
We'll probably want some way to disable this behavior, as you might not actually want the variables you type in the shell to inject themselves into your code. Although note that this is already the behavior at the module level because writing to globals() works just fine. We could easily make it not do that there by copying globals before passing it to the shell. IMO we should do that, so that the option is either "shell edits variables" which causes it to edit both globals and locals, or "shell doesn't edit variables" which causes the shells to always get a copy of globals and locals. That way the behavior is effectively the same whether you are at the module level or inside a function.
What should the config look like? We can force it to work with any of the shells, even the ones that inject a lot of variables. So what should the default look like? Ideally for the internal and classic shells it would be enabled by default and for IPython it should be disabled by default.
This could probably use some more testing, but for now, the main thing I know is missing is a configuration option, which I'd like feedback on how to best do (see my previous comment). Should it just default to the behavior being on (or off) or try to set a "best guess" default depending on which shell is enabled? Or should it default to on but only actually work in the shells that don't inject variables (the rest would always copy locals() to prevent it from working).
CC @inducer
- ptipython doesn't work at all. As in, it's broken even in
main. When you try to access a local variable in ptpython, it doesn't see it. I don't know why because it looks likelocalsis being passed through correctly, so it seems like the problem is likely upstream. Does anyone even use ptipython? It seems defunct now that IPython itself uses prompt-toolkit, which has been the case for a while.
I would be OK with just removing ptipython.
setting
I would vote for keeping this simple to start. Either propagate or don't. And if ipython is being used with "yes, propagate", maybe print a one-line warning every time it starts, stating that IPython spews copious amounts of variables.