From 106cf164ec33cb6214e2a1d48726ab4e1e6473bb 2014-12-10 09:45:26 From: Matthias BUSSONNIER Date: 2014-12-10 09:45:26 Subject: [PATCH] load the per kernel kernel.js and kernel.css As per discussion, each kernel can provide a file name kernel.js that we try to load at kernel switching. If such a file exist we assume that the kernel pathches the javasscript and that this javascript cannot be unpatched, and further switching of the kernel cannot be undone without reloading the page. (separate PR for UI) if a kernel provide kernel.js, the it should consist into a AMD module definition that uses require.js the module shoudl define a function name `onload` that will be called at the appropriate moment before the kernel starts. --- diff --git a/IPython/html/static/notebook/js/kernelselector.js b/IPython/html/static/notebook/js/kernelselector.js index 01f6d2a..ed6195e 100644 --- a/IPython/html/static/notebook/js/kernelselector.js +++ b/IPython/html/static/notebook/js/kernelselector.js @@ -21,6 +21,7 @@ define([ this.bind_events(); // Make the object globally available for user convenience & inspection IPython.kernelselector = this; + Object.seal(this); }; KernelSelector.prototype.request_kernelspecs = function() { @@ -61,10 +62,30 @@ define([ }; KernelSelector.prototype.change_kernel = function(kernel_name) { + /** + * TODO, have a methods to set kernel spec directly ? + **/ + var that = this; if (kernel_name === this.current_selection) { return; } var ks = this.kernelspecs[kernel_name]; + var new_mode_url = 'kernelspecs/'+ks.name+'/kernel'; + + var css_url = this.notebook.base_url+new_mode_url+'.css'; + $.ajax({ + type: 'HEAD', + url: css_url, + success: function(){ + $('#kernel-css') + .attr('href',css_url); + }, + error:function(){ + console.warn(new_mode_url+' does not provide custom URL, you might see a 404 error that shoudl not prevent '+ + ' the Jupyter notebook from working :' ,css_url ); + } + }); + try { this.notebook.start_session(kernel_name); } catch (e) { @@ -78,8 +99,32 @@ define([ return; } this.events.trigger('spec_changed.Kernel', ks); + + + // load new mode kernel.js if exist + require([new_mode_url], + // if new mode has custom.js + function(new_mode){ + that.lock_switch(); + if(new_mode && new_mode.onload){ + new_mode.onload(); + } else { + console.warn("The current kernel seem to define a kernel.js file; though this file does"+ + "not contain any asynchronous module definition. This is undefined behavior"+ + "which is not recommeneded"); + } + }, + function(err){ + // if new mode does not have custom.js + console.warn('Any above 404 on '+new_mode_url+'.js is normal'); + } + ); }; - + + KernelSelector.prototype.lock_switch = function() { + console.warn('switching kernel is not guarantied to work !'); + }; + KernelSelector.prototype.bind_events = function() { var that = this; this.events.on('spec_changed.Kernel', function(event, data) { @@ -87,7 +132,7 @@ define([ that.element.find("#current_kernel_spec").find('.kernel_name').text(data.display_name); that.element.find("#current_kernel_logo").attr("src", "/kernelspecs/"+data.name+"/logo-64x64.png"); }); - + this.events.on('kernel_created.Session', function(event, data) { if (data.kernel.name !== that.current_selection) { // If we created a 'python' session, we only know if it's Python diff --git a/IPython/html/static/notebook/js/main.js b/IPython/html/static/notebook/js/main.js index a6c8264..cff2c58 100644 --- a/IPython/html/static/notebook/js/main.js +++ b/IPython/html/static/notebook/js/main.js @@ -113,6 +113,7 @@ require([ notification_area.init_notification_widgets(); var kernel_selector = new kernelselector.KernelSelector( '#kernel_selector_widget', notebook); + notebook.set_kernelselector(kernel_selector); $('body').append('
x'+
                      'x'+
diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js
index 19556f2..6c8496b 100644
--- a/IPython/html/static/notebook/js/notebook.js
+++ b/IPython/html/static/notebook/js/notebook.js
@@ -1864,7 +1864,14 @@ define([
         // Trigger an event changing the kernel spec - this will set the default
         // codemirror mode
         if (this.metadata.kernelspec !== undefined) {
-            this.events.trigger('spec_changed.Kernel', this.metadata.kernelspec);
+            // TODO shoudl probably not trigger here, 
+            // should call the kernel selector, or custom.{js|css} not loaded.
+            if(this.kernel_selector){
+                // technically not perfect, we should check that the kernelspec matches
+                this.kernel_selector.change_kernel(this.metadata.kernelspec.name);
+            } else {
+                console.log('do not have handle on kernnel_selector');
+            }
         }
         
         // Set the codemirror mode from language_info metadata
@@ -2308,6 +2315,10 @@ define([
         this.events.trigger('notebook_loaded.Notebook');
     };
 
+    Notebook.prototype.set_kernelselector = function(k_selector){
+        this.kernel_selector = k_selector;
+    };
+
     /**
      * Failure callback for loading a notebook from the server.
      * 
diff --git a/IPython/html/templates/notebook.html b/IPython/html/templates/notebook.html
index 9c7547e..236339d 100644
--- a/IPython/html/templates/notebook.html
+++ b/IPython/html/templates/notebook.html
@@ -17,6 +17,7 @@ window.mathjax_url = "{{mathjax_url}}";
 {{super()}}
 
 
+
 
 {% endblock %}
 
diff --git a/IPython/html/templates/page.html b/IPython/html/templates/page.html
index 48f0a89..541f5a9 100644
--- a/IPython/html/templates/page.html
+++ b/IPython/html/templates/page.html
@@ -24,6 +24,7 @@
           baseUrl: '{{static_url("", include_version=False)}}',
           paths: {
             nbextensions : '{{ base_url }}nbextensions',
+            kernelspecs : '{{ base_url }}kernelspecs',
             underscore : 'components/underscore/underscore-min',
             backbone : 'components/backbone/backbone-min',
             jquery: 'components/jquery/jquery.min',