##// END OF EJS Templates
Merge pull request #3756 from minrk/wiredoc...
Min RK -
r11721:42034aaf merge
parent child Browse files
Show More
@@ -265,6 +265,8 b' class IPythonConsoleApp(Configurable):'
265 setattr(self, name, cfg[name])
265 setattr(self, name, cfg[name])
266 if 'key' in cfg:
266 if 'key' in cfg:
267 self.config.Session.key = str_to_bytes(cfg['key'])
267 self.config.Session.key = str_to_bytes(cfg['key'])
268 if 'signature_scheme' in cfg:
269 self.config.Session.signature_scheme = cfg['signature_scheme']
268
270
269 def init_ssh(self):
271 def init_ssh(self):
270 """set up ssh tunnels, if needed."""
272 """set up ssh tunnels, if needed."""
@@ -50,7 +50,9 b' from IPython.utils.traitlets import ('
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51
51
52 def write_connection_file(fname=None, shell_port=0, iopub_port=0, stdin_port=0, hb_port=0,
52 def write_connection_file(fname=None, shell_port=0, iopub_port=0, stdin_port=0, hb_port=0,
53 control_port=0, ip=LOCALHOST, key=b'', transport='tcp'):
53 control_port=0, ip=LOCALHOST, key=b'', transport='tcp',
54 signature_scheme='hmac-sha256',
55 ):
54 """Generates a JSON config file, including the selection of random ports.
56 """Generates a JSON config file, including the selection of random ports.
55
57
56 Parameters
58 Parameters
@@ -78,7 +80,15 b' def write_connection_file(fname=None, shell_port=0, iopub_port=0, stdin_port=0, '
78 The ip address the kernel will bind to.
80 The ip address the kernel will bind to.
79
81
80 key : str, optional
82 key : str, optional
81 The Session key used for HMAC authentication.
83 The Session key used for message authentication.
84
85 signature_scheme : str, optional
86 The scheme used for message authentication.
87 This has the form 'digest-hash', where 'digest'
88 is the scheme used for digests, and 'hash' is the name of the hash function
89 used by the digest scheme.
90 Currently, 'hmac' is the only supported digest scheme,
91 and 'sha256' is the default hash function.
82
92
83 """
93 """
84 # default to temporary connector file
94 # default to temporary connector file
@@ -129,6 +139,7 b' def write_connection_file(fname=None, shell_port=0, iopub_port=0, stdin_port=0, '
129 cfg['ip'] = ip
139 cfg['ip'] = ip
130 cfg['key'] = bytes_to_str(key)
140 cfg['key'] = bytes_to_str(key)
131 cfg['transport'] = transport
141 cfg['transport'] = transport
142 cfg['signature_scheme'] = signature_scheme
132
143
133 with open(fname, 'w') as f:
144 with open(fname, 'w') as f:
134 f.write(json.dumps(cfg, indent=2))
145 f.write(json.dumps(cfg, indent=2))
@@ -380,6 +391,7 b' class ConnectionFileMixin(HasTraits):'
380 _connection_file_written = Bool(False)
391 _connection_file_written = Bool(False)
381
392
382 transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True)
393 transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True)
394 signature_scheme = Unicode('')
383
395
384 ip = Unicode(LOCALHOST, config=True,
396 ip = Unicode(LOCALHOST, config=True,
385 help="""Set the kernel\'s IP address [default localhost].
397 help="""Set the kernel\'s IP address [default localhost].
@@ -427,6 +439,7 b' class ConnectionFileMixin(HasTraits):'
427 stdin_port=self.stdin_port,
439 stdin_port=self.stdin_port,
428 hb_port=self.hb_port,
440 hb_port=self.hb_port,
429 control_port=self.control_port,
441 control_port=self.control_port,
442 signature_scheme=self.signature_scheme,
430 )
443 )
431
444
432 def cleanup_connection_file(self):
445 def cleanup_connection_file(self):
@@ -463,6 +476,7 b' class ConnectionFileMixin(HasTraits):'
463 stdin_port=self.stdin_port, iopub_port=self.iopub_port,
476 stdin_port=self.stdin_port, iopub_port=self.iopub_port,
464 shell_port=self.shell_port, hb_port=self.hb_port,
477 shell_port=self.shell_port, hb_port=self.hb_port,
465 control_port=self.control_port,
478 control_port=self.control_port,
479 signature_scheme=self.signature_scheme,
466 )
480 )
467 # write_connection_file also sets default ports:
481 # write_connection_file also sets default ports:
468 for name in port_names:
482 for name in port_names:
@@ -479,7 +493,10 b' class ConnectionFileMixin(HasTraits):'
479 self.ip = cfg['ip']
493 self.ip = cfg['ip']
480 for name in port_names:
494 for name in port_names:
481 setattr(self, name, cfg[name])
495 setattr(self, name, cfg[name])
482 self.session.key = str_to_bytes(cfg['key'])
496 if 'key' in cfg:
497 self.session.key = str_to_bytes(cfg['key'])
498 if cfg.get('signature_scheme'):
499 self.session.signature_scheme = cfg['signature_scheme']
483
500
484 #--------------------------------------------------------------------------
501 #--------------------------------------------------------------------------
485 # Creating connected sockets
502 # Creating connected sockets
@@ -10,7 +10,7 b' from session import extract_header, Session'
10 class ZMQDisplayHook(object):
10 class ZMQDisplayHook(object):
11 """A simple displayhook that publishes the object's repr over a ZeroMQ
11 """A simple displayhook that publishes the object's repr over a ZeroMQ
12 socket."""
12 socket."""
13 topic=None
13 topic=b'pyout'
14
14
15 def __init__(self, session, pub_socket):
15 def __init__(self, session, pub_socket):
16 self.session = session
16 self.session = session
@@ -44,6 +44,7 b' class OutStream(object):'
44 self.session = session
44 self.session = session
45 self.pub_socket = pub_socket
45 self.pub_socket = pub_socket
46 self.name = name
46 self.name = name
47 self.topic = b'stream.' + py3compat.cast_bytes(name)
47 self.parent_header = {}
48 self.parent_header = {}
48 self._new_buffer()
49 self._new_buffer()
49 self._buffer_lock = threading.Lock()
50 self._buffer_lock = threading.Lock()
@@ -24,6 +24,7 b' Authors:'
24 # Imports
24 # Imports
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 import hashlib
27 import hmac
28 import hmac
28 import logging
29 import logging
29 import os
30 import os
@@ -50,7 +51,9 b' from IPython.utils.importstring import import_item'
50 from IPython.utils.jsonutil import extract_dates, squash_dates, date_default
51 from IPython.utils.jsonutil import extract_dates, squash_dates, date_default
51 from IPython.utils.py3compat import str_to_bytes, str_to_unicode
52 from IPython.utils.py3compat import str_to_bytes, str_to_unicode
52 from IPython.utils.traitlets import (CBytes, Unicode, Bool, Any, Instance, Set,
53 from IPython.utils.traitlets import (CBytes, Unicode, Bool, Any, Instance, Set,
53 DottedObjectName, CUnicode, Dict, Integer)
54 DottedObjectName, CUnicode, Dict, Integer,
55 TraitError,
56 )
54 from IPython.kernel.zmq.serialize import MAX_ITEMS, MAX_BYTES
57 from IPython.kernel.zmq.serialize import MAX_ITEMS, MAX_BYTES
55
58
56 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
@@ -308,10 +311,26 b' class Session(Configurable):'
308 help="""execution key, for extra authentication.""")
311 help="""execution key, for extra authentication.""")
309 def _key_changed(self, name, old, new):
312 def _key_changed(self, name, old, new):
310 if new:
313 if new:
311 self.auth = hmac.HMAC(new)
314 self.auth = hmac.HMAC(new, digestmod=self.digest_mod)
312 else:
315 else:
313 self.auth = None
316 self.auth = None
314
317
318 signature_scheme = Unicode('hmac-sha256', config=True,
319 help="""The digest scheme used to construct the message signatures.
320 Must have the form 'hmac-HASH'.""")
321 def _signature_scheme_changed(self, name, old, new):
322 if not new.startswith('hmac-'):
323 raise TraitError("signature_scheme must start with 'hmac-', got %r" % new)
324 hash_name = new.split('-', 1)[1]
325 try:
326 self.digest_mod = getattr(hashlib, hash_name)
327 except AttributeError:
328 raise TraitError("hashlib has no such attribute: %s" % hash_name)
329
330 digest_mod = Any()
331 def _digest_mod_default(self):
332 return hashlib.sha256
333
315 auth = Instance(hmac.HMAC)
334 auth = Instance(hmac.HMAC)
316
335
317 digest_history = Set()
336 digest_history = Set()
@@ -387,6 +406,11 b' class Session(Configurable):'
387 key : bytes
406 key : bytes
388 The key used to initialize an HMAC signature. If unset, messages
407 The key used to initialize an HMAC signature. If unset, messages
389 will not be signed or checked.
408 will not be signed or checked.
409 signature_scheme : str
410 The message digest scheme. Currently must be of the form 'hmac-HASH',
411 where 'HASH' is a hashing function available in Python's hashlib.
412 The default is 'hmac-sha256'.
413 This is ignored if 'key' is empty.
390 keyfile : filepath
414 keyfile : filepath
391 The file containing a key. If this is set, `key` will be
415 The file containing a key. If this is set, `key` will be
392 initialized to the contents of the file.
416 initialized to the contents of the file.
@@ -61,7 +61,7 b' class ZMQDisplayPublisher(DisplayPublisher):'
61 session = Instance(Session)
61 session = Instance(Session)
62 pub_socket = Instance(SocketABC)
62 pub_socket = Instance(SocketABC)
63 parent_header = Dict({})
63 parent_header = Dict({})
64 topic = CBytes(b'displaypub')
64 topic = CBytes(b'display_data')
65
65
66 def set_parent(self, parent):
66 def set_parent(self, parent):
67 """Set the parent for outbound messages."""
67 """Set the parent for outbound messages."""
@@ -251,7 +251,7 b' class IPControllerApp(BaseParallelApplication):'
251 ecfg = json.loads(f.read())
251 ecfg = json.loads(f.read())
252
252
253 # json gives unicode, Session.key wants bytes
253 # json gives unicode, Session.key wants bytes
254 c.Session.key = ecfg['exec_key'].encode('ascii')
254 c.Session.key = ecfg['key'].encode('ascii')
255
255
256 xport,ip = ecfg['interface'].split('://')
256 xport,ip = ecfg['interface'].split('://')
257
257
@@ -269,7 +269,7 b' class IPControllerApp(BaseParallelApplication):'
269 with open(fname) as f:
269 with open(fname) as f:
270 ccfg = json.loads(f.read())
270 ccfg = json.loads(f.read())
271
271
272 for key in ('exec_key', 'registration', 'pack', 'unpack'):
272 for key in ('key', 'registration', 'pack', 'unpack', 'signature_scheme'):
273 assert ccfg[key] == ecfg[key], "mismatch between engine and client info: %r" % key
273 assert ccfg[key] == ecfg[key], "mismatch between engine and client info: %r" % key
274
274
275 xport,addr = ccfg['interface'].split('://')
275 xport,addr = ccfg['interface'].split('://')
@@ -338,10 +338,11 b' class IPControllerApp(BaseParallelApplication):'
338 # save to new json config files
338 # save to new json config files
339 f = self.factory
339 f = self.factory
340 base = {
340 base = {
341 'exec_key' : f.session.key.decode('ascii'),
341 'key' : f.session.key.decode('ascii'),
342 'location' : self.location,
342 'location' : self.location,
343 'pack' : f.session.packer,
343 'pack' : f.session.packer,
344 'unpack' : f.session.unpacker,
344 'unpack' : f.session.unpacker,
345 'signature_scheme' : f.session.signature_scheme,
345 }
346 }
346
347
347 cdict = {'ssh' : self.ssh_server}
348 cdict = {'ssh' : self.ssh_server}
@@ -227,9 +227,10 b' class IPEngineApp(BaseParallelApplication):'
227 ip = disambiguate_ip_address(ip, location)
227 ip = disambiguate_ip_address(ip, location)
228 d['interface'] = '%s://%s' % (proto, ip)
228 d['interface'] = '%s://%s' % (proto, ip)
229
229
230 # DO NOT allow override of basic URLs, serialization, or exec_key
230 # DO NOT allow override of basic URLs, serialization, or key
231 # JSON file takes top priority there
231 # JSON file takes top priority there
232 config.Session.key = cast_bytes(d['exec_key'])
232 config.Session.key = cast_bytes(d['key'])
233 config.Session.signature_scheme = d['signature_scheme']
233
234
234 config.EngineFactory.url = d['interface'] + ':%i' % d['registration']
235 config.EngineFactory.url = d['interface'] + ':%i' % d['registration']
235
236
@@ -462,7 +462,8 b' class Client(HasTraits):'
462 # configure and construct the session
462 # configure and construct the session
463 extra_args['packer'] = cfg['pack']
463 extra_args['packer'] = cfg['pack']
464 extra_args['unpacker'] = cfg['unpack']
464 extra_args['unpacker'] = cfg['unpack']
465 extra_args['key'] = cast_bytes(cfg['exec_key'])
465 extra_args['key'] = cast_bytes(cfg['key'])
466 extra_args['signature_scheme'] = cfg['signature_scheme']
466
467
467 self.session = Session(**extra_args)
468 self.session = Session(**extra_args)
468
469
@@ -93,7 +93,7 b' A message is defined by the following four-dictionary structure::'
93 'header' : {
93 'header' : {
94 'msg_id' : uuid,
94 'msg_id' : uuid,
95 'username' : str,
95 'username' : str,
96 'session' : uuid
96 'session' : uuid,
97 # All recognized message type strings are listed below.
97 # All recognized message type strings are listed below.
98 'msg_type' : str,
98 'msg_type' : str,
99 },
99 },
@@ -101,16 +101,101 b' A message is defined by the following four-dictionary structure::'
101 # In a chain of messages, the header from the parent is copied so that
101 # In a chain of messages, the header from the parent is copied so that
102 # clients can track where messages come from.
102 # clients can track where messages come from.
103 'parent_header' : dict,
103 'parent_header' : dict,
104
105 # The actual content of the message must be a dict, whose structure
106 # depends on the message type.
107 'content' : dict,
108
104
109 # Any metadata associated with the message.
105 # Any metadata associated with the message.
110 'metadata' : dict,
106 'metadata' : dict,
107
108 # The actual content of the message must be a dict, whose structure
109 # depends on the message type.
110 'content' : dict,
111 }
111 }
112
112
113
113 The Wire Protocol
114 =================
115
116
117 This message format exists at a high level,
118 but does not describe the actual *implementation* at the wire level in zeromq.
119 The canonical implementation of the message spec is our :class:`~IPython.kernel.zmq.session.Session` class.
120
121 .. note::
122
123 This section should only be relevant to non-Python consumers of the protocol.
124 Python consumers should simply import and use IPython's own implementation of the wire protocol
125 in the :class:`IPython.kernel.zmq.session.Session` object.
126
127 Every message is serialized to a sequence of at least six blobs of bytes:
128
129 .. sourcecode:: python
130
131 [
132 b'u-u-i-d', # zmq identity(ies)
133 b'<IDS|MSG>', # delimiter
134 b'baddad42', # HMAC signature
135 b'{header}', # serialized header dict
136 b'{parent_header}', # serialized parent header dict
137 b'{metadata}', # serialized metadata dict
138 b'{content}, # serialized content dict
139 b'blob', # extra raw data buffer(s)
140 ...
141 ]
142
143 The front of the message is the ZeroMQ routing prefix,
144 which can be zero or more socket identities.
145 This is every piece of the message prior to the delimiter key ``<IDS|MSG>``.
146 In the case of IOPub, there should be just one prefix component,
147 which is the topic for IOPub subscribers, e.g. ``pyout``, ``display_data``.
148
149 .. note::
150
151 In most cases, the IOPub topics are irrelevant and completely ignored,
152 because frontends just subscribe to all topics.
153 The convention used in the IPython kernel is to use the msg_type as the topic,
154 and possibly extra information about the message, e.g. ``pyout`` or ``stream.stdout``
155
156 After the delimiter is the `HMAC`_ signature of the message, used for authentication.
157 If authentication is disabled, this should be an empty string.
158 By default, the hashing function used for computing these signatures is sha256.
159
160 .. _HMAC: http://en.wikipedia.org/wiki/HMAC
161
162 .. note::
163
164 To disable authentication and signature checking,
165 set the `key` field of a connection file to an empty string.
166
167 The signature is the HMAC hex digest of the concatenation of:
168
169 - A shared key (typically the ``key`` field of a connection file)
170 - The serialized header dict
171 - The serialized parent header dict
172 - The serialized metadata dict
173 - The serialized content dict
174
175 In Python, this is implemented via:
176
177 .. sourcecode:: python
178
179 # once:
180 digester = HMAC(key, digestmod=hashlib.sha256)
181
182 # for each message
183 d = digester.copy()
184 for serialized_dict in (header, parent, metadata, content):
185 d.update(serialized_dict)
186 signature = d.hexdigest()
187
188 After the signature is the actual message, always in four frames of bytes.
189 The four dictionaries that compose a message are serialized separately,
190 in the order of header, parent header, metadata, and content.
191 These can be serialized by any function that turns a dict into bytes.
192 The default and most common serialization is JSON, but msgpack and pickle
193 are common alternatives.
194
195 After the serialized dicts are zero to many raw data buffers,
196 which can be used by message types that support binary data (mainly apply and data_pub).
197
198
114 Python functional API
199 Python functional API
115 =====================
200 =====================
116
201
@@ -388,73 +473,7 b" When status is 'error', the following extra fields are present::"
388 When status is 'abort', there are for now no additional data fields. This
473 When status is 'abort', there are for now no additional data fields. This
389 happens when the kernel was interrupted by a signal.
474 happens when the kernel was interrupted by a signal.
390
475
391 Kernel attribute access
392 -----------------------
393
394 .. warning::
395
396 This part of the messaging spec is not actually implemented in the kernel
397 yet.
398
399 While this protocol does not specify full RPC access to arbitrary methods of
400 the kernel object, the kernel does allow read (and in some cases write) access
401 to certain attributes.
402
403 The policy for which attributes can be read is: any attribute of the kernel, or
404 its sub-objects, that belongs to a :class:`Configurable` object and has been
405 declared at the class-level with Traits validation, is in principle accessible
406 as long as its name does not begin with a leading underscore. The attribute
407 itself will have metadata indicating whether it allows remote read and/or write
408 access. The message spec follows for attribute read and write requests.
409
410 Message type: ``getattr_request``::
411
412 content = {
413 # The (possibly dotted) name of the attribute
414 'name' : str,
415 }
416
476
417 When a ``getattr_request`` fails, there are two possible error types:
418
419 - AttributeError: this type of error was raised when trying to access the
420 given name by the kernel itself. This means that the attribute likely
421 doesn't exist.
422
423 - AccessError: the attribute exists but its value is not readable remotely.
424
425
426 Message type: ``getattr_reply``::
427
428 content = {
429 # One of ['ok', 'AttributeError', 'AccessError'].
430 'status' : str,
431 # If status is 'ok', a JSON object.
432 'value' : object,
433 }
434
435 Message type: ``setattr_request``::
436
437 content = {
438 # The (possibly dotted) name of the attribute
439 'name' : str,
440
441 # A JSON-encoded object, that will be validated by the Traits
442 # information in the kernel
443 'value' : object,
444 }
445
446 When a ``setattr_request`` fails, there are also two possible error types with
447 similar meanings as those of the ``getattr_request`` case, but for writing.
448
449 Message type: ``setattr_reply``::
450
451 content = {
452 # One of ['ok', 'AttributeError', 'AccessError'].
453 'status' : str,
454 }
455
456
457
458 Object information
477 Object information
459 ------------------
478 ------------------
460
479
@@ -469,12 +488,12 b' Message type: ``object_info_request``::'
469
488
470 content = {
489 content = {
471 # The (possibly dotted) name of the object to be searched in all
490 # The (possibly dotted) name of the object to be searched in all
472 # relevant namespaces
491 # relevant namespaces
473 'name' : str,
492 'oname' : str,
474
493
475 # The level of detail desired. The default (0) is equivalent to typing
494 # The level of detail desired. The default (0) is equivalent to typing
476 # 'x?' at the prompt, 1 is equivalent to 'x??'.
495 # 'x?' at the prompt, 1 is equivalent to 'x??'.
477 'detail_level' : int,
496 'detail_level' : int,
478 }
497 }
479
498
480 The returned information will be a dictionary with keys very similar to the
499 The returned information will be a dictionary with keys very similar to the
@@ -529,16 +548,16 b' Message type: ``object_info_reply``::'
529 # objects, this field is empty.
548 # objects, this field is empty.
530 'argspec' : { # The names of all the arguments
549 'argspec' : { # The names of all the arguments
531 args : list,
550 args : list,
532 # The name of the varargs (*args), if any
551 # The name of the varargs (*args), if any
533 varargs : str,
552 varargs : str,
534 # The name of the varkw (**kw), if any
553 # The name of the varkw (**kw), if any
535 varkw : str,
554 varkw : str,
536 # The values (as strings) of all default arguments. Note
555 # The values (as strings) of all default arguments. Note
537 # that these must be matched *in reverse* with the 'args'
556 # that these must be matched *in reverse* with the 'args'
538 # list above, since the first positional args have no default
557 # list above, since the first positional args have no default
539 # value at all.
558 # value at all.
540 defaults : list,
559 defaults : list,
541 },
560 },
542
561
543 # For instances, provide the constructor signature (the definition of
562 # For instances, provide the constructor signature (the definition of
544 # the __init__ method):
563 # the __init__ method):
@@ -573,30 +592,44 b' Message type: ``complete_request``::'
573
592
574 content = {
593 content = {
575 # The text to be completed, such as 'a.is'
594 # The text to be completed, such as 'a.is'
576 'text' : str,
595 # this may be an empty string if the frontend does not do any lexing,
577
596 # in which case the kernel must figure out the completion
578 # The full line, such as 'print a.is'. This allows completers to
597 # based on 'line' and 'cursor_pos'.
579 # make decisions that may require information about more than just the
598 'text' : str,
580 # current word.
599
581 'line' : str,
600 # The full line, such as 'print a.is'. This allows completers to
582
601 # make decisions that may require information about more than just the
583 # The entire block of text where the line is. This may be useful in the
602 # current word.
584 # case of multiline completions where more context may be needed. Note: if
603 'line' : str,
585 # in practice this field proves unnecessary, remove it to lighten the
604
586 # messages.
605 # The entire block of text where the line is. This may be useful in the
606 # case of multiline completions where more context may be needed. Note: if
607 # in practice this field proves unnecessary, remove it to lighten the
608 # messages.
587
609
588 'block' : str,
610 'block' : str or null/None,
589
611
590 # The position of the cursor where the user hit 'TAB' on the line.
612 # The position of the cursor where the user hit 'TAB' on the line.
591 'cursor_pos' : int,
613 'cursor_pos' : int,
592 }
614 }
593
615
594 Message type: ``complete_reply``::
616 Message type: ``complete_reply``::
595
617
596 content = {
618 content = {
597 # The list of all matches to the completion request, such as
619 # The list of all matches to the completion request, such as
598 # ['a.isalnum', 'a.isalpha'] for the above example.
620 # ['a.isalnum', 'a.isalpha'] for the above example.
599 'matches' : list
621 'matches' : list,
622
623 # the substring of the matched text
624 # this is typically the common prefix of the matches,
625 # and the text that is already in the block that would be replaced by the full completion.
626 # This would be 'a.is' in the above example.
627 'text' : str,
628
629 # status should be 'ok' unless an exception was raised during the request,
630 # in which case it should be 'error', along with the usual error message content
631 # in other messages.
632 'status' : 'ok'
600 }
633 }
601
634
602
635
@@ -671,21 +704,21 b' Message type: ``connect_request``::'
671 Message type: ``connect_reply``::
704 Message type: ``connect_reply``::
672
705
673 content = {
706 content = {
674 'shell_port' : int # The port the shell ROUTER socket is listening on.
707 'shell_port' : int, # The port the shell ROUTER socket is listening on.
675 'iopub_port' : int # The port the PUB socket is listening on.
708 'iopub_port' : int, # The port the PUB socket is listening on.
676 'stdin_port' : int # The port the stdin ROUTER socket is listening on.
709 'stdin_port' : int, # The port the stdin ROUTER socket is listening on.
677 'hb_port' : int # The port the heartbeat socket is listening on.
710 'hb_port' : int, # The port the heartbeat socket is listening on.
678 }
711 }
679
712
680
713
681 Kernel info
714 Kernel info
682 -----------
715 -----------
683
716
684 If a client needs to know what protocol the kernel supports, it can
717 If a client needs to know information about the kernel, it can
685 ask version number of the messaging protocol supported by the kernel.
718 make a request of the kernel's information.
686 This message can be used to fetch other core information of the
719 This message can be used to fetch core information of the
687 kernel, including language (e.g., Python), language version number and
720 kernel, including language (e.g., Python), language version number and
688 IPython version number.
721 IPython version number, and the IPython message spec version number.
689
722
690 Message type: ``kernel_info_request``::
723 Message type: ``kernel_info_request``::
691
724
@@ -741,9 +774,6 b' Upon their own shutdown, client applications will typically execute a last'
741 minute sanity check and forcefully terminate any kernel that is still alive, to
774 minute sanity check and forcefully terminate any kernel that is still alive, to
742 avoid leaving stray processes in the user's machine.
775 avoid leaving stray processes in the user's machine.
743
776
744 For both shutdown request and reply, there is no actual content that needs to
745 be sent, so the content dict is empty.
746
747 Message type: ``shutdown_request``::
777 Message type: ``shutdown_request``::
748
778
749 content = {
779 content = {
@@ -772,18 +802,13 b' Streams (stdout, stderr, etc)'
772 Message type: ``stream``::
802 Message type: ``stream``::
773
803
774 content = {
804 content = {
775 # The name of the stream is one of 'stdin', 'stdout', 'stderr'
805 # The name of the stream is one of 'stdout', 'stderr'
776 'name' : str,
806 'name' : str,
777
807
778 # The data is an arbitrary string to be written to that stream
808 # The data is an arbitrary string to be written to that stream
779 'data' : str,
809 'data' : str,
780 }
810 }
781
811
782 When a kernel receives a raw_input call, it should also broadcast it on the pub
783 socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
784 to monitor/display kernel interactions and possibly replay them to their user
785 or otherwise expose them.
786
787 Display Data
812 Display Data
788 ------------
813 ------------
789
814
@@ -956,39 +981,6 b' Message type: ``status``::'
956 execution_state : ('busy', 'idle', 'starting')
981 execution_state : ('busy', 'idle', 'starting')
957 }
982 }
958
983
959 Kernel crashes
960 --------------
961
962 When the kernel has an unexpected exception, caught by the last-resort
963 sys.excepthook, we should broadcast the crash handler's output before exiting.
964 This will allow clients to notice that a kernel died, inform the user and
965 propose further actions.
966
967 Message type: ``crash``::
968
969 content = {
970 # Similarly to the 'error' case for execute_reply messages, this will
971 # contain ename, evalue and traceback fields.
972
973 # An additional field with supplementary information such as where to
974 # send the crash message
975 'info' : str,
976 }
977
978
979 Future ideas
980 ------------
981
982 Other potential message types, currently unimplemented, listed below as ideas.
983
984 Message type: ``file``::
985
986 content = {
987 'path' : 'cool.jpg',
988 'mimetype' : str,
989 'data' : str,
990 }
991
992
984
993 Messages on the stdin ROUTER/DEALER sockets
985 Messages on the stdin ROUTER/DEALER sockets
994 ===========================================
986 ===========================================
General Comments 0
You need to be logged in to leave comments. Login now