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