Merge pull request #6991 from minrk/unhandled-types

Handle unrecognized output and cell types
This commit is contained in:
Thomas Kluyver 2014-11-30 19:13:55 -08:00
commit eb14a13843
8 changed files with 316 additions and 51 deletions

View File

@ -53,7 +53,9 @@ define([
get: function() { return that._metadata; },
set: function(value) {
that._metadata = value;
that.celltoolbar.rebuild();
if (that.celltoolbar) {
that.celltoolbar.rebuild();
}
}
});
@ -194,11 +196,11 @@ define([
if((cur.line !== 0 || cur.ch !==0) && event.keyCode === 38){
event._ipkmIgnore = true;
}
var nLastLine = editor.lastLine()
if( ( event.keyCode === 40)
&& (( cur.line !== nLastLine)
|| ( cur.ch !== editor.getLineHandle(nLastLine).text.length))
){
var nLastLine = editor.lastLine();
if ((event.keyCode === 40) &&
((cur.line !== nLastLine) ||
(cur.ch !== editor.getLineHandle(nLastLine).text.length))
) {
event._ipkmIgnore = true;
}
// if this is an edit_shortcuts shortcut, the global keyboard/shortcut
@ -254,6 +256,14 @@ define([
}
};
/**
* should be overritten by subclass
* @method execute
*/
Cell.prototype.execute = function () {
return;
};
/**
* handle cell level logic when a cell is rendered
* @method render
@ -386,7 +396,9 @@ define([
* @method refresh
*/
Cell.prototype.refresh = function () {
this.code_mirror.refresh();
if (this.code_mirror) {
this.code_mirror.refresh();
}
};
/**
@ -590,8 +602,74 @@ define([
this.code_mirror.setOption('mode', default_mode);
};
var UnrecognizedCell = function (options) {
/** Constructor for unrecognized cells */
Cell.apply(this, arguments);
this.cell_type = 'unrecognized';
this.celltoolbar = null;
this.data = {};
Object.seal(this);
};
UnrecognizedCell.prototype = Object.create(Cell.prototype);
// cannot merge or split unrecognized cells
UnrecognizedCell.prototype.is_mergeable = function () {
return false;
};
UnrecognizedCell.prototype.is_splittable = function () {
return false;
};
UnrecognizedCell.prototype.toJSON = function () {
// deepcopy the metadata so copied cells don't share the same object
return JSON.parse(JSON.stringify(this.data));
};
UnrecognizedCell.prototype.fromJSON = function (data) {
this.data = data;
if (data.metadata !== undefined) {
this.metadata = data.metadata;
} else {
data.metadata = this.metadata;
}
this.element.find('.inner_cell').find("a").text("Unrecognized cell type: " + data.cell_type);
};
UnrecognizedCell.prototype.create_element = function () {
Cell.prototype.create_element.apply(this, arguments);
var cell = this.element = $("<div>").addClass('cell unrecognized_cell');
cell.attr('tabindex','2');
var prompt = $('<div/>').addClass('prompt input_prompt');
cell.append(prompt);
var inner_cell = $('<div/>').addClass('inner_cell');
inner_cell.append(
$("<a>")
.attr("href", "#")
.text("Unrecognized cell type")
);
cell.append(inner_cell);
this.element = cell;
};
UnrecognizedCell.prototype.bind_events = function () {
Cell.prototype.bind_events.apply(this, arguments);
var cell = this;
this.element.find('.inner_cell').find("a").click(function () {
cell.events.trigger('unrecognized_cell.Cell', {cell: cell})
});
};
// Backwards compatibility.
IPython.Cell = Cell;
return {'Cell': Cell};
return {
Cell: Cell,
UnrecognizedCell: UnrecognizedCell
};
});

View File

