-
-
Notifications
You must be signed in to change notification settings - Fork 404
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
Add Comms to allow updating plots dynamically #838
Merged
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
cf11743
DimensionedPlot now have access to a renderer instance
philippjfr 0a1f3b6
Added Comms to plot updates dynamically
philippjfr 004eb38
JupyterWidget unpacks the comms msg
philippjfr 0fbab57
Ensured Plot.comms is set
philippjfr f857ace
Switched to hex ids for comms
philippjfr 0c00a57
Comm initializes on first push
philippjfr 24e5228
Refactored widgets to use existing Comms to update plots
philippjfr ad7bf00
Fixed nbagg widget after comms changes
philippjfr e01e511
Fixes for rerendering matplotlib widgets
philippjfr e8afac3
Fix for embedded bokeh widgets
philippjfr 9316a07
JupyterComms now opened on the frontend
philippjfr ccf3edd
Renamed Rendererer.patch to Renderer.diff
philippjfr 118af7b
Renamed NbAggCommSocket
philippjfr 17f3760
Added JupyterComms for uni- and bi-directional communication
philippjfr a59dc85
Small fix for Plot pprint
philippjfr f3e8bd4
Renamed SimpleJupyterComm to JupyterPushComm
philippjfr f2892cb
Small fix for plot instantiation tests
philippjfr 3295c92
Improved docstrings for msg_handlers
philippjfr 4b6d483
Made Comm.decode a class method
philippjfr 1eaded6
Added basic Comm unit tests
philippjfr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
import uuid | ||
|
||
import param | ||
from ipykernel.comm import Comm as IPyComm | ||
from IPython import get_ipython | ||
|
||
|
||
class Comm(param.Parameterized): | ||
""" | ||
Comm encompasses any uni- or bi-directional connection between | ||
a python process and a frontend allowing passing of messages | ||
between the two. A Comms class must implement methods | ||
send data and handle received message events. | ||
|
||
If the Comm has to be set up on the frontend a template to | ||
handle the creation of the comms channel along with a message | ||
handler to process incoming messages must be supplied. | ||
|
||
The template must accept three arguments: | ||
|
||
* comms_target - A unique id to register to register as the comms target. | ||
* msg_handler - JS code that processes messages sent to the frontend. | ||
* init_frame - The initial frame to render on the frontend. | ||
""" | ||
|
||
template = '' | ||
|
||
def __init__(self, plot, target=None, on_msg=None): | ||
""" | ||
Initializes a Comms object | ||
""" | ||
self.target = target if target else uuid.uuid4().hex | ||
self._plot = plot | ||
self._on_msg = on_msg | ||
self._comm = None | ||
|
||
|
||
def init(self, on_msg=None): | ||
""" | ||
Initializes comms channel. | ||
""" | ||
|
||
|
||
def send(self, data): | ||
""" | ||
Sends data to the frontend | ||
""" | ||
|
||
|
||
def decode(self, msg): | ||
""" | ||
Decode incoming message, e.g. by parsing json. | ||
""" | ||
return msg | ||
|
||
|
||
@property | ||
def comm(self): | ||
if not self._comm: | ||
raise ValueError('Comm has not been initialized') | ||
return self._comm | ||
|
||
|
||
def _handle_msg(self, msg): | ||
""" | ||
Decode received message before passing it to on_msg callback | ||
if it has been defined. | ||
""" | ||
if self._on_msg: | ||
self._on_msg(self.decode(msg)) | ||
|
||
|
||
class JupyterPushComm(Comm): | ||
""" | ||
JupyterPushComm provides a Comm for simple unidirectional | ||
communication from the python process to a frontend. The | ||
Comm is opened before the first event is sent to the frontend. | ||
""" | ||
|
||
template = """ | ||
<script> | ||
function msg_handler(msg) {{ | ||
var data = msg.content.data; | ||
{msg_handler} | ||
}} | ||
|
||
if ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel !== undefined)) {{ | ||
comm_manager = Jupyter.notebook.kernel.comm_manager; | ||
comm_manager.register_target("{comms_target}", register_handler); | ||
}} | ||
</script> | ||
|
||
<div id="{comms_target}"> | ||
{init_frame} | ||
</div> | ||
""" | ||
|
||
def init(self): | ||
if self._comm: | ||
return | ||
self._comm = IPyComm(target_name=self.target, data={}) | ||
self._comm.on_msg(self._handle_msg) | ||
|
||
|
||
def decode(self, msg): | ||
return msg['content']['data'] | ||
|
||
|
||
def send(self, data): | ||
""" | ||
Pushes data across comm socket. | ||
""" | ||
if not self._comm: | ||
self.init() | ||
self.comm.send(data) | ||
|
||
|
||
|
||
class JupyterComm(Comm): | ||
""" | ||
JupyterComm allows for a bidirectional communication channel | ||
inside the Jupyter notebook. The JupyterComm will register | ||
a comm target on the IPython kernel comm manager, which will then | ||
be opened by the templated code on the frontend. | ||
""" | ||
|
||
template = """ | ||
<script> | ||
function msg_handler(msg) {{ | ||
var data = msg.content.data; | ||
{msg_handler} | ||
}} | ||
|
||
if ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel !== undefined)) {{ | ||
var comm_manager = Jupyter.notebook.kernel.comm_manager; | ||
comm = comm_manager.new_comm("{comms_target}", {{}}, {{}}, {{}}, "{comms_target}"); | ||
comm.on_msg(msg_handler); | ||
}} | ||
</script> | ||
|
||
<div id="{comms_target}"> | ||
{init_frame} | ||
</div> | ||
""" | ||
|
||
def __init__(self, plot, target=None, on_msg=None): | ||
""" | ||
Initializes a Comms object | ||
""" | ||
super(JupyterComm, self).__init__(plot, target, on_msg) | ||
self.manager = get_ipython().kernel.comm_manager | ||
self.manager.register_target(self.target, self._handle_open) | ||
|
||
|
||
def _handle_open(self, comm, msg): | ||
self._comm = comm | ||
self._comm.on_msg(self._handle_msg) | ||
|
||
|
||
def send(self, data): | ||
""" | ||
Pushes data across comm socket. | ||
""" | ||
self.comm.send(data) | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
How about calling it
JupyterPushComm
? From the sound of it, we may not need it in future one bokeh works with bi-directional comms.