##// END OF EJS Templates
Merge pull request #6991 from minrk/unhandled-types...
Thomas Kluyver -
r19117:bc59b4a1 merge
parent child Browse files
Show More
@@ -53,7 +53,9 b' define(['
53 53 get: function() { return that._metadata; },
54 54 set: function(value) {
55 55 that._metadata = value;
56 that.celltoolbar.rebuild();
56 if (that.celltoolbar) {
57 that.celltoolbar.rebuild();
58 }
57 59 }
58 60 });
59 61
@@ -194,11 +196,11 b' define(['
194 196 if((cur.line !== 0 || cur.ch !==0) && event.keyCode === 38){
195 197 event._ipkmIgnore = true;
196 198 }
197 var nLastLine = editor.lastLine()
198 if( ( event.keyCode === 40)
199 && (( cur.line !== nLastLine)
200 || ( cur.ch !== editor.getLineHandle(nLastLine).text.length))
201 ){
199 var nLastLine = editor.lastLine();
200 if ((event.keyCode === 40) &&
201 ((cur.line !== nLastLine) ||
202 (cur.ch !== editor.getLineHandle(nLastLine).text.length))
203 ) {
202 204 event._ipkmIgnore = true;
203 205 }
204 206 // if this is an edit_shortcuts shortcut, the global keyboard/shortcut
@@ -255,6 +257,14 b' define(['
255 257 };
256 258
257 259 /**
260 * should be overritten by subclass
261 * @method execute
262 */
263 Cell.prototype.execute = function () {
264 return;
265 };
266
267 /**
258 268 * handle cell level logic when a cell is rendered
259 269 * @method render
260 270 * @return is the action being taken
@@ -386,7 +396,9 b' define(['
386 396 * @method refresh
387 397 */
388 398 Cell.prototype.refresh = function () {
389 this.code_mirror.refresh();
399 if (this.code_mirror) {
400 this.code_mirror.refresh();
401 }
390 402 };
391 403
392 404 /**
@@ -590,8 +602,74 b' define(['
590 602 this.code_mirror.setOption('mode', default_mode);
591 603 };
592 604
605 var UnrecognizedCell = function (options) {
606 /** Constructor for unrecognized cells */
607 Cell.apply(this, arguments);
608 this.cell_type = 'unrecognized';
609 this.celltoolbar = null;
610 this.data = {};
611
612 Object.seal(this);
613 };
614
615 UnrecognizedCell.prototype = Object.create(Cell.prototype);
616
617
618 // cannot merge or split unrecognized cells
619 UnrecognizedCell.prototype.is_mergeable = function () {
620 return false;
621 };
622
623 UnrecognizedCell.prototype.is_splittable = function () {
624 return false;
625 };
626
627 UnrecognizedCell.prototype.toJSON = function () {
628 // deepcopy the metadata so copied cells don't share the same object
629 return JSON.parse(JSON.stringify(this.data));
630 };
631
632 UnrecognizedCell.prototype.fromJSON = function (data) {
633 this.data = data;
634 if (data.metadata !== undefined) {
635 this.metadata = data.metadata;
636 } else {
637 data.metadata = this.metadata;
638 }
639 this.element.find('.inner_cell').find("a").text("Unrecognized cell type: " + data.cell_type);
640 };
641
642 UnrecognizedCell.prototype.create_element = function () {
643 Cell.prototype.create_element.apply(this, arguments);
644 var cell = this.element = $("<div>").addClass('cell unrecognized_cell');
645 cell.attr('tabindex','2');
646
647 var prompt = $('<div/>').addClass('prompt input_prompt');
648 cell.append(prompt);
649 var inner_cell = $('<div/>').addClass('inner_cell');
650 inner_cell.append(
651 $("<a>")
652 .attr("href", "#")
653 .text("Unrecognized cell type")
654 );
655 cell.append(inner_cell);
656 this.element = cell;
657 };
658
659 UnrecognizedCell.prototype.bind_events = function () {
660 Cell.prototype.bind_events.apply(this, arguments);
661 var cell = this;
662
663 this.element.find('.inner_cell').find("a").click(function () {
664 cell.events.trigger('unrecognized_cell.Cell', {cell: cell})
665 });
666 };
667
593 668 // Backwards compatibility.
594 669 IPython.Cell = Cell;
595 670
596 return {'Cell': Cell};
671 return {
672 Cell: Cell,
673 UnrecognizedCell: UnrecognizedCell
674 };
597 675 });
@@ -6,6 +6,7 b' define(['
6 6 'jquery',
7 7 'base/js/utils',
8 8 'base/js/dialog',
9 'notebook/js/cell',
9 10 'notebook/js/textcell',
10 11 'notebook/js/codecell',
11 12 'services/sessions/session',
@@ -22,13 +23,14 b' define(['
22 23 'notebook/js/scrollmanager'
23 24 ], function (
24 25 IPython,
25 $,
26 utils,
27 dialog,
28 textcell,
29 codecell,
26 $,
27 utils,
28 dialog,
29 cellmod,
30 textcell,
31 codecell,
30 32 session,
31 celltoolbar,
33 celltoolbar,
32 34 marked,
33 35 CodeMirror,
34 36 runMode,
@@ -147,7 +149,7 b' define(['
147 149 this.minimum_autosave_interval = 120000;
148 150 this.notebook_name_blacklist_re = /[\/\\:]/;
149 151 this.nbformat = 4; // Increment this when changing the nbformat
150 this.nbformat_minor = 0; // Increment this when changing the nbformat
152 this.nbformat_minor = this.current_nbformat_minor = 0; // Increment this when changing the nbformat
151 153 this.codemirror_mode = 'ipython';
152 154 this.create_elements();
153 155 this.bind_events();
@@ -211,6 +213,14 b' define(['
211 213 that.dirty = true;
212 214 });
213 215
216 this.events.on('unrecognized_cell.Cell', function () {
217 that.warn_nbformat_minor();
218 });
219
220 this.events.on('unrecognized_output.OutputArea', function () {
221 that.warn_nbformat_minor();
222 });
223
214 224 this.events.on('set_dirty.Notebook', function (event, data) {
215 225 that.dirty = data.value;
216 226 });
@@ -304,6 +314,28 b' define(['
304 314 return null;
305 315 };
306 316 };
317
318 Notebook.prototype.warn_nbformat_minor = function (event) {
319 // trigger a warning dialog about missing functionality from newer minor versions
320 var v = 'v' + this.nbformat + '.';
321 var orig_vs = v + this.nbformat_minor;
322 var this_vs = v + this.current_nbformat_minor;
323 var msg = "This notebook is version " + orig_vs + ", but we only fully support up to " +
324 this_vs + ". You can still work with this notebook, but cell and output types " +
325 "introduced in later notebook versions will not be available.";
326
327 dialog.modal({
328 notebook: this,
329 keyboard_manager: this.keyboard_manager,
330 title : "Newer Notebook",
331 body : msg,
332 buttons : {
333 OK : {
334 "class" : "btn-danger"
335 }
336 }
337 });
338 }
307 339
308 340 /**
309 341 * Set the dirty flag, and trigger the set_dirty.Notebook event
@@ -900,7 +932,8 b' define(['
900 932 cell = new textcell.RawCell(cell_options);
901 933 break;
902 934 default:
903 console.log("invalid cell type: ", type);
935 console.log("Unrecognized cell type: ", type, cellmod);
936 cell = new cellmod.UnrecognizedCell(cell_options);
904 937 }
905 938
906 939 if(this._insert_element_at_index(cell.element,index)) {
@@ -2222,26 +2255,8 b' define(['
2222 2255 }
2223 2256 }
2224 2257 });
2225 } else if (orig_nbformat_minor !== undefined && nbmodel.nbformat_minor < orig_nbformat_minor) {
2226 var that = this;
2227 var orig_vs = 'v' + nbmodel.nbformat + '.' + orig_nbformat_minor;
2228 var this_vs = 'v' + nbmodel.nbformat + '.' + this.nbformat_minor;
2229 msg = "This notebook is version " + orig_vs + ", but we only fully support up to " +
2230 this_vs + ". You can still work with this notebook, but some features " +
2231 "introduced in later notebook versions may not be available.";
2232
2233 dialog.modal({
2234 notebook: this,
2235 keyboard_manager: this.keyboard_manager,
2236 title : "Newer Notebook",
2237 body : msg,
2238 buttons : {
2239 OK : {
2240 class : "btn-danger"
2241 }
2242 }
2243 });
2244
2258 } else if (this.nbformat_minor < nbmodel.nbformat_minor) {
2259 this.nbformat_minor = nbmodel.nbformat_minor;
2245 2260 }
2246 2261
2247 2262 // Create the session after the notebook is completely loaded to prevent
@@ -245,7 +245,7 b' define(['
245 245 'text/plain'
246 246 ];
247 247
248 OutputArea.prototype.validate_output = function (json) {
248 OutputArea.prototype.validate_mimebundle = function (json) {
249 249 // scrub invalid outputs
250 250 var data = json.data;
251 251 $.map(OutputArea.output_types, function(key){
@@ -263,11 +263,6 b' define(['
263 263 OutputArea.prototype.append_output = function (json) {
264 264 this.expand();
265 265
266 // validate output data types
267 if (json.data) {
268 json = this.validate_output(json);
269 }
270
271 266 // Clear the output if clear is queued.
272 267 var needs_height_reset = false;
273 268 if (this.clear_queued) {
@@ -276,14 +271,25 b' define(['
276 271 }
277 272
278 273 var record_output = true;
279
280 if (json.output_type === 'execute_result') {
281 this.append_execute_result(json);
282 } else if (json.output_type === 'error') {
283 this.append_error(json);
284 } else if (json.output_type === 'stream') {
285 // append_stream might have merged the output with earlier stream output
286 record_output = this.append_stream(json);
274 switch(json.output_type) {
275 case 'execute_result':
276 json = this.validate_mimebundle(json);
277 this.append_execute_result(json);
278 break;
279 case 'stream':
280 // append_stream might have merged the output with earlier stream output
281 record_output = this.append_stream(json);
282 break;
283 case 'error':
284 this.append_error(json);
285 break;
286 case 'display_data':
287 // append handled below
288 json = this.validate_mimebundle(json);
289 break;
290 default:
291 console.log("unrecognized output type: " + json.output_type);
292 this.append_unrecognized(json);
287 293 }
288 294
289 295 // We must release the animation fixed height in a callback since Gecko
@@ -485,6 +491,23 b' define(['
485 491 };
486 492
487 493
494 OutputArea.prototype.append_unrecognized = function (json) {
495 var that = this;
496 var toinsert = this.create_output_area();
497 var subarea = $('<div/>').addClass('output_subarea output_unrecognized');
498 toinsert.append(subarea);
499 subarea.append(
500 $("<a>")
501 .attr("href", "#")
502 .text("Unrecognized output: " + json.output_type)
503 .click(function () {
504 that.events.trigger('unrecognized_output.OutputArea', {output: json})
505 })
506 );
507 this._safe_append(toinsert);
508 };
509
510
488 511 OutputArea.prototype.append_display_data = function (json, handle_inserted) {
489 512 var toinsert = this.create_output_area();
490 513 if (this.append_mime_type(json, toinsert, handle_inserted)) {
@@ -338,7 +338,7 b' define(['
338 338 var textcell = {
339 339 TextCell: TextCell,
340 340 MarkdownCell: MarkdownCell,
341 RawCell: RawCell,
341 RawCell: RawCell
342 342 };
343 343 return textcell;
344 344 });
@@ -61,3 +61,34 b' div.prompt:empty {'
61 61 padding-top: 0;
62 62 padding-bottom: 0;
63 63 }
64
65 div.unrecognized_cell {
66 // from text_cell
67 padding: 5px 5px 5px 0px;
68 .hbox();
69
70 .inner_cell {
71 .border-radius(@border-radius-base);
72 padding: 5px;
73 font-weight: bold;
74 color: red;
75 border: 1px solid @light_border_color;
76 background: darken(@cell_background, 5%);
77 // remove decoration from link
78 a {
79 color: inherit;
80 text-decoration: none;
81
82 &:hover {
83 color: inherit;
84 text-decoration: none;
85 }
86 }
87 }
88 }
89 @media (max-width: 480px) {
90 // remove prompt indentation on small screens
91 div.unrecognized_cell > div.prompt {
92 display: none;
93 }
94 }
@@ -172,3 +172,19 b' input.raw_input:focus {'
172 172 p.p-space {
173 173 margin-bottom: 10px;
174 174 }
175
176 div.output_unrecognized {
177 padding: 5px;
178 font-weight: bold;
179 color: red;
180 // remove decoration from link
181 a {
182 color: inherit;
183 text-decoration: none;
184
185 &:hover {
186 color: inherit;
187 text-decoration: none;
188 }
189 }
190 } No newline at end of file
@@ -419,6 +419,44 b' div.prompt:empty {'
419 419 padding-top: 0;
420 420 padding-bottom: 0;
421 421 }
422 div.unrecognized_cell {
423 padding: 5px 5px 5px 0px;
424 /* Old browsers */
425 display: -webkit-box;
426 -webkit-box-orient: horizontal;
427 -webkit-box-align: stretch;
428 display: -moz-box;
429 -moz-box-orient: horizontal;
430 -moz-box-align: stretch;
431 display: box;
432 box-orient: horizontal;
433 box-align: stretch;
434 /* Modern browsers */
435 display: flex;
436 flex-direction: row;
437 align-items: stretch;
438 }
439 div.unrecognized_cell .inner_cell {
440 border-radius: 4px;
441 padding: 5px;
442 font-weight: bold;
443 color: red;
444 border: 1px solid #cfcfcf;
445 background: #eaeaea;
446 }
447 div.unrecognized_cell .inner_cell a {
448 color: inherit;
449 text-decoration: none;
450 }
451 div.unrecognized_cell .inner_cell a:hover {
452 color: inherit;
453 text-decoration: none;
454 }
455 @media (max-width: 480px) {
456 div.unrecognized_cell > div.prompt {
457 display: none;
458 }
459 }
422 460 /* any special styling for code cells that are currently running goes here */
423 461 div.input {
424 462 page-break-inside: avoid;
@@ -888,6 +926,19 b' input.raw_input:focus {'
888 926 p.p-space {
889 927 margin-bottom: 10px;
890 928 }
929 div.output_unrecognized {
930 padding: 5px;
931 font-weight: bold;
932 color: red;
933 }
934 div.output_unrecognized a {
935 color: inherit;
936 text-decoration: none;
937 }
938 div.output_unrecognized a:hover {
939 color: inherit;
940 text-decoration: none;
941 }
891 942 .rendered_html {
892 943 color: #000000;
893 944 /* any extras will just be numbers: */
@@ -8291,6 +8291,44 b' div.prompt:empty {'
8291 8291 padding-top: 0;
8292 8292 padding-bottom: 0;
8293 8293 }
8294 div.unrecognized_cell {
8295 padding: 5px 5px 5px 0px;
8296 /* Old browsers */
8297 display: -webkit-box;
8298 -webkit-box-orient: horizontal;
8299 -webkit-box-align: stretch;
8300 display: -moz-box;
8301 -moz-box-orient: horizontal;
8302 -moz-box-align: stretch;
8303 display: box;
8304 box-orient: horizontal;
8305 box-align: stretch;
8306 /* Modern browsers */
8307 display: flex;
8308 flex-direction: row;
8309 align-items: stretch;
8310 }
8311 div.unrecognized_cell .inner_cell {
8312 border-radius: 4px;
8313 padding: 5px;
8314 font-weight: bold;
8315 color: red;
8316 border: 1px solid #cfcfcf;
8317 background: #eaeaea;
8318 }
8319 div.unrecognized_cell .inner_cell a {
8320 color: inherit;
8321 text-decoration: none;
8322 }
8323 div.unrecognized_cell .inner_cell a:hover {
8324 color: inherit;
8325 text-decoration: none;
8326 }
8327 @media (max-width: 480px) {
8328 div.unrecognized_cell > div.prompt {
8329 display: none;
8330 }
8331 }
8294 8332 /* any special styling for code cells that are currently running goes here */
8295 8333 div.input {
8296 8334 page-break-inside: avoid;
@@ -8760,6 +8798,19 b' input.raw_input:focus {'
8760 8798 p.p-space {
8761 8799 margin-bottom: 10px;
8762 8800 }
8801 div.output_unrecognized {
8802 padding: 5px;
8803 font-weight: bold;
8804 color: red;
8805 }
8806 div.output_unrecognized a {
8807 color: inherit;
8808 text-decoration: none;
8809 }
8810 div.output_unrecognized a:hover {
8811 color: inherit;
8812 text-decoration: none;
8813 }
8763 8814 .rendered_html {
8764 8815 color: #000000;
8765 8816 /* any extras will just be numbers: */
@@ -306,6 +306,41 b''
306 306 "from IPython.display import Image\n",
307 307 "Image(\"http://ipython.org/_static/IPy_header.png\")"
308 308 ]
309 },
310 {
311 "cell_type": "future cell",
312 "metadata": {},
313 "key": "value"
314 },
315 {
316 "cell_type": "code",
317 "execution_count": 99,
318 "metadata": {},
319 "outputs": [
320 {
321 "name": "stdout",
322 "output_type": "stream",
323 "text": [
324 "hello\n"
325 ]
326 },
327 {
328 "output_type": "future output",
329 "some key": [
330 "some data"
331 ]
332 },
333 {
334 "name": "stdout",
335 "output_type": "stream",
336 "text": [
337 "hello again\n"
338 ]
339 }
340 ],
341 "source": [
342 "future_output()"
343 ]
309 344 }
310 345 ],
311 346 "metadata": {},
@@ -54,18 +54,19 b''
54 54 "cells": {
55 55 "description": "Array of cells of the current notebook.",
56 56 "type": "array",
57 "items": {
58 "type": "object",
59 "oneOf": [
60 {"$ref": "#/definitions/raw_cell"},
61 {"$ref": "#/definitions/markdown_cell"},
62 {"$ref": "#/definitions/code_cell"}
63 ]
64 }
57 "items": {"$ref": "#/definitions/cell"}
65 58 }
66 59 },
67 60
68 61 "definitions": {
62 "cell": {
63 "type": "object",
64 "oneOf": [
65 {"$ref": "#/definitions/raw_cell"},
66 {"$ref": "#/definitions/markdown_cell"},
67 {"$ref": "#/definitions/code_cell"}
68 ]
69 },
69 70
70 71 "raw_cell": {
71 72 "description": "Notebook raw nbconvert cell.",
@@ -157,6 +158,31 b''
157 158 }
158 159 }
159 160 },
161
162 "unrecognized_cell": {
163 "description": "Unrecognized cell from a future minor-revision to the notebook format.",
164 "type": "object",
165 "additionalProperties": true,
166 "required": ["cell_type", "metadata"],
167 "properties": {
168 "cell_type": {
169 "description": "String identifying the type of cell.",
170 "not" : {
171 "enum": ["markdown", "code", "raw"]
172 }
173 },
174 "metadata": {
175 "description": "Cell-level metadata.",
176 "type": "object",
177 "properties": {
178 "name": {"$ref": "#/definitions/misc/metadata_name"},
179 "tags": {"$ref": "#/definitions/misc/metadata_tags"}
180 },
181 "additionalProperties": true
182 }
183 }
184 },
185
160 186 "output": {
161 187 "type": "object",
162 188 "oneOf": [
@@ -249,6 +275,21 b''
249 275 }
250 276 },
251 277
278 "unrecognized_output": {
279 "description": "Unrecognized output from a future minor-revision to the notebook format.",
280 "type": "object",
281 "additionalProperties": true,
282 "required": ["output_type"],
283 "properties": {
284 "output_type": {
285 "description": "Type of cell output.",
286 "not": {
287 "enum": ["execute_result", "display_data", "stream", "error"]
288 }
289 }
290 }
291 },
292
252 293 "misc": {
253 294 "metadata_name": {
254 295 "description": "The cell's name. If present, must be a non-empty string.",
@@ -30,7 +30,6 b' def _relax_additional_properties(obj):'
30 30 if isinstance(obj, dict):
31 31 for key, value in obj.items():
32 32 if key == 'additionalProperties':
33 print(obj)
34 33 value = True
35 34 else:
36 35 value = _relax_additional_properties(value)
@@ -40,6 +39,15 b' def _relax_additional_properties(obj):'
40 39 obj[i] = _relax_additional_properties(value)
41 40 return obj
42 41
42 def _allow_undefined(schema):
43 schema['definitions']['cell']['oneOf'].append(
44 {"$ref": "#/definitions/unrecognized_cell"}
45 )
46 schema['definitions']['output']['oneOf'].append(
47 {"$ref": "#/definitions/unrecognized_output"}
48 )
49 return schema
50
43 51 def get_validator(version=None, version_minor=None):
44 52 """Load the JSON schema into a Validator"""
45 53 if version is None:
@@ -66,6 +74,8 b' def get_validator(version=None, version_minor=None):'
66 74 if current_minor < version_minor:
67 75 # notebook from the future, relax all `additionalProperties: False` requirements
68 76 schema_json = _relax_additional_properties(schema_json)
77 # and allow undefined cell types and outputs
78 schema_json = _allow_undefined(schema_json)
69 79
70 80 validators[version_tuple] = Validator(schema_json)
71 81 return validators[version_tuple]
General Comments 0
You need to be logged in to leave comments. Login now