diff --git a/notebook/notebookapp.py b/notebook/notebookapp.py index 3d32014c15..34c1c0f52e 100644 --- a/notebook/notebookapp.py +++ b/notebook/notebookapp.py @@ -114,15 +114,6 @@ def load_handlers(name): return mod.default_handlers -class DeprecationHandler(IPythonHandler): - def get(self, url_path): - self.set_header("Content-Type", 'text/javascript') - self.finish(""" - console.warn('`/static/widgets/js` is deprecated. Use `nbextensions/widgets/widgets/js` instead.'); - define(['%s'], function(x) { return x; }); - """ % url_path_join('nbextensions', 'widgets', 'widgets', url_path.rstrip('.js'))) - self.log.warn('Deprecated widget Javascript path /static/widgets/js/*.js was used') - #----------------------------------------------------------------------------- # The Tornado web application #----------------------------------------------------------------------------- @@ -225,7 +216,6 @@ def init_handlers(self, settings): # Order matters. The first handler to match the URL will handle the request. handlers = [] - handlers.append((r'/deprecatedwidgets/(.*)', DeprecationHandler)) handlers.extend(load_handlers('tree.handlers')) handlers.extend([(r"/login", settings['login_handler_class'])]) handlers.extend([(r"/logout", settings['logout_handler_class'])]) @@ -244,16 +234,17 @@ def init_handlers(self, settings): handlers.extend(load_handlers('services.security.handlers')) # BEGIN HARDCODED WIDGETS HACK + # TODO: Remove on notebook 5.0 try: - import ipywidgets + import ipywidgets as widgets handlers.append( (r"/nbextensions/widgets/(.*)", FileFindHandler, { - 'path': ipywidgets.find_static_assets(), + 'path': widgets.find_static_assets(), 'no_cache_paths': ['/'], # don't cache anything in nbextensions }), ) except: - app_log.warn('ipywidgets package not installed. Widgets are unavailable.') + app_log.warning('Widgets are unavailable. Please install widgetsnbextension or ipywidgets 4.0') # END HARDCODED WIDGETS HACK handlers.append( diff --git a/notebook/static/base/js/utils.js b/notebook/static/base/js/utils.js index a9f4e2ec74..e64d71a432 100644 --- a/notebook/static/base/js/utils.js +++ b/notebook/static/base/js/utils.js @@ -13,6 +13,16 @@ define([ // keep track of which extensions have been loaded already var extensions_loaded = []; + /** + * Whether or not an extension has been loaded + * @param {string} extension - name of the extension + * @return {boolean} true if loaded already + */ + var is_loaded = function(extension) { + var ext_path = "nbextensions/" + extension; + return extensions_loaded.indexOf(ext_path) >= 0; + }; + /** * Load a single extension. * @param {string} extension - extension path. @@ -21,17 +31,17 @@ define([ var load_extension = function (extension) { return new Promise(function(resolve, reject) { var ext_path = "nbextensions/" + extension; - require([ext_path], function(module) { - try { - if (extensions_loaded.indexOf(ext_path) < 0) { - console.log("Loading extension: " + extension); - module.load_ipython_extension(); - extensions_loaded.push(ext_path); + requirejs([ext_path], function(module) { + if (!is_loaded(extension)) { + console.log("Loading extension: " + extension); + if (module.load_ipython_extension) { + Promise.resolve(module.load_ipython_extension()).then(function() { + resolve(module); + }).catch(reject); } - else{ - console.log("Loaded extension already: " + extension); - } - } finally { + extensions_loaded.push(ext_path); + } else { + console.log("Loaded extension already: " + extension); resolve(module); } }, function(err) { @@ -72,12 +82,12 @@ define([ * in a 'load_extensions' key inside it. */ function load_extensions_from_config(section) { - section.loaded.then(function() { + return section.loaded.then(function() { if (section.data.load_extensions) { var active = filter_extensions(section.data.load_extensions); return load_extensions.apply(this, active); } - }); + }).catch(utils.reject('Could not load nbextensions from ' + section.section_name + ' config file')); } //============================================================================ @@ -841,6 +851,7 @@ define([ }; var utils = { + is_loaded: is_loaded, load_extension: load_extension, load_extensions: load_extensions, filter_extensions: filter_extensions, diff --git a/notebook/static/notebook/js/main.js b/notebook/static/notebook/js/main.js index 4f5cbce6bf..497516acc7 100644 --- a/notebook/static/notebook/js/main.js +++ b/notebook/static/notebook/js/main.js @@ -54,12 +54,6 @@ require([ ) { "use strict"; - // BEGIN HARDCODED WIDGETS HACK - utils.load_extension('widgets/notebook/js/extension').catch(function () { - console.warn('ipywidgets package not installed. Widgets are not available.'); - }); - // END HARDCODED WIDGETS HACK - // compat with old IPython, remove for IPython > 3.0 window.CodeMirror = CodeMirror; @@ -177,8 +171,28 @@ require([ configurable: false }); - utils.load_extensions_from_config(config_section); - utils.load_extensions_from_config(common_config); + // Now actually load nbextensions from config + Promise.all([ + utils.load_extensions_from_config(config_section), + utils.load_extensions_from_config(common_config), + ]) + .catch(function(error) { + console.error('Could not load nbextensions from user config files', error); + }) + // BEGIN HARDCODED WIDGETS HACK + .then(function() { + if (!utils.is_loaded('widgets/extension')) { + // Fallback to the ipywidgets extension + utils.load_extension('widgets/notebook/js/extension').catch(function () { + console.warn('Widgets are not available. Please install widgetsnbextension or ipywidgets 4.0'); + }); + } + }) + .catch(function(error) { + console.error('Could not load ipywidgets', error); + }); + // END HARDCODED WIDGETS HACK + notebook.load_notebook(common_options.notebook_path); }); diff --git a/notebook/templates/page.html b/notebook/templates/page.html index 5ea5a61d73..95927286f3 100644 --- a/notebook/templates/page.html +++ b/notebook/templates/page.html @@ -27,7 +27,6 @@ 'auth/js/main': 'auth/js/main.min', custom : '{{ base_url }}custom', nbextensions : '{{ base_url }}nbextensions', - widgets : '{{ base_url }}deprecatedwidgets', kernelspecs : '{{ base_url }}kernelspecs', underscore : 'components/underscore/underscore-min', backbone : 'components/backbone/backbone-min',