New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Usermod #648
Usermod #648
Conversation
This now works with embedding in a terminal program, but there's an odd exception. You can modify mutable values and define new local variables, but it doesn't rebind existing names. In the example below, doing from IPython import embed a = 12 def f(): b = 66 c = [] embed() print locals() print globals() f() |
Also, if I define |
Should we close #384 and focus only on this one then? |
If you're happy with this approach, yes. |
OK, I'm closing #384 then, and we'll focus on this one instead. I do like the idea of being more careful about how we handle namespaces, so I vote for this. Unfortunately I can't finish a full review of this one right now, but I'll try to get to it in the evening. Thanks! |
OK, great. Actually, I'm just going to revert a couple of commits that I no longer like, so if you've checked this branch out, be ready to fetch it again. |
We had wanted this one to sit in master for a while before release, given its potential implications. Do we want to get on this, as we want 0.12 by December? |
I'm not too concerned about it being deferred. I think the main visible benefit it gives is that you can pickle objects defined interactively (#29). It could potentially lead to some small API breakage, but I don't think most software that embeds it passes a |
@takluyver, I see a merge conflict on this one now... If you have a chance to clean it up, I'd be happy to try and work on it so we can merge sooner rather than later... |
…and add test for pickling interactively defined objects. Closes ipythongh-29
Rebased and run the test suite on 2.7 and 3.2. |
"Code in functions must be able to access variables outside them." | ||
ip = get_ipython() | ||
ip.run_cell("a = 10") | ||
ip.run_cell(("def f(x):" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
though this code is correct as-is, you probably meant to have a \n at the end here, no? It would make it more natural and in case anyone ever adds for some reason one more line, it would continue to work where as without newlines one more would be a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right - thanks. Sorted.
Clean up handling of global namespaces with the proper semantics. A global namespace should always be tied to a module: pickle accesses classes via the module in which they're defined. So I've changed the arguments for instantiating an InteractiveShell to include `user_module` in place of `user_global_ns`. The global namespace simply becomes a reference to `user_module.__dict__`. For instantiating InteractiveShell, there are four possibilities: * Neither `user_ns` nor `user_module` is given. A new (real) module is created named `__main__`, and its `__dict__` becomes the global and local namespace. This is what happens when starting IPython normally. * Only `user_module` is given. Its `__dict__` becomes the global and local namespace. * Both `user_ns` and `user_module` are given. `user_module.__dict__` is the global namespace, and `user_ns` is the local namespace. Note that we can't interactively define closures over variables in the local namespace (this seems to be a limitation of Python). * Only `user_ns` is given. It is treated as the global and local namespace, and a `DummyMod` object is created to refer to it. This is intended as a convenience, especially for the test suite. The recommended way to pass in a single global namespace is as a reference to the module. `embed()` digs out the locals and the module from the frame in which it's called. Closes gh-29, closes gh-693.
…on#648. code used it as a dict. Updated that code to handle a dict correctly, and added tests to catch this issue in the future (also increases test coverage of pylab code).
Fix bug in pylab support introduced in #648, and refactor the pylab/gui support to eliminate a lot of code duplication we had in a number of places. Now all duplicate code is gone, and the only real difference is how gui event loops are integrated, which is reduced to a single static method that each relevant class grabs from its specific machinery.
Clean up handling of global namespaces with the proper semantics. A global namespace should always be tied to a module: pickle accesses classes via the module in which they're defined. So I've changed the arguments for instantiating an InteractiveShell to include `user_module` in place of `user_global_ns`. The global namespace simply becomes a reference to `user_module.__dict__`. For instantiating InteractiveShell, there are four possibilities: * Neither `user_ns` nor `user_module` is given. A new (real) module is created named `__main__`, and its `__dict__` becomes the global and local namespace. This is what happens when starting IPython normally. * Only `user_module` is given. Its `__dict__` becomes the global and local namespace. * Both `user_ns` and `user_module` are given. `user_module.__dict__` is the global namespace, and `user_ns` is the local namespace. Note that we can't interactively define closures over variables in the local namespace (this seems to be a limitation of Python). * Only `user_ns` is given. It is treated as the global and local namespace, and a `DummyMod` object is created to refer to it. This is intended as a convenience, especially for the test suite. The recommended way to pass in a single global namespace is as a reference to the module. `embed()` digs out the locals and the module from the frame in which it's called. Closes ipythongh-29, closes ipythongh-693.
…on#648. code used it as a dict. Updated that code to handle a dict correctly, and added tests to catch this issue in the future (also increases test coverage of pylab code).
Fix bug in pylab support introduced in ipython#648, and refactor the pylab/gui support to eliminate a lot of code duplication we had in a number of places. Now all duplicate code is gone, and the only real difference is how gui event loops are integrated, which is reduced to a single static method that each relevant class grabs from its specific machinery.
This is intended to supersede my PR #384, where I made it possible to pickle interactively defined objects. While I was working on that, I realised that our distinction between local and global namespaces is a bit unclear (because they're usually the same thing). This goes some way towards clearing that up.
A global namespace should always be tied to a module: pickle accesses classes via the module in which they're defined. So I've changed the arguments for instantiating an InteractiveShell to include
user_module
in place ofuser_global_ns
. The global namespace simply becomes a reference touser_module.__dict__
.For instantiating InteractiveShell, there are four possibilities:
user_ns
noruser_module
is given. A new (real) module is created named__main__
, and its__dict__
becomes the global and local namespace. This is what happens when starting IPython normally.user_module
is given. Its__dict__
becomes the global and local namespace.user_ns
anduser_module
are given.user_module.__dict__
is the global namespace, anduser_ns
is the local namespace. Note that we can't interactively define closures over variables in the local namespace (this seems to be a limitation of Python).user_ns
is given. It is treated as the global and local namespace, and aDummyMod
object is created to refer to it. This is intended as a convenience, especially for the test suite. The recommended way to pass in a single global namespace is as a reference to the module.embed()
digs out the locals and the module from the frame in which it's called.While I was doing namespaces, I also re-included a reference to the InteractiveShell, as a weakref proxy, named
_ipy
.