##// END OF EJS Templates
Add an optional metadata attribute to all messages and add a session-level default metadata attribute.
Jason Grout -
Show More
@@ -220,19 +220,19 b' var IPython = (function (IPython) {'
220 // 'set_next_input': set_next_input_callback
220 // 'set_next_input': set_next_input_callback
221 // }
221 // }
222 //
222 //
223 // The execute_reply_callback will be passed the content object of the execute_reply
223 // The execute_reply_callback will be passed the content and metadata objects of the execute_reply
224 // message documented here:
224 // message documented here:
225 //
225 //
226 // http://ipython.org/ipython-doc/dev/development/messaging.html#execute
226 // http://ipython.org/ipython-doc/dev/development/messaging.html#execute
227 //
227 //
228 // The output_callback will be passed msg_type ('stream','display_data','pyout','pyerr')
228 // The output_callback will be passed msg_type ('stream','display_data','pyout','pyerr')
229 // of the output and the content and header objects of the PUB/SUB channel that contains the
229 // of the output and the content and metadata objects of the PUB/SUB channel that contains the
230 // output:
230 // output:
231 //
231 //
232 // http://ipython.org/ipython-doc/dev/development/messaging.html#messages-on-the-pub-sub-socket
232 // http://ipython.org/ipython-doc/dev/development/messaging.html#messages-on-the-pub-sub-socket
233 //
233 //
234 // The clear_output_callback will be passed a content object that contains
234 // The clear_output_callback will be passed a content object that contains
235 // stdout, stderr and other fields that are booleans, as well as the header object.
235 // stdout, stderr and other fields that are booleans, as well as the metadata object.
236 //
236 //
237 // The set_next_input_callback will be passed the text that should become the next
237 // The set_next_input_callback will be passed the text that should become the next
238 // input cell.
238 // input cell.
@@ -313,12 +313,13 b' var IPython = (function (IPython) {'
313 reply = $.parseJSON(e.data);
313 reply = $.parseJSON(e.data);
314 var header = reply.header;
314 var header = reply.header;
315 var content = reply.content;
315 var content = reply.content;
316 var metadata = reply.metadata;
316 var msg_type = header.msg_type;
317 var msg_type = header.msg_type;
317 var callbacks = this.get_callbacks_for_msg(reply.parent_header.msg_id);
318 var callbacks = this.get_callbacks_for_msg(reply.parent_header.msg_id);
318 if (callbacks !== undefined) {
319 if (callbacks !== undefined) {
319 var cb = callbacks[msg_type];
320 var cb = callbacks[msg_type];
320 if (cb !== undefined) {
321 if (cb !== undefined) {
321 cb(content);
322 cb(content, metadata);
322 }
323 }
323 };
324 };
324
325
@@ -347,10 +348,10 b' var IPython = (function (IPython) {'
347
348
348
349
349 Kernel.prototype._handle_iopub_reply = function (e) {
350 Kernel.prototype._handle_iopub_reply = function (e) {
350 reply = $.parseJSON(e.data);
351 var reply = $.parseJSON(e.data);
351 var content = reply.content;
352 var content = reply.content;
352 var msg_type = reply.header.msg_type;
353 var msg_type = reply.header.msg_type;
353 var header = reply.header;
354 var metadata = reply.metadata;
354 var callbacks = this.get_callbacks_for_msg(reply.parent_header.msg_id);
355 var callbacks = this.get_callbacks_for_msg(reply.parent_header.msg_id);
355 if (msg_type !== 'status' && callbacks === undefined) {
356 if (msg_type !== 'status' && callbacks === undefined) {
356 // Message not from one of this notebook's cells and there are no
357 // Message not from one of this notebook's cells and there are no
@@ -361,7 +362,7 b' var IPython = (function (IPython) {'
361 if (output_types.indexOf(msg_type) >= 0) {
362 if (output_types.indexOf(msg_type) >= 0) {
362 var cb = callbacks['output'];
363 var cb = callbacks['output'];
363 if (cb !== undefined) {
364 if (cb !== undefined) {
364 cb(msg_type, content, header);
365 cb(msg_type, content, metadata);
365 }
366 }
366 } else if (msg_type === 'status') {
367 } else if (msg_type === 'status') {
367 if (content.execution_state === 'busy') {
368 if (content.execution_state === 'busy') {
@@ -375,7 +376,7 b' var IPython = (function (IPython) {'
375 } else if (msg_type === 'clear_output') {
376 } else if (msg_type === 'clear_output') {
376 var cb = callbacks['clear_output'];
377 var cb = callbacks['clear_output'];
377 if (cb !== undefined) {
378 if (cb !== undefined) {
378 cb(content, header);
379 cb(content, metadata);
379 }
380 }
380 };
381 };
381 };
382 };
@@ -292,8 +292,8 b' class Session(Configurable):'
292 username = Unicode(os.environ.get('USER',u'username'), config=True,
292 username = Unicode(os.environ.get('USER',u'username'), config=True,
293 help="""Username for the Session. Default is your system username.""")
293 help="""Username for the Session. Default is your system username.""")
294
294
295 subheader = Dict({}, config=True,
295 metadata = Dict({}, config=True,
296 help="""Subheader dictionary, which serves as the default subheader fields for each message.""")
296 help="""Metadata dictionary, which serves as the default top-level metadata dict for each message.""")
297
297
298 # message signature related traits:
298 # message signature related traits:
299
299
@@ -405,7 +405,7 b' class Session(Configurable):'
405 def msg_header(self, msg_type):
405 def msg_header(self, msg_type):
406 return msg_header(self.msg_id, msg_type, self.username, self.session)
406 return msg_header(self.msg_id, msg_type, self.username, self.session)
407
407
408 def msg(self, msg_type, content=None, parent=None, subheader=None, header=None):
408 def msg(self, msg_type, content=None, parent=None, subheader=None, header=None, metadata=None):
409 """Return the nested message dict.
409 """Return the nested message dict.
410
410
411 This format is different from what is sent over the wire. The
411 This format is different from what is sent over the wire. The
@@ -415,13 +415,17 b' class Session(Configurable):'
415 msg = {}
415 msg = {}
416 header = self.msg_header(msg_type) if header is None else header
416 header = self.msg_header(msg_type) if header is None else header
417 msg['header'] = header
417 msg['header'] = header
418 if subheader is not None:
419 msg['header'].update(subheader)
418 msg['msg_id'] = header['msg_id']
420 msg['msg_id'] = header['msg_id']
419 msg['msg_type'] = header['msg_type']
421 msg['msg_type'] = header['msg_type']
420 msg['parent_header'] = {} if parent is None else extract_header(parent)
422 msg['parent_header'] = {} if parent is None else extract_header(parent)
421 msg['content'] = {} if content is None else content
423 msg['content'] = {} if content is None else content
422 msg['header'].update(self.subheader)
424 metadata_dict = self.metadata.copy()
423 if subheader is not None:
425 if metadata is not None:
424 msg['header'].update(subheader)
426 metadata_dict.update(metadata)
427 if metadata_dict:
428 msg['metadata'] = metadata_dict
425 return msg
429 return msg
426
430
427 def sign(self, msg_list):
431 def sign(self, msg_list):
@@ -496,7 +500,7 b' class Session(Configurable):'
496 return to_send
500 return to_send
497
501
498 def send(self, stream, msg_or_type, content=None, parent=None, ident=None,
502 def send(self, stream, msg_or_type, content=None, parent=None, ident=None,
499 buffers=None, subheader=None, track=False, header=None):
503 buffers=None, subheader=None, track=False, header=None, metadata=None):
500 """Build and send a message via stream or socket.
504 """Build and send a message via stream or socket.
501
505
502 The message format used by this function internally is as follows:
506 The message format used by this function internally is as follows:
@@ -520,7 +524,7 b' class Session(Configurable):'
520 content : dict or None
524 content : dict or None
521 The content of the message (ignored if msg_or_type is a message).
525 The content of the message (ignored if msg_or_type is a message).
522 header : dict or None
526 header : dict or None
523 The header dict for the message (ignores if msg_to_type is a message).
527 The header dict for the message (ignored if msg_to_type is a message).
524 parent : Message or dict or None
528 parent : Message or dict or None
525 The parent or parent header describing the parent of this message
529 The parent or parent header describing the parent of this message
526 (ignored if msg_or_type is a message).
530 (ignored if msg_or_type is a message).
@@ -529,11 +533,14 b' class Session(Configurable):'
529 subheader : dict or None
533 subheader : dict or None
530 Extra header keys for this message's header (ignored if msg_or_type
534 Extra header keys for this message's header (ignored if msg_or_type
531 is a message).
535 is a message).
536 metadata : dict or None
537 The metadata describing the message
532 buffers : list or None
538 buffers : list or None
533 The already-serialized buffers to be appended to the message.
539 The already-serialized buffers to be appended to the message.
534 track : bool
540 track : bool
535 Whether to track. Only for use with Sockets, because ZMQStream
541 Whether to track. Only for use with Sockets, because ZMQStream
536 objects cannot track messages.
542 objects cannot track messages.
543
537
544
538 Returns
545 Returns
539 -------
546 -------
@@ -557,7 +564,7 b' class Session(Configurable):'
557 msg = msg_or_type
564 msg = msg_or_type
558 else:
565 else:
559 msg = self.msg(msg_or_type, content=content, parent=parent,
566 msg = self.msg(msg_or_type, content=content, parent=parent,
560 subheader=subheader, header=header)
567 subheader=subheader, header=header, metadata=metadata)
561
568
562 buffers = [] if buffers is None else buffers
569 buffers = [] if buffers is None else buffers
563 to_send = self.serialize(msg, ident)
570 to_send = self.serialize(msg, ident)
@@ -81,7 +81,7 b' representation of all the data, we can communicate with such clients.'
81 General Message Format
81 General Message Format
82 ======================
82 ======================
83
83
84 A message is defined by the following three-dictionary structure::
84 A message is defined by the following four-dictionary structure::
85
85
86 {
86 {
87 # The message header contains a pair of unique identifiers for the
87 # The message header contains a pair of unique identifiers for the
@@ -105,6 +105,9 b' A message is defined by the following three-dictionary structure::'
105 # The actual content of the message must be a dict, whose structure
105 # The actual content of the message must be a dict, whose structure
106 # depends on the message type.
106 # depends on the message type.
107 'content' : dict,
107 'content' : dict,
108
109 # Any metadata associated with the message; this dictionary is optional.
110 'metadata' : dict,
108 }
111 }
109
112
110
113
@@ -127,6 +130,7 b' messages upon deserialization to the following form for convenience::'
127 'msg_type' : str,
130 'msg_type' : str,
128 'parent_header' : dict,
131 'parent_header' : dict,
129 'content' : dict,
132 'content' : dict,
133 'metadata' : dict, # optional
130 }
134 }
131
135
132 All messages sent to or received by any IPython process should have this
136 All messages sent to or received by any IPython process should have this
General Comments 0
You need to be logged in to leave comments. Login now