@ -6,6 +6,7 @@ define([
'jquery',
'base/js/utils',
'base/js/dialog',
'notebook/js/cell',
'notebook/js/textcell',
'notebook/js/codecell',
'services/sessions/session',
@ -22,13 +23,14 @@ define([
'notebook/js/scrollmanager'
], function (
IPython,
$,
utils,
dialog,
textcell,
codecell,
$,
utils,
dialog,
cellmod,
textcell,
codecell,
session,
celltoolbar,
celltoolbar,
marked,
CodeMirror,
runMode,
@ -147,7 +149,7 @@ define([
this.minimum_autosave_interval = 120000;
this.notebook_name_blacklist_re = /[\/\\:]/;
this.nbformat = 4; // Increment this when changing the nbformat
this.nbformat_minor = 0; // Increment this when changing the nbformat
this.nbformat_minor = this.current_nbformat_minor = 0; // Increment this when changing the nbformat
this.codemirror_mode = 'ipython';
this.create_elements();
this.bind_events();
@ -211,6 +213,14 @@ define([
that.dirty = true;
});
this.events.on('unrecognized_cell.Cell', function () {
that.warn_nbformat_minor();
});
this.events.on('unrecognized_output.OutputArea', function () {
that.warn_nbformat_minor();
});
this.events.on('set_dirty.Notebook', function (event, data) {
that.dirty = data.value;
});
@ -304,6 +314,28 @@ define([
return null;
};
};
Notebook.prototype.warn_nbformat_minor = function (event) {
// trigger a warning dialog about missing functionality from newer minor versions
var v = 'v' + this.nbformat + '.';
var orig_vs = v + this.nbformat_minor;
var this_vs = v + this.current_nbformat_minor;
var msg = "This notebook is version " + orig_vs + ", but we only fully support up to " +
this_vs + ". You can still work with this notebook, but cell and output types " +
"introduced in later notebook versions will not be available.";
dialog.modal({
notebook: this,
keyboard_manager: this.keyboard_manager,
title : "Newer Notebook",
body : msg,
buttons : {
OK : {
"class" : "btn-danger"
}
}
});
}
/**
* Set the dirty flag, and trigger the set_dirty.Notebook event
@ -900,7 +932,8 @@ define([
cell = new textcell.RawCell(cell_options);
break;
default:
console.log("invalid cell type: ", type);
console.log("Unrecognized cell type: ", type, cellmod);
cell = new cellmod.UnrecognizedCell(cell_options);
}
if(this._insert_element_at_index(cell.element,index)) {
@ -2222,26 +2255,8 @@ define([
}
}
});
} else if (orig_nbformat_minor !== undefined && nbmodel.nbformat_minor < orig_nbformat_minor) {
var that = this;
var orig_vs = 'v' + nbmodel.nbformat + '.' + orig_nbformat_minor;
var this_vs = 'v' + nbmodel.nbformat + '.' + this.nbformat_minor;
msg = "This notebook is version " + orig_vs + ", but we only fully support up to " +
this_vs + ". You can still work with this notebook, but some features " +
"introduced in later notebook versions may not be available.";
dialog.modal({
notebook: this,
keyboard_manager: this.keyboard_manager,
title : "Newer Notebook",
body : msg,
buttons : {
OK : {
class : "btn-danger"
}
}
});
} else if (this.nbformat_minor < nbmodel.nbformat_minor) {
this.nbformat_minor = nbmodel.nbformat_minor;
}
// Create the session after the notebook is completely loaded to prevent

View File

@ -245,7 +245,7 @@ define([
'text/plain'
];
OutputArea.prototype.validate_output = function (json) {
OutputArea.prototype.validate_mimebundle = function (json) {
// scrub invalid outputs
var data = json.data;
$.map(OutputArea.output_types, function(key){
@ -263,11 +263,6 @@ define([
OutputArea.prototype.append_output = function (json) {
this.expand();
// validate output data types
if (json.data) {
json = this.validate_output(json);
}
// Clear the output if clear is queued.
var needs_height_reset = false;
if (this.clear_queued) {
@ -276,14 +271,25 @@ define([
}
var record_output = true;
if (json.output_type === 'execute_result') {
this.append_execute_result(json);
} else if (json.output_type === 'error') {
this.append_error(json);
} else if (json.output_type === 'stream') {
// append_stream might have merged the output with earlier stream output
record_output = this.append_stream(json);
switch(json.output_type) {
case 'execute_result':
json = this.validate_mimebundle(json);
this.append_execute_result(json);
break;
case 'stream':
// append_stream might have merged the output with earlier stream output
record_output = this.append_stream(json);
break;
case 'error':
this.append_error(json);
break;
case 'display_data':
// append handled below
json = this.validate_mimebundle(json);
break;
default:
console.log("unrecognized output type: " + json.output_type);
this.append_unrecognized(json);
}
// We must release the animation fixed height in a callback since Gecko
@ -485,6 +491,23 @@ define([
};
OutputArea.prototype.append_unrecognized = function (json) {
var that = this;
var toinsert = this.create_output_area();
var subarea = $('<div/>').addClass('output_subarea output_unrecognized');
toinsert.append(subarea);
subarea.append(
$("<a>")
.attr("href", "#")
.text("Unrecognized output: " + json.output_type)
.click(function () {
that.events.trigger('unrecognized_output.OutputArea', {output: json})
})
);
this._safe_append(toinsert);
};
OutputArea.prototype.append_display_data = function (json, handle_inserted) {
var toinsert = this.create_output_area();
if (this.append_mime_type(json, toinsert, handle_inserted)) {

View File

@ -338,7 +338,7 @@ define([
var textcell = {
TextCell: TextCell,
MarkdownCell: MarkdownCell,
RawCell: RawCell,
RawCell: RawCell
};
return textcell;
});

View File

@ -61,3 +61,34 @@ div.prompt:empty {
padding-top: 0;
padding-bottom: 0;
}
div.unrecognized_cell {
// from text_cell
padding: 5px 5px 5px 0px;
.hbox();
.inner_cell {
.border-radius(@border-radius-base);
padding: 5px;
font-weight: bold;
color: red;
border: 1px solid @light_border_color;
background: darken(@cell_background, 5%);
// remove decoration from link
a {
color: inherit;
text-decoration: none;
&:hover {
color: inherit;
text-decoration: none;
}
}
}
}
@media (max-width: 480px) {
// remove prompt indentation on small screens
div.unrecognized_cell > div.prompt {
display: none;
}
}

View File

@ -172,3 +172,19 @@ input.raw_input:focus {
p.p-space {
margin-bottom: 10px;
}
div.output_unrecognized {
padding: 5px;
font-weight: bold;
color: red;
// remove decoration from link
a {
color: inherit;
text-decoration: none;
&:hover {
color: inherit;
text-decoration: none;
}
}
}

View File

@ -419,6 +419,44 @@ div.prompt:empty {
padding-top: 0;
padding-bottom: 0;
}
div.unrecognized_cell {
padding: 5px 5px 5px 0px;
/* Old browsers */
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
display: box;
box-orient: horizontal;
box-align: stretch;
/* Modern browsers */
display: flex;
flex-direction: row;
align-items: stretch;
}
div.unrecognized_cell .inner_cell {
border-radius: 4px;
padding: 5px;
font-weight: bold;
color: red;
border: 1px solid #cfcfcf;
background: #eaeaea;
}
div.unrecognized_cell .inner_cell a {
color: inherit;
text-decoration: none;
}
div.unrecognized_cell .inner_cell a:hover {
color: inherit;
text-decoration: none;
}
@media (max-width: 480px) {
div.unrecognized_cell > div.prompt {
display: none;
}
}
/* any special styling for code cells that are currently running goes here */
div.input {
page-break-inside: avoid;
@ -888,6 +926,19 @@ input.raw_input:focus {
p.p-space {
margin-bottom: 10px;
}
div.output_unrecognized {
padding: 5px;
font-weight: bold;
color: red;
}
div.output_unrecognized a {
color: inherit;
text-decoration: none;
}
div.output_unrecognized a:hover {
color: inherit;
text-decoration: none;
}
.rendered_html {
color: #000000;
/* any extras will just be numbers: */

View File

@ -8291,6 +8291,44 @@ div.prompt:empty {
padding-top: 0;
padding-bottom: 0;
}
div.unrecognized_cell {
padding: 5px 5px 5px 0px;
/* Old browsers */
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
display: box;
box-orient: horizontal;
box-align: stretch;
/* Modern browsers */
display: flex;
flex-direction: row;
align-items: stretch;
}
div.unrecognized_cell .inner_cell {
border-radius: 4px;
padding: 5px;
font-weight: bold;
color: red;
border: 1px solid #cfcfcf;
background: #eaeaea;
}
div.unrecognized_cell .inner_cell a {
color: inherit;
text-decoration: none;
}
div.unrecognized_cell .inner_cell a:hover {
color: inherit;
text-decoration: none;
}
@media (max-width: 480px) {
div.unrecognized_cell > div.prompt {
display: none;
}
}
/* any special styling for code cells that are currently running goes here */
div.input {
page-break-inside: avoid;
@ -8760,6 +8798,19 @@ input.raw_input:focus {
p.p-space {
margin-bottom: 10px;
}
div.output_unrecognized {
padding: 5px;
font-weight: bold;
color: red;
}
div.output_unrecognized a {
color: inherit;
text-decoration: none;
}
div.output_unrecognized a:hover {
color: inherit;
text-decoration: none;
}
.rendered_html {
color: #000000;
/* any extras will just be numbers: */