Show More
@@ -38,6 +38,9 b" __version__ = '.'.join(map(str, _ver))" | |||||
38 | version = __version__ # backwards compatibility name |
|
38 | version = __version__ # backwards compatibility name | |
39 | version_info = (_version_major, _version_minor, _version_micro, _version_extra) |
|
39 | version_info = (_version_major, _version_minor, _version_micro, _version_extra) | |
40 |
|
40 | |||
|
41 | # Change this when incrementing the kernel protocol version | |||
|
42 | kernel_protocol_version_info = (4, 0) | |||
|
43 | ||||
41 | description = "IPython: Productive Interactive Computing" |
|
44 | description = "IPython: Productive Interactive Computing" | |
42 |
|
45 | |||
43 | long_description = \ |
|
46 | long_description = \ |
@@ -39,6 +39,7 b' from IPython.config.configurable import Configurable' | |||||
39 | from IPython.config.application import boolean_flag, catch_config_error |
|
39 | from IPython.config.application import boolean_flag, catch_config_error | |
40 | from IPython.core.application import ProfileDir |
|
40 | from IPython.core.application import ProfileDir | |
41 | from IPython.core.error import StdinNotImplementedError |
|
41 | from IPython.core.error import StdinNotImplementedError | |
|
42 | from IPython.core import release | |||
42 | from IPython.core.shellapp import ( |
|
43 | from IPython.core.shellapp import ( | |
43 | InteractiveShellApp, shell_flags, shell_aliases |
|
44 | InteractiveShellApp, shell_flags, shell_aliases | |
44 | ) |
|
45 | ) | |
@@ -61,6 +62,11 b' from zmqshell import ZMQInteractiveShell' | |||||
61 | # Main kernel class |
|
62 | # Main kernel class | |
62 | #----------------------------------------------------------------------------- |
|
63 | #----------------------------------------------------------------------------- | |
63 |
|
64 | |||
|
65 | protocol_version = list(release.kernel_protocol_version_info) | |||
|
66 | ipython_version = list(release.version_info) | |||
|
67 | language_version = list(sys.version_info[:3]) | |||
|
68 | ||||
|
69 | ||||
64 | class Kernel(Configurable): |
|
70 | class Kernel(Configurable): | |
65 |
|
71 | |||
66 | #--------------------------------------------------------------------------- |
|
72 | #--------------------------------------------------------------------------- | |
@@ -156,6 +162,7 b' class Kernel(Configurable):' | |||||
156 | # Build dict of handlers for message types |
|
162 | # Build dict of handlers for message types | |
157 | msg_types = [ 'execute_request', 'complete_request', |
|
163 | msg_types = [ 'execute_request', 'complete_request', | |
158 | 'object_info_request', 'history_request', |
|
164 | 'object_info_request', 'history_request', | |
|
165 | 'kernel_info_request', | |||
159 | 'connect_request', 'shutdown_request', |
|
166 | 'connect_request', 'shutdown_request', | |
160 | 'apply_request', |
|
167 | 'apply_request', | |
161 | ] |
|
168 | ] | |
@@ -509,6 +516,17 b' class Kernel(Configurable):' | |||||
509 | content, parent, ident) |
|
516 | content, parent, ident) | |
510 | self.log.debug("%s", msg) |
|
517 | self.log.debug("%s", msg) | |
511 |
|
518 | |||
|
519 | def kernel_info_request(self, stream, ident, parent): | |||
|
520 | vinfo = { | |||
|
521 | 'protocol_version': protocol_version, | |||
|
522 | 'ipython_version': ipython_version, | |||
|
523 | 'language_version': language_version, | |||
|
524 | 'language': 'python', | |||
|
525 | } | |||
|
526 | msg = self.session.send(stream, 'kernel_info_reply', | |||
|
527 | vinfo, parent, ident) | |||
|
528 | self.log.debug("%s", msg) | |||
|
529 | ||||
512 | def shutdown_request(self, stream, ident, parent): |
|
530 | def shutdown_request(self, stream, ident, parent): | |
513 | self.shell.exit_now = True |
|
531 | self.shell.exit_now = True | |
514 | content = dict(status='ok') |
|
532 | content = dict(status='ok') |
@@ -363,6 +363,12 b' class ShellSocketChannel(ZMQSocketChannel):' | |||||
363 | self._queue_send(msg) |
|
363 | self._queue_send(msg) | |
364 | return msg['header']['msg_id'] |
|
364 | return msg['header']['msg_id'] | |
365 |
|
365 | |||
|
366 | def kernel_info(self): | |||
|
367 | """Request kernel info.""" | |||
|
368 | msg = self.session.msg('kernel_info_request') | |||
|
369 | self._queue_send(msg) | |||
|
370 | return msg['header']['msg_id'] | |||
|
371 | ||||
366 | def shutdown(self, restart=False): |
|
372 | def shutdown(self, restart=False): | |
367 | """Request an immediate kernel shutdown. |
|
373 | """Request an immediate kernel shutdown. | |
368 |
|
374 |
@@ -43,7 +43,6 b' from zmq.utils import jsonapi' | |||||
43 | from zmq.eventloop.ioloop import IOLoop |
|
43 | from zmq.eventloop.ioloop import IOLoop | |
44 | from zmq.eventloop.zmqstream import ZMQStream |
|
44 | from zmq.eventloop.zmqstream import ZMQStream | |
45 |
|
45 | |||
46 | import IPython |
|
|||
47 | from IPython.config.application import Application, boolean_flag |
|
46 | from IPython.config.application import Application, boolean_flag | |
48 | from IPython.config.configurable import Configurable, LoggingConfigurable |
|
47 | from IPython.config.configurable import Configurable, LoggingConfigurable | |
49 | from IPython.utils.importstring import import_item |
|
48 | from IPython.utils.importstring import import_item | |
@@ -75,7 +74,6 b' def squash_unicode(obj):' | |||||
75 | # globals and defaults |
|
74 | # globals and defaults | |
76 | #----------------------------------------------------------------------------- |
|
75 | #----------------------------------------------------------------------------- | |
77 |
|
76 | |||
78 | _version_info_list = list(IPython.version_info) |
|
|||
79 | # ISO8601-ify datetime objects |
|
77 | # ISO8601-ify datetime objects | |
80 | json_packer = lambda obj: jsonapi.dumps(obj, default=date_default) |
|
78 | json_packer = lambda obj: jsonapi.dumps(obj, default=date_default) | |
81 | json_unpacker = lambda s: extract_dates(jsonapi.loads(s)) |
|
79 | json_unpacker = lambda s: extract_dates(jsonapi.loads(s)) | |
@@ -188,7 +186,6 b' class Message(object):' | |||||
188 |
|
186 | |||
189 | def msg_header(msg_id, msg_type, username, session): |
|
187 | def msg_header(msg_id, msg_type, username, session): | |
190 | date = datetime.now() |
|
188 | date = datetime.now() | |
191 | version = _version_info_list |
|
|||
192 | return locals() |
|
189 | return locals() | |
193 |
|
190 | |||
194 | def extract_header(msg_or_header): |
|
191 | def extract_header(msg_or_header): |
@@ -21,7 +21,7 b' from ..blockingkernelmanager import BlockingKernelManager' | |||||
21 | from IPython.testing import decorators as dec |
|
21 | from IPython.testing import decorators as dec | |
22 | from IPython.utils import io |
|
22 | from IPython.utils import io | |
23 | from IPython.utils.traitlets import ( |
|
23 | from IPython.utils.traitlets import ( | |
24 | HasTraits, TraitError, Bool, Unicode, Dict, Integer, List, Enum, |
|
24 | HasTraits, TraitError, Bool, Unicode, Dict, Integer, List, Enum, Any, | |
25 | ) |
|
25 | ) | |
26 |
|
26 | |||
27 | #----------------------------------------------------------------------------- |
|
27 | #----------------------------------------------------------------------------- | |
@@ -83,7 +83,17 b" def execute(code='', **kwargs):" | |||||
83 |
|
83 | |||
84 |
|
84 | |||
85 | class Reference(HasTraits): |
|
85 | class Reference(HasTraits): | |
86 |
|
86 | |||
|
87 | """ | |||
|
88 | Base class for message spec specification testing. | |||
|
89 | ||||
|
90 | This class is the core of the message specification test. The | |||
|
91 | idea is that child classes implement trait attributes for each | |||
|
92 | message keys, so that message keys can be tested against these | |||
|
93 | traits using :meth:`check` method. | |||
|
94 | ||||
|
95 | """ | |||
|
96 | ||||
87 | def check(self, d): |
|
97 | def check(self, d): | |
88 | """validate a dict against our traits""" |
|
98 | """validate a dict against our traits""" | |
89 | for key in self.trait_names(): |
|
99 | for key in self.trait_names(): | |
@@ -185,6 +195,25 b' class CompleteReply(Reference):' | |||||
185 | matches = List(Unicode) |
|
195 | matches = List(Unicode) | |
186 |
|
196 | |||
187 |
|
197 | |||
|
198 | def Version(num, trait=Integer): | |||
|
199 | return List(trait, default_value=[0] * num, minlen=num, maxlen=num) | |||
|
200 | ||||
|
201 | ||||
|
202 | class KernelInfoReply(Reference): | |||
|
203 | ||||
|
204 | protocol_version = Version(2) | |||
|
205 | ipython_version = Version(4, Any) | |||
|
206 | language_version = Version(3) | |||
|
207 | language = Unicode() | |||
|
208 | ||||
|
209 | def _ipython_version_changed(self, name, old, new): | |||
|
210 | for v in new: | |||
|
211 | nt.assert_true( | |||
|
212 | isinstance(v, int) or isinstance(v, basestring), | |||
|
213 | 'expected int or string as version component, got {0!r}' | |||
|
214 | .format(v)) | |||
|
215 | ||||
|
216 | ||||
188 | # IOPub messages |
|
217 | # IOPub messages | |
189 |
|
218 | |||
190 | class PyIn(Reference): |
|
219 | class PyIn(Reference): | |
@@ -226,12 +255,16 b' references = {' | |||||
226 | 'object_info_reply' : OInfoReply(), |
|
255 | 'object_info_reply' : OInfoReply(), | |
227 | 'status' : Status(), |
|
256 | 'status' : Status(), | |
228 | 'complete_reply' : CompleteReply(), |
|
257 | 'complete_reply' : CompleteReply(), | |
|
258 | 'kernel_info_reply': KernelInfoReply(), | |||
229 | 'pyin' : PyIn(), |
|
259 | 'pyin' : PyIn(), | |
230 | 'pyout' : PyOut(), |
|
260 | 'pyout' : PyOut(), | |
231 | 'pyerr' : PyErr(), |
|
261 | 'pyerr' : PyErr(), | |
232 | 'stream' : Stream(), |
|
262 | 'stream' : Stream(), | |
233 | 'display_data' : DisplayData(), |
|
263 | 'display_data' : DisplayData(), | |
234 | } |
|
264 | } | |
|
265 | """ | |||
|
266 | Specifications of `content` part of the reply messages. | |||
|
267 | """ | |||
235 |
|
268 | |||
236 |
|
269 | |||
237 | def validate_message(msg, msg_type=None, parent=None): |
|
270 | def validate_message(msg, msg_type=None, parent=None): | |
@@ -421,6 +454,18 b' def test_complete():' | |||||
421 | yield nt.assert_true(name in matches, "Missing match: %r" % name) |
|
454 | yield nt.assert_true(name in matches, "Missing match: %r" % name) | |
422 |
|
455 | |||
423 |
|
456 | |||
|
457 | @dec.parametric | |||
|
458 | def test_kernel_info_request(): | |||
|
459 | flush_channels() | |||
|
460 | ||||
|
461 | shell = KM.shell_channel | |||
|
462 | ||||
|
463 | msg_id = shell.kernel_info() | |||
|
464 | reply = shell.get_msg(timeout=2) | |||
|
465 | for tst in validate_message(reply, 'kernel_info_reply', msg_id): | |||
|
466 | yield tst | |||
|
467 | ||||
|
468 | ||||
424 | # IOPub channel |
|
469 | # IOPub channel | |
425 |
|
470 | |||
426 |
|
471 |
@@ -670,6 +670,47 b' Message type: ``connect_reply``::' | |||||
670 | } |
|
670 | } | |
671 |
|
671 | |||
672 |
|
672 | |||
|
673 | Kernel info | |||
|
674 | ----------- | |||
|
675 | ||||
|
676 | If a client needs to know what protocol the kernel supports, it can | |||
|
677 | ask version number of the messaging protocol supported by the kernel. | |||
|
678 | This message can be used to fetch other core information of the | |||
|
679 | kernel, including language (e.g., Python), language version number and | |||
|
680 | IPython version number. | |||
|
681 | ||||
|
682 | Message type: ``kernel_info_request``:: | |||
|
683 | ||||
|
684 | content = { | |||
|
685 | } | |||
|
686 | ||||
|
687 | Message type: ``kernel_info_reply``:: | |||
|
688 | ||||
|
689 | content = { | |||
|
690 | # Version of messaging protocol (mandatory). | |||
|
691 | # The first integer indicates major version. It is incremented when | |||
|
692 | # there is any backward incompatible change. | |||
|
693 | # The second integer indicates minor version. It is incremented when | |||
|
694 | # there is any backward compatible change. | |||
|
695 | 'protocol_version': [int, int], | |||
|
696 | ||||
|
697 | # IPython version number (optional). | |||
|
698 | # Non-python kernel backend may not have this version number. | |||
|
699 | # The last component is an extra field, which may be 'dev' or | |||
|
700 | # 'rc1' in development version. It is an empty string for | |||
|
701 | # released version. | |||
|
702 | 'ipython_version': [int, int, int, str], | |||
|
703 | ||||
|
704 | # Language version number (mandatory). | |||
|
705 | # It is Python version number (e.g., [2, 7, 3]) for the kernel | |||
|
706 | # included in IPython. | |||
|
707 | 'language_version': [int, ...], | |||
|
708 | ||||
|
709 | # Programming language in which kernel is implemented (mandatory). | |||
|
710 | # Kernel included in IPython returns 'python'. | |||
|
711 | 'language': str, | |||
|
712 | } | |||
|
713 | ||||
673 |
|
714 | |||
674 | Kernel shutdown |
|
715 | Kernel shutdown | |
675 | --------------- |
|
716 | --------------- |
General Comments 0
You need to be logged in to leave comments.
Login now