-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
IPEP 21: widget messages #4195
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
IPEP 21: widget messages #4195
Conversation
cc: @dcjones, who has been implementing JS-based plotting widgets in IJulia. Would be nice in the PEP to refer to the "kernel" rather than "Python" side, and to separate the things that any kernel must do from the specific implementation details in the IPython kernel. |
I tried to do this, I will read through again and see where I slipped up. There are actually three pieces here:
|
I read through the IPEP, and Python is never mentioned in the spec - I only use Kernel and Frontend there. When I switch gears to talk about the specific APIs of the Python and Javascript implementations, I discuss the languages in which those implementations exist. I have clarified the transition, though. |
Great work, I love the symmetry and simplicity! Widget Creation:
Widget object:
|
I think the biggest question I have at this point is how widgets relate to our standard display messages. What happens if a widget needs to update the state of a matplotlib plot? Seems like there needs to be some coordination there. Do widgets handle the display messages? Do why manage their own Another question is if we are going to have any notion of widget nesting. If there is a plot that updates with the values of 4 sliders and 2 checkboxes, is that 1 widget or 6? |
var msg_types = ['widget_create', 'widget_destroy', 'widget_update']; | ||
for (var i = 0; i < msg_types.length; i++) { | ||
var msg_type = msg_types[i]; | ||
kernel.register_iopub_handler(msg_type, $.proxy(this[msg_type], this)); |
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.
Do we make sure that we unregister these handlers when the widget is destroyed?
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.
These are only registered once - there is only one WidgetManager.
In the IPEP, we should emphasize that the |
Could you point to your examples? |
@ivanov and @jdfreder I think the best way for us to test this widget messages is to use it to write our higher level JS/Python APIs. You are the two leads on that (Paul on the Python side, Jon on the Javascript side). Can you both start to think about that stuff. I am more than will to have design discussion with both of you. I want us to start this stuff as soon as possible so we have time to iterate and bake the design before 2.0. |
@ellisonbg sounds like a good idea. When are you going to be back in town? |
In the PEP, you ask: "Question: the handle_foo messages get the data dict, not the full message. This means they don't have access to metadata, etc. Should the handlers get the full message instead?" I think yes. It would be useful, for example, to access the metadata. It might also be useful to see the timestamp when a message was generated, for example. And at least passing in the metadata would be more consistent with other handlers, right? |
@jdfreder I will be back Sat night, back in the office on Monday. I will be in touch. |
@jasongrout makes a good point. I could imagine that for some widgets, the timestamps are important - they could be used to throttle the update rates. |
I should mention - I play some last week with some slider widgets and quickly found that it was easy to flood the kernel with calls. I am wondering if we want to add code on the JS side that can automatically throttle the rate at which the update messages are send. I think this is going to be a really common problem that most highly interactive widgets have. |
Another question to consider: How do you lay out multiple widgets? Suppose I want two sliders next to each other, above an interactive plot, with two buttons off to the side? I can construct the necessary html, for example. How do I specify where to put the widgets in the html? This is related to @ellisonbg's comment about nested widgets. For Sage interacts, we have 3 layout systems, two of which are currently active. One is a list of lists (i.e., rows of columns). Another that might be more applicable here is to just spit out the html, then give the "locations", which are jquery selectors for the places to put the widgets. |
An update from the dev meeting and today's discussion: These are not widgets, they are the basic communication object used to implement widgets. As a result, they should not be called widgets, but something else. I think I'm going with Comm for now. When you create a Widget, it will use a Comm, but it will not be a Comm.
The creator picks the ID, can be done from either side.
Yes
Right now, it just logs an error.
Yes, the spec is fully symmetrical. I initially didn't allow this, because of a note from the dev meeting,
Okay, I will pass along the whole message - it's not appreciably more complicated.
Will do.
I don't think so. Other than creation / destruction, there is only one message type, so if message handlers should ever send a message back at all, this restriction cannot be enforced. It makes perfect sense for an update from one side to result in a different update coming back (e.g. changing a value causing a replot). It is up to the implementer to ensure they don't get stuck. |
@jasongrout - this is not GUI widgets, only the communication part. Layout, etc. is entirely independent of this. |
Yes, I ran into this myself, and quickly started throttling requests. I'm not sure how to do it in a generic way that we can reasonably enforce on all widget authors, though. |
@minrk this brings up a good point about naming. The current naming On Thu, Sep 12, 2013 at 2:53 PM, Min RK [email protected] wrote:
Brian E. Granger |
@minrk: it makes sense that layout issues are above the communication layer. But the creation handler will have to address this somehow, so that's another vote for the whole message (including maybe layout metadata) being passed into the create handler. |
That seems like it would be up to the Widget implementation - some might hook up events on an existing OutputArea, some might manipulate their own div elsewhere (sidebar namespace browser). It doesn't seem like a question that can have a generic answer.
I don't know. I also am not sure this has any bearing on the code here - this is just the very basic communication code for allowing some object in the Kernel to talk to some object in the Frontend and vice versa. |
@minrk: if you're changing the names to reflect a message channel, maybe instead of |
@jasongrout reading my mind - I have switched create/update/destroy to more comm-appropriate open/send/close. |
I like the simplicity of the open/send/close/handlers idea. Basically you are just creating a private message channel on top of the existing messaging framework. I can see how just passing the data attribute makes sense---the IPython message wrapping the data attribute is nothing but routing information. |
That's true - and if the entity constructing the object is interesting in timings, it can always add them to the data messages. I guess I will live it using just |
So how do you handle a channel open message from a frontend to a kernel that has multiple frontends? Do you broadcast out an open message to all other frontends (like you would echo input)? What about channel close messages? Are send messages from the kernel sent to all frontends? |
This is a good point, where there is an asymmetry - one kernel, possibly multiple frontends. It seems to me that it makes sense in general for a Comm on the Kernel side to re-broadcast both |
* @submodule comm | ||
*/ | ||
|
||
var IPython = (function (IPython) { |
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.
Would you like to start using require
?
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.
I would like to use require
but that should be a separate PR.
A few more thoughts:
|
for reusing default execute callbacks
Javascript-side version for creating and connecting Comms in one call Without a `get_ipython()`-like global handle, Comm constructor can't do the same magic as the IPython one.
I think this is ready to go, if anyone wants to have a last look. |
+1 to merging. |
Woohoo! Great work! |
Awesome! On Thu, Oct 24, 2013 at 12:55 PM, Jason Grout [email protected]:
Brian E. Granger |
Great. Thank you. |
Fantastic job, guys. Very, very happy about this. |
@minrk in this, (I should have seen it, sorry) |
comm merging renamed object_info_request to object_info
Must have been mixed up as part of the rebase, I know I tested tooltips. It was wrong to use |
IPEP 21: widget messages
comm merging renamed object_info_request to object_info
IPEP 21 has full description of the proposal.
This is just the basic communication tube, through which widgets might communicate.
It's pretty basic, but it seems to work reasonably well.
Some example use cases for the Comms implemented here: http://nbviewer.ipython.org/6547109
This also refactors callbacks in a clearer way, allowing callback cleanup since widget messages dramatically exacerbate #2524.
closes #2524.