diff --git a/IPython/frontend/html/notebook/static/js/kernel.js b/IPython/frontend/html/notebook/static/js/kernel.js index 68e486a..99ac624 100644 --- a/IPython/frontend/html/notebook/static/js/kernel.js +++ b/IPython/frontend/html/notebook/static/js/kernel.js @@ -106,8 +106,10 @@ var IPython = (function (IPython) { resizable: false, modal: true, title: "Websocket closed", + closeText: "", + close: function(event, ui) {$(this).dialog('destroy').remove();}, buttons : { - "Okay": function () { + "OK": function () { $(this).dialog('close'); } } diff --git a/IPython/frontend/html/notebook/static/js/notebook.js b/IPython/frontend/html/notebook/static/js/notebook.js index be66714..898672b 100644 --- a/IPython/frontend/html/notebook/static/js/notebook.js +++ b/IPython/frontend/html/notebook/static/js/notebook.js @@ -29,6 +29,7 @@ var IPython = (function (IPython) { this.notebook_id = null; this.notebook_name = null; this.notebook_name_blacklist_re = /[\/\\]/; + this.nbformat = 3 // Increment this when changing the nbformat this.style(); this.create_elements(); this.bind_events(); @@ -1222,7 +1223,7 @@ var IPython = (function (IPython) { // We may want to move the name/id/nbformat logic inside toJSON? var data = this.toJSON(); data.metadata.name = this.notebook_name; - data.nbformat = 3; + data.nbformat = this.nbformat; // We do the call with settings so we can set cache to false. var settings = { processData : false, @@ -1230,8 +1231,8 @@ var IPython = (function (IPython) { type : "PUT", data : JSON.stringify(data), headers : {'Content-Type': 'application/json'}, - success : $.proxy(this.notebook_save_success,this), - error : $.proxy(this.notebook_save_failed,this) + success : $.proxy(this.save_notebook_success,this), + error : $.proxy(this.save_notebook_error,this) }; $([IPython.events]).trigger('notebook_saving.Notebook'); var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id; @@ -1239,13 +1240,13 @@ var IPython = (function (IPython) { }; - Notebook.prototype.notebook_save_success = function (data, status, xhr) { + Notebook.prototype.save_notebook_success = function (data, status, xhr) { this.dirty = false; $([IPython.events]).trigger('notebook_saved.Notebook'); }; - Notebook.prototype.notebook_save_failed = function (xhr, status, error_msg) { + Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) { $([IPython.events]).trigger('notebook_save_failed.Notebook'); }; @@ -1259,9 +1260,8 @@ var IPython = (function (IPython) { cache : false, type : "GET", dataType : "json", - success : function (data, status, xhr) { - that.load_notebook_success(data, status, xhr); - } + success : $.proxy(this.load_notebook_success,this), + error : $.proxy(this.load_notebook_error,this), }; $([IPython.events]).trigger('notebook_loading.Notebook'); var url = $('body').data('baseProjectUrl') + 'notebooks/' + this.notebook_id; @@ -1280,9 +1280,59 @@ var IPython = (function (IPython) { } this.select(0); this.scroll_to_top(); + if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) { + msg = "This notebook has been converted from an older " + + "notebook format (v"+data.orig_nbformat+") to the current notebook " + + "format (v"+data.nbformat+"). The next time you save this notebook, the " + + "newer notebook format will be used and older verions of IPython " + + "may not be able to read it. To keep the older version, close the " + + "notebook without saving it."; + var dialog = $('
'); + dialog.html(msg); + this.element.append(dialog); + dialog.dialog({ + resizable: false, + modal: true, + title: "Notebook converted", + closeText: "", + close: function(event, ui) {$(this).dialog('destroy').remove();}, + buttons : { + "OK": function () { + $(this).dialog('close'); + } + }, + width: 400 + }); + } $([IPython.events]).trigger('notebook_loaded.Notebook'); }; + + Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) { + if (xhr.status === 500) { + msg = "An error occurred while loading this notebook. Most likely " + + "this notebook is in a newer format than is supported by this " + + "version of IPython. This version can load notebook formats " + + "v"+this.nbformat+" or earlier."; + var dialog = $('
'); + dialog.html(msg); + this.element.append(dialog); + dialog.dialog({ + resizable: false, + modal: true, + title: "Error loading notebook", + closeText: "", + close: function(event, ui) {$(this).dialog('destroy').remove();}, + buttons : { + "OK": function () { + $(this).dialog('close'); + } + }, + width: 400 + }); + } + } + IPython.Notebook = Notebook; diff --git a/IPython/nbformat/current.py b/IPython/nbformat/current.py index a1e29dc..c16efc4 100644 --- a/IPython/nbformat/current.py +++ b/IPython/nbformat/current.py @@ -28,14 +28,14 @@ from IPython.nbformat import v1 from IPython.nbformat.v3 import ( NotebookNode, new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet, - parse_filename, new_metadata, new_author, new_heading_cell + parse_filename, new_metadata, new_author, new_heading_cell, nbformat ) #----------------------------------------------------------------------------- # Code #----------------------------------------------------------------------------- -current_nbformat = 3 +current_nbformat = nbformat class NBFormatError(Exception): @@ -45,8 +45,8 @@ class NBFormatError(Exception): def parse_json(s, **kwargs): """Parse a string into a (nbformat, dict) tuple.""" d = json.loads(s, **kwargs) - nbformat = d.get('nbformat',1) - return nbformat, d + nbf = d.get('nbformat',1) + return nbf, d def parse_py(s, **kwargs): @@ -54,25 +54,25 @@ def parse_py(s, **kwargs): pattern = r'# (?P\d+)' m = re.search(pattern,s) if m is not None: - nbformat = int(m.group('nbformat')) + nbf = int(m.group('nbformat')) else: - nbformat = 3 - return nbformat, s + nbf = current_nbformat + return nbf, s def reads_json(s, **kwargs): """Read a JSON notebook from a string and return the NotebookNode object.""" - nbformat, d = parse_json(s, **kwargs) - if nbformat == 1: + nbf, d = parse_json(s, **kwargs) + if nbf == 1: nb = v1.to_notebook_json(d, **kwargs) nb = v3.convert_to_this_nbformat(nb, orig_version=1) - elif nbformat == 2: + elif nbf == 2: nb = v2.to_notebook_json(d, **kwargs) nb = v3.convert_to_this_nbformat(nb, orig_version=2) - elif nbformat == 3: + elif nbf == 3: nb = v3.to_notebook_json(d, **kwargs) else: - raise NBFormatError('Unsupported JSON nbformat version: %i' % nbformat) + raise NBFormatError('Unsupported JSON nbformat version: %i' % nbf) return nb @@ -82,13 +82,13 @@ def writes_json(nb, **kwargs): def reads_py(s, **kwargs): """Read a .py notebook from a string and return the NotebookNode object.""" - nbformat, s = parse_py(s, **kwargs) - if nbformat == 2: + nbf, s = parse_py(s, **kwargs) + if nbf == 2: nb = v2.to_notebook_py(s, **kwargs) - elif nbformat == 3: + elif nbf == 3: nb = v3.to_notebook_py(s, **kwargs) else: - raise NBFormatError('Unsupported PY nbformat version: %i' % nbformat) + raise NBFormatError('Unsupported PY nbformat version: %i' % nbf) return nb diff --git a/IPython/nbformat/v3/convert.py b/IPython/nbformat/v3/convert.py index 8d67db9..8914fef 100644 --- a/IPython/nbformat/v3/convert.py +++ b/IPython/nbformat/v3/convert.py @@ -40,6 +40,9 @@ def convert_to_this_nbformat(nb, orig_version=2): nb = v2.convert_to_this_nbformat(nb) orig_version = 2 if orig_version == 2: + # Mark the original nbformat so consumers know it has been converted. + nb.nbformat = 3 + nb.orig_nbformat = 2 return nb elif orig_version == 3: return nb