Show More
@@ -176,6 +176,7 b' class FileContentsManager(ContentsManager):' | |||
|
176 | 176 | model['created'] = created |
|
177 | 177 | model['content'] = None |
|
178 | 178 | model['format'] = None |
|
179 | model['message'] = None | |
|
179 | 180 | return model |
|
180 | 181 | |
|
181 | 182 | def _dir_model(self, name, path='', content=True): |
@@ -258,6 +259,7 b' class FileContentsManager(ContentsManager):' | |||
|
258 | 259 | self.mark_trusted_cells(nb, name, path) |
|
259 | 260 | model['content'] = nb |
|
260 | 261 | model['format'] = 'json' |
|
262 | self.validate_notebook_model(model) | |
|
261 | 263 | return model |
|
262 | 264 | |
|
263 | 265 | def get_model(self, name, path='', content=True): |
@@ -366,7 +368,14 b' class FileContentsManager(ContentsManager):' | |||
|
366 | 368 | except Exception as e: |
|
367 | 369 | raise web.HTTPError(400, u'Unexpected error while saving file: %s %s' % (os_path, e)) |
|
368 | 370 | |
|
371 | validation_message = None | |
|
372 | if model['type'] == 'notebook': | |
|
373 | self.validate_notebook_model(model) | |
|
374 | validation_message = model.get('message', None) | |
|
375 | ||
|
369 | 376 | model = self.get_model(new_name, new_path, content=False) |
|
377 | if validation_message: | |
|
378 | model['message'] = validation_message | |
|
370 | 379 | return model |
|
371 | 380 | |
|
372 | 381 | def update(self, model, name, path=''): |
@@ -5,6 +5,7 b'' | |||
|
5 | 5 | |
|
6 | 6 | from fnmatch import fnmatch |
|
7 | 7 | import itertools |
|
8 | import json | |
|
8 | 9 | import os |
|
9 | 10 | |
|
10 | 11 | from tornado.web import HTTPError |
@@ -216,6 +217,16 b' class ContentsManager(LoggingConfigurable):' | |||
|
216 | 217 | break |
|
217 | 218 | return name |
|
218 | 219 | |
|
220 | def validate_notebook_model(self, model): | |
|
221 | """Add failed-validation message to model""" | |
|
222 | try: | |
|
223 | current.validate(model['content']) | |
|
224 | except current.ValidationError as e: | |
|
225 | model['message'] = 'Notebook Validation failed: {}:\n{}'.format( | |
|
226 | e.message, json.dumps(e.instance, indent=1, default=lambda obj: '<UNKNOWN>'), | |
|
227 | ) | |
|
228 | return model | |
|
229 | ||
|
219 | 230 | def create_file(self, model=None, path='', ext='.ipynb'): |
|
220 | 231 | """Create a new file or directory and return its model with no content.""" |
|
221 | 232 | path = path.strip('/') |
@@ -1826,6 +1826,7 b' define([' | |||
|
1826 | 1826 | * @param {Object} data JSON representation of a notebook |
|
1827 | 1827 | */ |
|
1828 | 1828 | Notebook.prototype.fromJSON = function (data) { |
|
1829 | ||
|
1829 | 1830 | var content = data.content; |
|
1830 | 1831 | var ncells = this.ncells(); |
|
1831 | 1832 | var i; |
@@ -1975,6 +1976,7 b' define([' | |||
|
1975 | 1976 | type : "PUT", |
|
1976 | 1977 | data : JSON.stringify(model), |
|
1977 | 1978 | headers : {'Content-Type': 'application/json'}, |
|
1979 | dataType : "json", | |
|
1978 | 1980 | success : $.proxy(this.save_notebook_success, this, start), |
|
1979 | 1981 | error : $.proxy(this.save_notebook_error, this) |
|
1980 | 1982 | }; |
@@ -2004,6 +2006,30 b' define([' | |||
|
2004 | 2006 | */ |
|
2005 | 2007 | Notebook.prototype.save_notebook_success = function (start, data, status, xhr) { |
|
2006 | 2008 | this.set_dirty(false); |
|
2009 | if (data.message) { | |
|
2010 | // save succeeded, but validation failed. | |
|
2011 | var body = $("<div>"); | |
|
2012 | var title = "Notebook validation failed"; | |
|
2013 | ||
|
2014 | body.append($("<p>").text( | |
|
2015 | "The save operation succeeded," + | |
|
2016 | " but the notebook does not appear to be valid." + | |
|
2017 | " The validation error was:" | |
|
2018 | )).append($("<div>").addClass("validation-error").append( | |
|
2019 | $("<pre>").text(data.message) | |
|
2020 | )); | |
|
2021 | dialog.modal({ | |
|
2022 | notebook: this, | |
|
2023 | keyboard_manager: this.keyboard_manager, | |
|
2024 | title: title, | |
|
2025 | body: body, | |
|
2026 | buttons : { | |
|
2027 | OK : { | |
|
2028 | "class" : "btn-primary" | |
|
2029 | } | |
|
2030 | } | |
|
2031 | }); | |
|
2032 | } | |
|
2007 | 2033 | this.events.trigger('notebook_saved.Notebook'); |
|
2008 | 2034 | this._update_autosave_interval(start); |
|
2009 | 2035 | if (this._checkpoint_after_save) { |
@@ -2278,7 +2304,57 b' define([' | |||
|
2278 | 2304 | * @param {jqXHR} xhr jQuery Ajax object |
|
2279 | 2305 | */ |
|
2280 | 2306 | Notebook.prototype.load_notebook_success = function (data, status, xhr) { |
|
2281 | this.fromJSON(data); | |
|
2307 | var failed; | |
|
2308 | try { | |
|
2309 | this.fromJSON(data); | |
|
2310 | } catch (e) { | |
|
2311 | failed = e; | |
|
2312 | console.log("Notebook failed to load from JSON:", e); | |
|
2313 | } | |
|
2314 | if (failed || data.message) { | |
|
2315 | // *either* fromJSON failed or validation failed | |
|
2316 | var body = $("<div>"); | |
|
2317 | var title; | |
|
2318 | if (failed) { | |
|
2319 | title = "Notebook failed to load"; | |
|
2320 | body.append($("<p>").text( | |
|
2321 | "The error was: " | |
|
2322 | )).append($("<div>").addClass("js-error").text( | |
|
2323 | failed.toString() | |
|
2324 | )).append($("<p>").text( | |
|
2325 | "See the error console for details." | |
|
2326 | )); | |
|
2327 | } else { | |
|
2328 | title = "Notebook validation failed"; | |
|
2329 | } | |
|
2330 | ||
|
2331 | if (data.message) { | |
|
2332 | var msg; | |
|
2333 | if (failed) { | |
|
2334 | msg = "The notebook also failed validation:" | |
|
2335 | } else { | |
|
2336 | msg = "An invalid notebook may not function properly." + | |
|
2337 | " The validation error was:" | |
|
2338 | } | |
|
2339 | body.append($("<p>").text( | |
|
2340 | msg | |
|
2341 | )).append($("<div>").addClass("validation-error").append( | |
|
2342 | $("<pre>").text(data.message) | |
|
2343 | )); | |
|
2344 | } | |
|
2345 | ||
|
2346 | dialog.modal({ | |
|
2347 | notebook: this, | |
|
2348 | keyboard_manager: this.keyboard_manager, | |
|
2349 | title: title, | |
|
2350 | body: body, | |
|
2351 | buttons : { | |
|
2352 | OK : { | |
|
2353 | "class" : "btn-primary" | |
|
2354 | } | |
|
2355 | } | |
|
2356 | }); | |
|
2357 | } | |
|
2282 | 2358 | if (this.ncells() === 0) { |
|
2283 | 2359 | this.insert_cell_below('code'); |
|
2284 | 2360 | this.edit_mode(0); |
General Comments 0
You need to be logged in to leave comments.
Login now