From 1c5293bd6c010f185205e3d566b262b1ac7cb0f7 2014-12-01 22:17:59 From: Thomas Kluyver Date: 2014-12-01 22:17:59 Subject: [PATCH] Merge pull request #6945 from minrk/kernel-info-lang fix loading of language name from kernel_info --- diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js index f3f1c64..09844a9 100644 --- a/IPython/html/static/notebook/js/notebook.js +++ b/IPython/html/static/notebook/js/notebook.js @@ -250,11 +250,9 @@ define([ this.events.on('kernel_ready.Kernel', function(event, data) { var kinfo = data.kernel.info_reply; var langinfo = kinfo.language_info || {}; - if (!langinfo.name) langinfo.name = kinfo.language; - that.metadata.language_info = langinfo; // Mode 'null' should be plain, unhighlighted text. - var cm_mode = langinfo.codemirror_mode || langinfo.language || 'null'; + var cm_mode = langinfo.codemirror_mode || langinfo.name || 'null'; that.set_codemirror_mode(cm_mode); }); @@ -1861,7 +1859,7 @@ define([ if (this.metadata.language_info !== undefined) { var langinfo = this.metadata.language_info; // Mode 'null' should be plain, unhighlighted text. - var cm_mode = langinfo.codemirror_mode || langinfo.language || 'null'; + var cm_mode = langinfo.codemirror_mode || langinfo.name || 'null'; this.set_codemirror_mode(cm_mode); } diff --git a/IPython/kernel/adapter.py b/IPython/kernel/adapter.py index 5c87cd0..25deac2 100644 --- a/IPython/kernel/adapter.py +++ b/IPython/kernel/adapter.py @@ -102,16 +102,20 @@ class V5toV4(Adapter): # shell channel def kernel_info_reply(self, msg): + v4c = {} content = msg['content'] - content.pop('banner', None) for key in ('language_version', 'protocol_version'): if key in content: - content[key] = _version_str_to_list(content[key]) - if content.pop('implementation', '') == 'ipython' \ + v4c[key] = _version_str_to_list(content[key]) + if content.get('implementation', '') == 'ipython' \ and 'implementation_version' in content: - content['ipython_version'] = content.pop('implmentation_version') - content.pop('implementation_version', None) - content.setdefault("implmentation", content['language']) + v4c['ipython_version'] = _version_str_to_list(content['implementation_version']) + language_info = content.get('language_info', {}) + language = language_info.get('name', '') + v4c.setdefault('language', language) + if 'version' in language_info: + v4c.setdefault('language_version', _version_str_to_list(language_info['version'])) + msg['content'] = v4c return msg def execute_request(self, msg): @@ -204,14 +208,23 @@ class V4toV5(Adapter): def kernel_info_reply(self, msg): content = msg['content'] - for key in ('language_version', 'protocol_version', 'ipython_version'): + for key in ('protocol_version', 'ipython_version'): if key in content: - content[key] = ".".join(map(str, content[key])) + content[key] = '.'.join(map(str, content[key])) + + content.setdefault('protocol_version', '4.1') if content['language'].startswith('python') and 'ipython_version' in content: content['implementation'] = 'ipython' content['implementation_version'] = content.pop('ipython_version') + language = content.pop('language') + language_info = content.setdefault('language_info', {}) + language_info.setdefault('name', language) + if 'language_version' in content: + language_version = '.'.join(map(str, content.pop('language_version'))) + language_info.setdefault('version', language_version) + content['banner'] = '' return msg diff --git a/IPython/kernel/tests/test_adapter.py b/IPython/kernel/tests/test_adapter.py index a976991..fe2c886 100644 --- a/IPython/kernel/tests/test_adapter.py +++ b/IPython/kernel/tests/test_adapter.py @@ -169,6 +169,26 @@ class V4toV5TestCase(AdapterTest): text = v5c['data']['text/plain'] self.assertEqual(text, '\n'.join([v4c['definition'], v4c['docstring']])) + def test_kernel_info_reply(self): + msg = self.msg("kernel_info_reply", { + 'language': 'python', + 'language_version': [2,8,0], + 'ipython_version': [1,2,3], + }) + v4, v5 = self.adapt(msg) + v4c = v4['content'] + v5c = v5['content'] + self.assertEqual(v5c, { + 'protocol_version': '4.1', + 'implementation': 'ipython', + 'implementation_version': '1.2.3', + 'language_info': { + 'name': 'python', + 'version': '2.8.0', + }, + 'banner' : '', + }) + # iopub channel def test_display_data(self): @@ -305,6 +325,29 @@ class V5toV4TestCase(AdapterTest): self.assertEqual(sorted(v4c), ['found', 'oname']) self.assertEqual(v4c['found'], False) + def test_kernel_info_reply(self): + msg = self.msg("kernel_info_reply", { + 'protocol_version': '5.0', + 'implementation': 'ipython', + 'implementation_version': '1.2.3', + 'language_info': { + 'name': 'python', + 'version': '2.8.0', + 'mimetype': 'text/x-python', + }, + 'banner' : 'the banner', + }) + v5, v4 = self.adapt(msg) + v4c = v4['content'] + v5c = v5['content'] + info = v5c['language_info'] + self.assertEqual(v4c, { + 'protocol_version': [5,0], + 'language': 'python', + 'language_version': [2,8,0], + 'ipython_version': [1,2,3], + }) + # iopub channel def test_display_data(self): diff --git a/IPython/kernel/tests/test_message_spec.py b/IPython/kernel/tests/test_message_spec.py index 3a72275..7c4bd46 100644 --- a/IPython/kernel/tests/test_message_spec.py +++ b/IPython/kernel/tests/test_message_spec.py @@ -4,8 +4,8 @@ # Distributed under the terms of the Modified BSD License. import re +import sys from distutils.version import LooseVersion as V -from subprocess import PIPE try: from queue import Empty # Py 3 except ImportError: @@ -13,10 +13,8 @@ except ImportError: import nose.tools as nt -from IPython.kernel import KernelManager - from IPython.utils.traitlets import ( - HasTraits, TraitError, Bool, Unicode, Dict, Integer, List, Enum, Any, + HasTraits, TraitError, Bool, Unicode, Dict, Integer, List, Enum, ) from IPython.utils.py3compat import string_types, iteritems @@ -150,15 +148,20 @@ class CompleteReply(Reference): cursor_end = Integer() status = Unicode() +class LanguageInfo(Reference): + name = Unicode('python') + version = Unicode(sys.version.split()[0]) class KernelInfoReply(Reference): protocol_version = Version(min='5.0') implementation = Unicode('ipython') implementation_version = Version(min='2.1') - language_version = Version(min='2.7') - language = Unicode('python') language_info = Dict() banner = Unicode() + + def check(self, d): + Reference.check(self, d) + LanguageInfo().check(d['language_info']) class IsCompleteReply(Reference): diff --git a/IPython/kernel/zmq/ipkernel.py b/IPython/kernel/zmq/ipkernel.py index 5cc0a01..89d9677 100644 --- a/IPython/kernel/zmq/ipkernel.py +++ b/IPython/kernel/zmq/ipkernel.py @@ -69,9 +69,10 @@ class IPythonKernel(KernelBase): # Kernel info fields implementation = 'ipython' implementation_version = release.version - language = 'python' - language_version = sys.version.split()[0] - language_info = {'mimetype': 'text/x-python', + language_info = { + 'name': 'python', + 'version': sys.version.split()[0], + 'mimetype': 'text/x-python', 'codemirror_mode': {'name': 'ipython', 'version': sys.version_info[0]}, 'pygments_lexer': 'ipython%d' % (3 if PY3 else 2), diff --git a/IPython/kernel/zmq/kernelbase.py b/IPython/kernel/zmq/kernelbase.py index 42b38c0..7b59656 100755 --- a/IPython/kernel/zmq/kernelbase.py +++ b/IPython/kernel/zmq/kernelbase.py @@ -455,8 +455,6 @@ class Kernel(SingletonConfigurable): 'protocol_version': release.kernel_protocol_version, 'implementation': self.implementation, 'implementation_version': self.implementation_version, - 'language': self.language, - 'language_version': self.language_version, 'language_info': self.language_info, 'banner': self.banner, } diff --git a/IPython/nbformat/v4/nbformat.v4.schema.json b/IPython/nbformat/v4/nbformat.v4.schema.json index 317a80b..365a08a 100644 --- a/IPython/nbformat/v4/nbformat.v4.schema.json +++ b/IPython/nbformat/v4/nbformat.v4.schema.json @@ -10,25 +10,51 @@ "type": "object", "additionalProperties": true, "properties": { - "kernel_info": { + "kernelspec": { "description": "Kernel information.", "type": "object", - "required": ["name", "language"], + "required": ["name", "display_name"], "properties": { "name": { "description": "Name of the kernel specification.", "type": "string" }, - "language": { - "description": "The programming language which this kernel runs.", - "type": "string" - }, - "codemirror_mode": { - "description": "The codemirror mode to use for code in this language.", + "display_name": { + "description": "Name to display in UI.", "type": "string" } } }, + "language_info": { + "description": "Kernel information.", + "type": "object", + "required": ["name"], + "properties": { + "name": { + "description": "The programming language which this kernel runs.", + "type": "string" + }, + "codemirror_mode": { + "description": "The codemirror mode to use for code in this language.", + "oneOf": [ + {"type": "string"}, + {"type": "object"} + ] + }, + "file_extension": { + "description": "The file extension for files in this language.", + "type": "string" + }, + "mimetype": { + "description": "The mimetype corresponding to files in this language.", + "type": "string" + }, + "pygments_lexer": { + "description": "The pygments lexer to use for code in this language.", + "type": "string" + } + } + }, "signature": { "description": "Hash of the notebook.", "type": "string" diff --git a/docs/source/development/messaging.rst b/docs/source/development/messaging.rst index 47befeb..08b7618 100644 --- a/docs/source/development/messaging.rst +++ b/docs/source/development/messaging.rst @@ -720,19 +720,20 @@ Message type: ``kernel_info_reply``:: # Implementation version number. # The version number of the kernel's implementation # (e.g. IPython.__version__ for the IPython kernel) - 'implementation_version': 'X.Y.Z', - - # Programming language in which kernel is implemented. - # Kernel included in IPython returns 'python'. - 'language': str, - - # Language version number. - # It is Python version number (e.g., '2.7.3') for the kernel - # included in IPython. - 'language_version': 'X.Y.Z', + 'implementation_version': 'X.Y.Z', # Information about the language of code for the kernel 'language_info': { + # Name of the programming language in which kernel is implemented. + # Kernel included in IPython returns 'python'. + 'name': str, + + # Language version number. + # It is Python version number (e.g., '2.7.3') for the kernel + # included in IPython. + 'version': 'X.Y.Z', + + # mimetype for script files in this language 'mimetype': str, # Extension without the dot, e.g. 'py' @@ -779,6 +780,14 @@ and `codemirror modes `_ for those fields ``language_info``, ``implementation``, ``implementation_version``, ``banner`` and ``help_links`` keys are added. +.. versionchanged:: 5.0 + + ``language_version`` moved to ``language_info.version`` + +.. versionchanged:: 5.0 + + ``language`` moved to ``language_info.name`` + .. _msging_shutdown: Kernel shutdown diff --git a/docs/source/notebook/nbformat.rst b/docs/source/notebook/nbformat.rst index 975d748..b2ee31f 100644 --- a/docs/source/notebook/nbformat.rst +++ b/docs/source/notebook/nbformat.rst @@ -36,11 +36,15 @@ At the highest level, a Jupyter notebook is a dictionary with a few keys: "metadata" : { "signature": "hex-digest", # used for authenticating unsafe outputs on load "kernel_info": { - # if kernel_info is defined, its name and language fields are required. - "name" : "the name of the kernel", - "language" : "the programming language of the kernel", - "codemirror_mode": "The name of the codemirror mode to use [optional]" + # if kernel_info is defined, its name field is required. + "name" : "the name of the kernel" }, + "language_info": { + # if language_info is defined, its name field is required. + "name" : "the programming language of the kernel", + "version": "the version of the language", + "codemirror_mode": "The name of the codemirror mode to use [optional]" + } }, "nbformat": 4, "nbformat_minor": 0,