From ac2ff1be88fe10df0b87ad0bb3df78cf2a880f48 2014-12-05 20:06:55 From: Min RK Date: 2014-12-05 20:06:55 Subject: [PATCH] kernelspecs is a dict sort menus client-side --- diff --git a/IPython/html/services/kernelspecs/handlers.py b/IPython/html/services/kernelspecs/handlers.py index f810414..2d1a75f 100644 --- a/IPython/html/services/kernelspecs/handlers.py +++ b/IPython/html/services/kernelspecs/handlers.py @@ -7,8 +7,6 @@ from tornado import web from ...base.handlers import IPythonHandler, json_errors -from IPython.kernel.kernelspec import _pythonfirst - class MainKernelSpecHandler(IPythonHandler): SUPPORTED_METHODS = ('GET',) @@ -17,18 +15,21 @@ class MainKernelSpecHandler(IPythonHandler): @json_errors def get(self): ksm = self.kernel_spec_manager - results = [] - for kernel_name in sorted(ksm.find_kernel_specs(), key=_pythonfirst): + km = self.kernel_manager + model = {} + model['default'] = km.default_kernel_name + model['kernelspecs'] = specs = {} + for kernel_name in ksm.find_kernel_specs(): try: d = ksm.get_kernel_spec(kernel_name).to_dict() except Exception: self.log.error("Failed to load kernel spec: '%s'", kernel_name, exc_info=True) continue d['name'] = kernel_name - results.append(d) + specs[kernel_name] = d self.set_header("Content-Type", 'application/json') - self.finish(json.dumps(results)) + self.finish(json.dumps(model)) class KernelSpecHandler(IPythonHandler): diff --git a/IPython/html/services/kernelspecs/tests/test_kernelspecs_api.py b/IPython/html/services/kernelspecs/tests/test_kernelspecs_api.py index a82a751..0d43fb1 100644 --- a/IPython/html/services/kernelspecs/tests/test_kernelspecs_api.py +++ b/IPython/html/services/kernelspecs/tests/test_kernelspecs_api.py @@ -78,16 +78,22 @@ class APITest(NotebookTestBase): with open(pjoin(bad_kernel_dir, 'kernel.json'), 'w') as f: f.write("garbage") - specs = self.ks_api.list().json() - assert isinstance(specs, list) + model = self.ks_api.list().json() + assert isinstance(model, dict) + self.assertEqual(model['default'], NATIVE_KERNEL_NAME) + specs = model['kernelspecs'] + assert isinstance(specs, dict) # 2: the sample kernelspec created in setUp, and the native Python kernel self.assertGreaterEqual(len(specs), 2) shutil.rmtree(bad_kernel_dir) def test_list_kernelspecs(self): - specs = self.ks_api.list().json() - assert isinstance(specs, list) + model = self.ks_api.list().json() + assert isinstance(model, dict) + self.assertEqual(model['default'], NATIVE_KERNEL_NAME) + specs = model['kernelspecs'] + assert isinstance(specs, dict) # 2: the sample kernelspec created in setUp, and the native Python kernel self.assertGreaterEqual(len(specs), 2) @@ -98,8 +104,8 @@ class APITest(NotebookTestBase): def is_default_kernelspec(s): return s['name'] == NATIVE_KERNEL_NAME and s['display_name'].startswith("IPython") - assert any(is_sample_kernelspec(s) for s in specs), specs - assert any(is_default_kernelspec(s) for s in specs), specs + assert any(is_sample_kernelspec(s) for s in specs.values()), specs + assert any(is_default_kernelspec(s) for s in specs.values()), specs def test_get_kernelspec(self): spec = self.ks_api.kernel_spec_info('Sample').json() # Case insensitive diff --git a/IPython/html/static/notebook/js/kernelselector.js b/IPython/html/static/notebook/js/kernelselector.js index 00da819..46d4882 100644 --- a/IPython/html/static/notebook/js/kernelselector.js +++ b/IPython/html/static/notebook/js/kernelselector.js @@ -25,16 +25,27 @@ define([ KernelSelector.prototype.request_kernelspecs = function() { var url = utils.url_join_encode(this.notebook.base_url, 'api/kernelspecs'); - $.ajax(url, {success: $.proxy(this._got_kernelspecs, this)}); + utils.promising_ajax(url).then($.proxy(this._got_kernelspecs, this)); }; - KernelSelector.prototype._got_kernelspecs = function(data, status, xhr) { - this.kernelspecs = {}; + KernelSelector.prototype._got_kernelspecs = function(data) { + this.kernelspecs = data.kernelspecs; var menu = this.element.find("#kernel_selector"); var change_kernel_submenu = $("#menu-change-kernel-submenu"); - for (var i = 0; i < data.length; i++) { - var ks = data[i]; - this.kernelspecs[ks.name] = ks; + var keys = Object.keys(data.kernelspecs).sort(function (a, b) { + // sort by display_name + var da = data.kernelspecs[a].display_name; + var db = data.kernelspecs[b].display_name; + if (da === db) { + return 0; + } else if (da > db) { + return 1; + } else { + return -1; + } + }); + for (var i = 0; i < keys.length; i++) { + var ks = this.kernelspecs[keys[i]]; var ksentry = $("
  • ").attr("id", "kernel-" +ks.name).append($('') .attr('href', '#') .click($.proxy(this.change_kernel, this, ks.name)) diff --git a/IPython/html/static/tree/js/newnotebook.js b/IPython/html/static/tree/js/newnotebook.js index 37ff15d..6a50391 100644 --- a/IPython/html/static/tree/js/newnotebook.js +++ b/IPython/html/static/tree/js/newnotebook.js @@ -38,11 +38,21 @@ define([ NewNotebookWidget.prototype._load_kernelspecs = function (data) { /** load kernelspec list */ - this.kernelspecs = {}; + this.kernelspecs = data.kernelspecs; var menu = this.element.find("#new-notebook-menu"); - for (var i = 0; i < data.length; i++) { - var ks = data[i]; - this.kernelspecs[ks.name] = ks; + var keys = Object.keys(data.kernelspecs).sort(function (a, b) { + var da = data.kernelspecs[a].display_name; + var db = data.kernelspecs[b].display_name; + if (da === db) { + return 0; + } else if (da > db) { + return 1; + } else { + return -1; + } + }); + for (var i = 0; i < keys.length; i++) { + var ks = this.kernelspecs[keys[i]]; var li = $("
  • ") .attr("id", "kernel-" +ks.name) .data('kernelspec', ks).append( @@ -59,12 +69,12 @@ define([ ); menu.append(li); } - this._load_default_kernelspec(); + this._load_default_kernelspec(data['default']); }; - NewNotebookWidget.prototype._load_default_kernelspec = function () { + NewNotebookWidget.prototype._load_default_kernelspec = function (default_name) { /** load default kernelspec name from localStorage, if defined */ - this.select_kernel(localStorage.default_kernel_name); + this.select_kernel(localStorage.default_kernel_name || default_name); }; NewNotebookWidget.prototype.select_kernel = function (kernel_name) {