diff --git a/IPython/html/static/notebook/js/comm.js b/IPython/html/static/notebook/js/comm.js
index 6969ef8..38fafa8 100644
--- a/IPython/html/static/notebook/js/comm.js
+++ b/IPython/html/static/notebook/js/comm.js
@@ -97,35 +97,35 @@ var IPython = (function (IPython) {
//-----------------------------------------------------------------------
var Comm = function (comm_id, target) {
- this.comm_id = comm_id;
+ this.comm_id = comm_id || new IPython.utils.uuid();
this.target = target || 'comm';
this._msg_callback = this._open_callback = this._close_callback = null;
};
// methods for sending messages
- Comm.prototype.open = function (data) {
+ Comm.prototype.open = function (data, callbacks) {
var content = {
comm_id : this.comm_id,
target : this.target,
data : data || {},
};
- this.kernel.send_shell_message("comm_open", content);
+ return this.kernel.send_shell_message("comm_open", content, callbacks);
};
- Comm.prototype.send = function (data) {
+ Comm.prototype.send = function (data, callbacks) {
var content = {
comm_id : this.comm_id,
data : data || {},
};
- return this.kernel.send_shell_message("comm_msg", content);
+ return this.kernel.send_shell_message("comm_msg", content, callbacks);
};
- Comm.prototype.close = function (data) {
+ Comm.prototype.close = function (data, callbacks) {
var content = {
comm_id : this.comm_id,
data : data || {},
};
- return this.kernel.send_shell_message("comm_close", content);
+ return this.kernel.send_shell_message("comm_close", content, callbacks);
};
// methods for registering callbacks for incoming messages
@@ -144,7 +144,7 @@ var IPython = (function (IPython) {
Comm.prototype.on_close = function (callback) {
this._register_callback('close', callback);
};
-
+
// methods for handling incoming messages
Comm.prototype._maybe_callback = function (key, msg) {
@@ -166,7 +166,7 @@ var IPython = (function (IPython) {
IPython.CommManager = CommManager;
IPython.Comm = Comm;
-
+
return IPython;
}(IPython));
diff --git a/IPython/kernel/comm/manager.py b/IPython/kernel/comm/manager.py
index 981dde6..54abae6 100644
--- a/IPython/kernel/comm/manager.py
+++ b/IPython/kernel/comm/manager.py
@@ -11,6 +11,8 @@
# Imports
#-----------------------------------------------------------------------------
+import sys
+
from IPython.config import LoggingConfigurable
from IPython.core.prompts import LazyEvaluate
from IPython.core.getipython import get_ipython
@@ -33,6 +35,23 @@ def lazy_keys(dikt):
return LazyEvaluate(lambda d: list(d.keys()))
+def with_output(method):
+ """method decorator for ensuring output is handled properly in a message handler
+
+ - sets parent header before entering the method
+ - flushes stdout/stderr after
+ """
+ def method_with_output(self, stream, ident, msg):
+ self.shell.set_parent(msg['header'])
+ try:
+ return method(self, stream, ident, msg)
+ finally:
+ sys.stdout.flush()
+ sys.stderr.flush()
+
+ return method_with_output
+
+
class CommManager(LoggingConfigurable):
"""Manager for Comms in the Kernel"""
@@ -97,7 +116,7 @@ class CommManager(LoggingConfigurable):
return comm
# Message handlers
-
+ @with_output
def comm_open(self, stream, ident, msg):
"""Handler for comm_open messages"""
content = msg['content']
@@ -117,6 +136,7 @@ class CommManager(LoggingConfigurable):
comm.handle_open(msg)
self.register_comm(comm)
+ @with_output
def comm_msg(self, stream, ident, msg):
"""Handler for comm_msg messages"""
content = msg['content']
@@ -127,6 +147,7 @@ class CommManager(LoggingConfigurable):
return
comm.handle_msg(msg)
+ @with_output
def comm_close(self, stream, ident, msg):
"""Handler for comm_close messages"""
content = msg['content']