##// END OF EJS Templates
Notebook id removed from the notebook format.
Brian E. Granger -
Show More
@@ -1,813 +1,812 b''
1
1
2 //============================================================================
2 //============================================================================
3 // Notebook
3 // Notebook
4 //============================================================================
4 //============================================================================
5
5
6 var IPython = (function (IPython) {
6 var IPython = (function (IPython) {
7
7
8 var utils = IPython.utils;
8 var utils = IPython.utils;
9
9
10 var Notebook = function (selector) {
10 var Notebook = function (selector) {
11 this.element = $(selector);
11 this.element = $(selector);
12 this.element.scroll();
12 this.element.scroll();
13 this.element.data("notebook", this);
13 this.element.data("notebook", this);
14 this.next_prompt_number = 1;
14 this.next_prompt_number = 1;
15 this.kernel = null;
15 this.kernel = null;
16 this.dirty = false;
16 this.dirty = false;
17 this.msg_cell_map = {};
17 this.msg_cell_map = {};
18 this.style();
18 this.style();
19 this.create_elements();
19 this.create_elements();
20 this.bind_events();
20 this.bind_events();
21 };
21 };
22
22
23
23
24 Notebook.prototype.style = function () {
24 Notebook.prototype.style = function () {
25 $('div#notebook').addClass('border-box-sizing');
25 $('div#notebook').addClass('border-box-sizing');
26 };
26 };
27
27
28
28
29 Notebook.prototype.create_elements = function () {
29 Notebook.prototype.create_elements = function () {
30 // We add this end_space div to the end of the notebook div to:
30 // We add this end_space div to the end of the notebook div to:
31 // i) provide a margin between the last cell and the end of the notebook
31 // i) provide a margin between the last cell and the end of the notebook
32 // ii) to prevent the div from scrolling up when the last cell is being
32 // ii) to prevent the div from scrolling up when the last cell is being
33 // edited, but is too low on the page, which browsers will do automatically.
33 // edited, but is too low on the page, which browsers will do automatically.
34 this.element.append($('<div class="end_space"></div>').height(50));
34 this.element.append($('<div class="end_space"></div>').height(50));
35 $('div#notebook').addClass('border-box-sizing');
35 $('div#notebook').addClass('border-box-sizing');
36 };
36 };
37
37
38
38
39 Notebook.prototype.bind_events = function () {
39 Notebook.prototype.bind_events = function () {
40 var that = this;
40 var that = this;
41 $(document).keydown(function (event) {
41 $(document).keydown(function (event) {
42 // console.log(event);
42 // console.log(event);
43 if (event.which === 38) {
43 if (event.which === 38) {
44 var cell = that.selected_cell();
44 var cell = that.selected_cell();
45 if (cell.at_top()) {
45 if (cell.at_top()) {
46 event.preventDefault();
46 event.preventDefault();
47 that.select_prev();
47 that.select_prev();
48 };
48 };
49 } else if (event.which === 40) {
49 } else if (event.which === 40) {
50 var cell = that.selected_cell();
50 var cell = that.selected_cell();
51 if (cell.at_bottom()) {
51 if (cell.at_bottom()) {
52 event.preventDefault();
52 event.preventDefault();
53 that.select_next();
53 that.select_next();
54 };
54 };
55 } else if (event.which === 13 && event.shiftKey) {
55 } else if (event.which === 13 && event.shiftKey) {
56 that.execute_selected_cell();
56 that.execute_selected_cell();
57 return false;
57 return false;
58 } else if (event.which === 13 && event.ctrlKey) {
58 } else if (event.which === 13 && event.ctrlKey) {
59 that.execute_selected_cell({terminal:true});
59 that.execute_selected_cell({terminal:true});
60 return false;
60 return false;
61 };
61 };
62 });
62 });
63
63
64 this.element.bind('collapse_pager', function () {
64 this.element.bind('collapse_pager', function () {
65 var app_height = $('div#main_app').height(); // content height
65 var app_height = $('div#main_app').height(); // content height
66 var splitter_height = $('div#pager_splitter').outerHeight(true);
66 var splitter_height = $('div#pager_splitter').outerHeight(true);
67 var new_height = app_height - splitter_height;
67 var new_height = app_height - splitter_height;
68 that.element.animate({height : new_height + 'px'}, 'fast');
68 that.element.animate({height : new_height + 'px'}, 'fast');
69 });
69 });
70
70
71 this.element.bind('expand_pager', function () {
71 this.element.bind('expand_pager', function () {
72 var app_height = $('div#main_app').height(); // content height
72 var app_height = $('div#main_app').height(); // content height
73 var splitter_height = $('div#pager_splitter').outerHeight(true);
73 var splitter_height = $('div#pager_splitter').outerHeight(true);
74 var pager_height = $('div#pager').outerHeight(true);
74 var pager_height = $('div#pager').outerHeight(true);
75 var new_height = app_height - pager_height - splitter_height;
75 var new_height = app_height - pager_height - splitter_height;
76 that.element.animate({height : new_height + 'px'}, 'fast');
76 that.element.animate({height : new_height + 'px'}, 'fast');
77 });
77 });
78
78
79 this.element.bind('collapse_left_panel', function () {
79 this.element.bind('collapse_left_panel', function () {
80 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
80 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
81 var new_margin = splitter_width;
81 var new_margin = splitter_width;
82 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
82 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
83 });
83 });
84
84
85 this.element.bind('expand_left_panel', function () {
85 this.element.bind('expand_left_panel', function () {
86 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
86 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
87 var left_panel_width = IPython.left_panel.width;
87 var left_panel_width = IPython.left_panel.width;
88 var new_margin = splitter_width + left_panel_width;
88 var new_margin = splitter_width + left_panel_width;
89 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
89 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
90 });
90 });
91
91
92 $(window).bind('beforeunload', function () {
92 $(window).bind('beforeunload', function () {
93 var kill_kernel = $('#kill_kernel').prop('checked');
93 var kill_kernel = $('#kill_kernel').prop('checked');
94 if (kill_kernel) {
94 if (kill_kernel) {
95 that.kernel.kill();
95 that.kernel.kill();
96 }
96 }
97 if (that.dirty) {
97 if (that.dirty) {
98 return "You have unsaved changes that will be lost if you leave this page.";
98 return "You have unsaved changes that will be lost if you leave this page.";
99 };
99 };
100 });
100 });
101 };
101 };
102
102
103
103
104 Notebook.prototype.scroll_to_bottom = function () {
104 Notebook.prototype.scroll_to_bottom = function () {
105 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
105 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
106 };
106 };
107
107
108
108
109 Notebook.prototype.scroll_to_top = function () {
109 Notebook.prototype.scroll_to_top = function () {
110 this.element.animate({scrollTop:0}, 0);
110 this.element.animate({scrollTop:0}, 0);
111 };
111 };
112
112
113
113
114 // Cell indexing, retrieval, etc.
114 // Cell indexing, retrieval, etc.
115
115
116
116
117 Notebook.prototype.cell_elements = function () {
117 Notebook.prototype.cell_elements = function () {
118 return this.element.children("div.cell");
118 return this.element.children("div.cell");
119 }
119 }
120
120
121
121
122 Notebook.prototype.ncells = function (cell) {
122 Notebook.prototype.ncells = function (cell) {
123 return this.cell_elements().length;
123 return this.cell_elements().length;
124 }
124 }
125
125
126
126
127 // TODO: we are often calling cells as cells()[i], which we should optimize
127 // TODO: we are often calling cells as cells()[i], which we should optimize
128 // to cells(i) or a new method.
128 // to cells(i) or a new method.
129 Notebook.prototype.cells = function () {
129 Notebook.prototype.cells = function () {
130 return this.cell_elements().toArray().map(function (e) {
130 return this.cell_elements().toArray().map(function (e) {
131 return $(e).data("cell");
131 return $(e).data("cell");
132 });
132 });
133 }
133 }
134
134
135
135
136 Notebook.prototype.find_cell_index = function (cell) {
136 Notebook.prototype.find_cell_index = function (cell) {
137 var result = null;
137 var result = null;
138 this.cell_elements().filter(function (index) {
138 this.cell_elements().filter(function (index) {
139 if ($(this).data("cell") === cell) {
139 if ($(this).data("cell") === cell) {
140 result = index;
140 result = index;
141 };
141 };
142 });
142 });
143 return result;
143 return result;
144 };
144 };
145
145
146
146
147 Notebook.prototype.index_or_selected = function (index) {
147 Notebook.prototype.index_or_selected = function (index) {
148 return index || this.selected_index() || 0;
148 return index || this.selected_index() || 0;
149 }
149 }
150
150
151
151
152 Notebook.prototype.select = function (index) {
152 Notebook.prototype.select = function (index) {
153 if (index !== undefined && index >= 0 && index < this.ncells()) {
153 if (index !== undefined && index >= 0 && index < this.ncells()) {
154 if (this.selected_index() !== null) {
154 if (this.selected_index() !== null) {
155 this.selected_cell().unselect();
155 this.selected_cell().unselect();
156 };
156 };
157 this.cells()[index].select();
157 this.cells()[index].select();
158 if (index === (this.ncells()-1)) {
158 if (index === (this.ncells()-1)) {
159 this.scroll_to_bottom();
159 this.scroll_to_bottom();
160 };
160 };
161 };
161 };
162 return this;
162 return this;
163 };
163 };
164
164
165
165
166 Notebook.prototype.select_next = function () {
166 Notebook.prototype.select_next = function () {
167 var index = this.selected_index();
167 var index = this.selected_index();
168 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
168 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
169 this.select(index+1);
169 this.select(index+1);
170 };
170 };
171 return this;
171 return this;
172 };
172 };
173
173
174
174
175 Notebook.prototype.select_prev = function () {
175 Notebook.prototype.select_prev = function () {
176 var index = this.selected_index();
176 var index = this.selected_index();
177 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
177 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
178 this.select(index-1);
178 this.select(index-1);
179 };
179 };
180 return this;
180 return this;
181 };
181 };
182
182
183
183
184 Notebook.prototype.selected_index = function () {
184 Notebook.prototype.selected_index = function () {
185 var result = null;
185 var result = null;
186 this.cell_elements().filter(function (index) {
186 this.cell_elements().filter(function (index) {
187 if ($(this).data("cell").selected === true) {
187 if ($(this).data("cell").selected === true) {
188 result = index;
188 result = index;
189 };
189 };
190 });
190 });
191 return result;
191 return result;
192 };
192 };
193
193
194
194
195 Notebook.prototype.cell_for_msg = function (msg_id) {
195 Notebook.prototype.cell_for_msg = function (msg_id) {
196 var cell_id = this.msg_cell_map[msg_id];
196 var cell_id = this.msg_cell_map[msg_id];
197 var result = null;
197 var result = null;
198 this.cell_elements().filter(function (index) {
198 this.cell_elements().filter(function (index) {
199 cell = $(this).data("cell");
199 cell = $(this).data("cell");
200 if (cell.cell_id === cell_id) {
200 if (cell.cell_id === cell_id) {
201 result = cell;
201 result = cell;
202 };
202 };
203 });
203 });
204 return result;
204 return result;
205 };
205 };
206
206
207
207
208 Notebook.prototype.selected_cell = function () {
208 Notebook.prototype.selected_cell = function () {
209 return this.cell_elements().eq(this.selected_index()).data("cell");
209 return this.cell_elements().eq(this.selected_index()).data("cell");
210 }
210 }
211
211
212
212
213 // Cell insertion, deletion and moving.
213 // Cell insertion, deletion and moving.
214
214
215
215
216 Notebook.prototype.delete_cell = function (index) {
216 Notebook.prototype.delete_cell = function (index) {
217 var i = index || this.selected_index();
217 var i = index || this.selected_index();
218 if (i !== null && i >= 0 && i < this.ncells()) {
218 if (i !== null && i >= 0 && i < this.ncells()) {
219 this.cell_elements().eq(i).remove();
219 this.cell_elements().eq(i).remove();
220 if (i === (this.ncells())) {
220 if (i === (this.ncells())) {
221 this.select(i-1);
221 this.select(i-1);
222 } else {
222 } else {
223 this.select(i);
223 this.select(i);
224 };
224 };
225 };
225 };
226 this.dirty = true;
226 this.dirty = true;
227 return this;
227 return this;
228 };
228 };
229
229
230
230
231 Notebook.prototype.append_cell = function (cell) {
231 Notebook.prototype.append_cell = function (cell) {
232 this.element.find('div.end_space').before(cell.element);
232 this.element.find('div.end_space').before(cell.element);
233 this.dirty = true;
233 this.dirty = true;
234 return this;
234 return this;
235 };
235 };
236
236
237
237
238 Notebook.prototype.insert_cell_after = function (cell, index) {
238 Notebook.prototype.insert_cell_after = function (cell, index) {
239 var ncells = this.ncells();
239 var ncells = this.ncells();
240 if (ncells === 0) {
240 if (ncells === 0) {
241 this.append_cell(cell);
241 this.append_cell(cell);
242 return this;
242 return this;
243 };
243 };
244 if (index >= 0 && index < ncells) {
244 if (index >= 0 && index < ncells) {
245 this.cell_elements().eq(index).after(cell.element);
245 this.cell_elements().eq(index).after(cell.element);
246 };
246 };
247 this.dirty = true;
247 this.dirty = true;
248 return this
248 return this
249 };
249 };
250
250
251
251
252 Notebook.prototype.insert_cell_before = function (cell, index) {
252 Notebook.prototype.insert_cell_before = function (cell, index) {
253 var ncells = this.ncells();
253 var ncells = this.ncells();
254 if (ncells === 0) {
254 if (ncells === 0) {
255 this.append_cell(cell);
255 this.append_cell(cell);
256 return this;
256 return this;
257 };
257 };
258 if (index >= 0 && index < ncells) {
258 if (index >= 0 && index < ncells) {
259 this.cell_elements().eq(index).before(cell.element);
259 this.cell_elements().eq(index).before(cell.element);
260 };
260 };
261 this.dirty = true;
261 this.dirty = true;
262 return this;
262 return this;
263 };
263 };
264
264
265
265
266 Notebook.prototype.move_cell_up = function (index) {
266 Notebook.prototype.move_cell_up = function (index) {
267 var i = index || this.selected_index();
267 var i = index || this.selected_index();
268 if (i !== null && i < this.ncells() && i > 0) {
268 if (i !== null && i < this.ncells() && i > 0) {
269 var pivot = this.cell_elements().eq(i-1);
269 var pivot = this.cell_elements().eq(i-1);
270 var tomove = this.cell_elements().eq(i);
270 var tomove = this.cell_elements().eq(i);
271 if (pivot !== null && tomove !== null) {
271 if (pivot !== null && tomove !== null) {
272 tomove.detach();
272 tomove.detach();
273 pivot.before(tomove);
273 pivot.before(tomove);
274 this.select(i-1);
274 this.select(i-1);
275 };
275 };
276 };
276 };
277 this.dirty = true;
277 this.dirty = true;
278 return this;
278 return this;
279 }
279 }
280
280
281
281
282 Notebook.prototype.move_cell_down = function (index) {
282 Notebook.prototype.move_cell_down = function (index) {
283 var i = index || this.selected_index();
283 var i = index || this.selected_index();
284 if (i !== null && i < (this.ncells()-1) && i >= 0) {
284 if (i !== null && i < (this.ncells()-1) && i >= 0) {
285 var pivot = this.cell_elements().eq(i+1)
285 var pivot = this.cell_elements().eq(i+1)
286 var tomove = this.cell_elements().eq(i)
286 var tomove = this.cell_elements().eq(i)
287 if (pivot !== null && tomove !== null) {
287 if (pivot !== null && tomove !== null) {
288 tomove.detach();
288 tomove.detach();
289 pivot.after(tomove);
289 pivot.after(tomove);
290 this.select(i+1);
290 this.select(i+1);
291 };
291 };
292 };
292 };
293 this.dirty = true;
293 this.dirty = true;
294 return this;
294 return this;
295 }
295 }
296
296
297
297
298 Notebook.prototype.sort_cells = function () {
298 Notebook.prototype.sort_cells = function () {
299 var ncells = this.ncells();
299 var ncells = this.ncells();
300 var sindex = this.selected_index();
300 var sindex = this.selected_index();
301 var swapped;
301 var swapped;
302 do {
302 do {
303 swapped = false
303 swapped = false
304 for (var i=1; i<ncells; i++) {
304 for (var i=1; i<ncells; i++) {
305 current = this.cell_elements().eq(i).data("cell");
305 current = this.cell_elements().eq(i).data("cell");
306 previous = this.cell_elements().eq(i-1).data("cell");
306 previous = this.cell_elements().eq(i-1).data("cell");
307 if (previous.input_prompt_number > current.input_prompt_number) {
307 if (previous.input_prompt_number > current.input_prompt_number) {
308 this.move_cell_up(i);
308 this.move_cell_up(i);
309 swapped = true;
309 swapped = true;
310 };
310 };
311 };
311 };
312 } while (swapped);
312 } while (swapped);
313 this.select(sindex);
313 this.select(sindex);
314 return this;
314 return this;
315 };
315 };
316
316
317
317
318 Notebook.prototype.insert_code_cell_before = function (index) {
318 Notebook.prototype.insert_code_cell_before = function (index) {
319 // TODO: Bounds check for i
319 // TODO: Bounds check for i
320 var i = this.index_or_selected(index);
320 var i = this.index_or_selected(index);
321 var cell = new IPython.CodeCell(this);
321 var cell = new IPython.CodeCell(this);
322 cell.set_input_prompt();
322 cell.set_input_prompt();
323 this.insert_cell_before(cell, i);
323 this.insert_cell_before(cell, i);
324 this.select(this.find_cell_index(cell));
324 this.select(this.find_cell_index(cell));
325 return cell;
325 return cell;
326 }
326 }
327
327
328
328
329 Notebook.prototype.insert_code_cell_after = function (index) {
329 Notebook.prototype.insert_code_cell_after = function (index) {
330 // TODO: Bounds check for i
330 // TODO: Bounds check for i
331 var i = this.index_or_selected(index);
331 var i = this.index_or_selected(index);
332 var cell = new IPython.CodeCell(this);
332 var cell = new IPython.CodeCell(this);
333 cell.set_input_prompt();
333 cell.set_input_prompt();
334 this.insert_cell_after(cell, i);
334 this.insert_cell_after(cell, i);
335 this.select(this.find_cell_index(cell));
335 this.select(this.find_cell_index(cell));
336 return cell;
336 return cell;
337 }
337 }
338
338
339
339
340 Notebook.prototype.insert_html_cell_before = function (index) {
340 Notebook.prototype.insert_html_cell_before = function (index) {
341 // TODO: Bounds check for i
341 // TODO: Bounds check for i
342 var i = this.index_or_selected(index);
342 var i = this.index_or_selected(index);
343 var cell = new IPython.HTMLCell(this);
343 var cell = new IPython.HTMLCell(this);
344 cell.config_mathjax();
344 cell.config_mathjax();
345 this.insert_cell_before(cell, i);
345 this.insert_cell_before(cell, i);
346 this.select(this.find_cell_index(cell));
346 this.select(this.find_cell_index(cell));
347 return cell;
347 return cell;
348 }
348 }
349
349
350
350
351 Notebook.prototype.insert_html_cell_after = function (index) {
351 Notebook.prototype.insert_html_cell_after = function (index) {
352 // TODO: Bounds check for i
352 // TODO: Bounds check for i
353 var i = this.index_or_selected(index);
353 var i = this.index_or_selected(index);
354 var cell = new IPython.HTMLCell(this);
354 var cell = new IPython.HTMLCell(this);
355 cell.config_mathjax();
355 cell.config_mathjax();
356 this.insert_cell_after(cell, i);
356 this.insert_cell_after(cell, i);
357 this.select(this.find_cell_index(cell));
357 this.select(this.find_cell_index(cell));
358 return cell;
358 return cell;
359 }
359 }
360
360
361
361
362 Notebook.prototype.insert_markdown_cell_before = function (index) {
362 Notebook.prototype.insert_markdown_cell_before = function (index) {
363 // TODO: Bounds check for i
363 // TODO: Bounds check for i
364 var i = this.index_or_selected(index);
364 var i = this.index_or_selected(index);
365 var cell = new IPython.MarkdownCell(this);
365 var cell = new IPython.MarkdownCell(this);
366 cell.config_mathjax();
366 cell.config_mathjax();
367 this.insert_cell_before(cell, i);
367 this.insert_cell_before(cell, i);
368 this.select(this.find_cell_index(cell));
368 this.select(this.find_cell_index(cell));
369 return cell;
369 return cell;
370 }
370 }
371
371
372
372
373 Notebook.prototype.insert_markdown_cell_after = function (index) {
373 Notebook.prototype.insert_markdown_cell_after = function (index) {
374 // TODO: Bounds check for i
374 // TODO: Bounds check for i
375 var i = this.index_or_selected(index);
375 var i = this.index_or_selected(index);
376 var cell = new IPython.MarkdownCell(this);
376 var cell = new IPython.MarkdownCell(this);
377 cell.config_mathjax();
377 cell.config_mathjax();
378 this.insert_cell_after(cell, i);
378 this.insert_cell_after(cell, i);
379 this.select(this.find_cell_index(cell));
379 this.select(this.find_cell_index(cell));
380 return cell;
380 return cell;
381 }
381 }
382
382
383
383
384 Notebook.prototype.to_code = function (index) {
384 Notebook.prototype.to_code = function (index) {
385 // TODO: Bounds check for i
385 // TODO: Bounds check for i
386 var i = this.index_or_selected(index);
386 var i = this.index_or_selected(index);
387 var source_element = this.cell_elements().eq(i);
387 var source_element = this.cell_elements().eq(i);
388 var source_cell = source_element.data("cell");
388 var source_cell = source_element.data("cell");
389 if (source_cell instanceof IPython.HTMLCell ||
389 if (source_cell instanceof IPython.HTMLCell ||
390 source_cell instanceof IPython.MarkdownCell) {
390 source_cell instanceof IPython.MarkdownCell) {
391 this.insert_code_cell_after(i);
391 this.insert_code_cell_after(i);
392 var target_cell = this.cells()[i+1];
392 var target_cell = this.cells()[i+1];
393 target_cell.set_code(source_cell.get_source());
393 target_cell.set_code(source_cell.get_source());
394 source_element.remove();
394 source_element.remove();
395 };
395 };
396 this.dirty = true;
396 this.dirty = true;
397 };
397 };
398
398
399
399
400 Notebook.prototype.to_markdown = function (index) {
400 Notebook.prototype.to_markdown = function (index) {
401 // TODO: Bounds check for i
401 // TODO: Bounds check for i
402 var i = this.index_or_selected(index);
402 var i = this.index_or_selected(index);
403 var source_element = this.cell_elements().eq(i);
403 var source_element = this.cell_elements().eq(i);
404 var source_cell = source_element.data("cell");
404 var source_cell = source_element.data("cell");
405 var target_cell = null;
405 var target_cell = null;
406 if (source_cell instanceof IPython.CodeCell) {
406 if (source_cell instanceof IPython.CodeCell) {
407 this.insert_markdown_cell_after(i);
407 this.insert_markdown_cell_after(i);
408 var target_cell = this.cells()[i+1];
408 var target_cell = this.cells()[i+1];
409 var text = source_cell.get_code();
409 var text = source_cell.get_code();
410 } else if (source_cell instanceof IPython.HTMLCell) {
410 } else if (source_cell instanceof IPython.HTMLCell) {
411 this.insert_markdown_cell_after(i);
411 this.insert_markdown_cell_after(i);
412 var target_cell = this.cells()[i+1];
412 var target_cell = this.cells()[i+1];
413 var text = source_cell.get_source();
413 var text = source_cell.get_source();
414 if (text === source_cell.placeholder) {
414 if (text === source_cell.placeholder) {
415 text = target_cell.placeholder;
415 text = target_cell.placeholder;
416 }
416 }
417 }
417 }
418 if (target_cell !== null) {
418 if (target_cell !== null) {
419 if (text === "") {text = target_cell.placeholder;};
419 if (text === "") {text = target_cell.placeholder;};
420 target_cell.set_source(text);
420 target_cell.set_source(text);
421 source_element.remove();
421 source_element.remove();
422 target_cell.edit();
422 target_cell.edit();
423 }
423 }
424 this.dirty = true;
424 this.dirty = true;
425 };
425 };
426
426
427
427
428 Notebook.prototype.to_html = function (index) {
428 Notebook.prototype.to_html = function (index) {
429 // TODO: Bounds check for i
429 // TODO: Bounds check for i
430 var i = this.index_or_selected(index);
430 var i = this.index_or_selected(index);
431 var source_element = this.cell_elements().eq(i);
431 var source_element = this.cell_elements().eq(i);
432 var source_cell = source_element.data("cell");
432 var source_cell = source_element.data("cell");
433 var target_cell = null;
433 var target_cell = null;
434 if (source_cell instanceof IPython.CodeCell) {
434 if (source_cell instanceof IPython.CodeCell) {
435 this.insert_html_cell_after(i);
435 this.insert_html_cell_after(i);
436 var target_cell = this.cells()[i+1];
436 var target_cell = this.cells()[i+1];
437 var text = source_cell.get_code();
437 var text = source_cell.get_code();
438 } else if (source_cell instanceof IPython.MarkdownCell) {
438 } else if (source_cell instanceof IPython.MarkdownCell) {
439 this.insert_html_cell_after(i);
439 this.insert_html_cell_after(i);
440 var target_cell = this.cells()[i+1];
440 var target_cell = this.cells()[i+1];
441 var text = source_cell.get_source();
441 var text = source_cell.get_source();
442 if (text === source_cell.placeholder) {
442 if (text === source_cell.placeholder) {
443 text = target_cell.placeholder;
443 text = target_cell.placeholder;
444 }
444 }
445 }
445 }
446 if (target_cell !== null) {
446 if (target_cell !== null) {
447 if (text === "") {text = target_cell.placeholder;};
447 if (text === "") {text = target_cell.placeholder;};
448 target_cell.set_source(text);
448 target_cell.set_source(text);
449 source_element.remove();
449 source_element.remove();
450 target_cell.edit();
450 target_cell.edit();
451 }
451 }
452 this.dirty = true;
452 this.dirty = true;
453 };
453 };
454
454
455
455
456 // Cell collapsing and output clearing
456 // Cell collapsing and output clearing
457
457
458 Notebook.prototype.collapse = function (index) {
458 Notebook.prototype.collapse = function (index) {
459 var i = this.index_or_selected(index);
459 var i = this.index_or_selected(index);
460 this.cells()[i].collapse();
460 this.cells()[i].collapse();
461 this.dirty = true;
461 this.dirty = true;
462 };
462 };
463
463
464
464
465 Notebook.prototype.expand = function (index) {
465 Notebook.prototype.expand = function (index) {
466 var i = this.index_or_selected(index);
466 var i = this.index_or_selected(index);
467 this.cells()[i].expand();
467 this.cells()[i].expand();
468 this.dirty = true;
468 this.dirty = true;
469 };
469 };
470
470
471
471
472 Notebook.prototype.set_autoindent = function (state) {
472 Notebook.prototype.set_autoindent = function (state) {
473 var cells = this.cells();
473 var cells = this.cells();
474 len = cells.length;
474 len = cells.length;
475 for (var i=0; i<len; i++) {
475 for (var i=0; i<len; i++) {
476 cells[i].set_autoindent(state)
476 cells[i].set_autoindent(state)
477 };
477 };
478 };
478 };
479
479
480
480
481 Notebook.prototype.clear_all_output = function () {
481 Notebook.prototype.clear_all_output = function () {
482 var ncells = this.ncells();
482 var ncells = this.ncells();
483 var cells = this.cells();
483 var cells = this.cells();
484 for (var i=0; i<ncells; i++) {
484 for (var i=0; i<ncells; i++) {
485 if (cells[i] instanceof IPython.CodeCell) {
485 if (cells[i] instanceof IPython.CodeCell) {
486 cells[i].clear_output();
486 cells[i].clear_output();
487 }
487 }
488 };
488 };
489 this.dirty = true;
489 this.dirty = true;
490 };
490 };
491
491
492
492
493 // Kernel related things
493 // Kernel related things
494
494
495 Notebook.prototype.start_kernel = function () {
495 Notebook.prototype.start_kernel = function () {
496 this.kernel = new IPython.Kernel();
496 this.kernel = new IPython.Kernel();
497 var notebook_id = IPython.save_widget.get_notebook_id();
497 var notebook_id = IPython.save_widget.get_notebook_id();
498 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
498 this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
499 };
499 };
500
500
501
501
502 Notebook.prototype.restart_kernel = function () {
502 Notebook.prototype.restart_kernel = function () {
503 var notebook_id = IPython.save_widget.get_notebook_id();
503 var notebook_id = IPython.save_widget.get_notebook_id();
504 this.kernel.restart($.proxy(this.kernel_started, this));
504 this.kernel.restart($.proxy(this.kernel_started, this));
505 };
505 };
506
506
507
507
508 Notebook.prototype.kernel_started = function () {
508 Notebook.prototype.kernel_started = function () {
509 console.log("Kernel started: ", this.kernel.kernel_id);
509 console.log("Kernel started: ", this.kernel.kernel_id);
510 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
510 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
511 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
511 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
512 };
512 };
513
513
514
514
515 Notebook.prototype.handle_shell_reply = function (e) {
515 Notebook.prototype.handle_shell_reply = function (e) {
516 reply = $.parseJSON(e.data);
516 reply = $.parseJSON(e.data);
517 var header = reply.header;
517 var header = reply.header;
518 var content = reply.content;
518 var content = reply.content;
519 var msg_type = header.msg_type;
519 var msg_type = header.msg_type;
520 // console.log(reply);
520 // console.log(reply);
521 var cell = this.cell_for_msg(reply.parent_header.msg_id);
521 var cell = this.cell_for_msg(reply.parent_header.msg_id);
522 if (msg_type === "execute_reply") {
522 if (msg_type === "execute_reply") {
523 cell.set_input_prompt(content.execution_count);
523 cell.set_input_prompt(content.execution_count);
524 this.dirty = true;
524 this.dirty = true;
525 } else if (msg_type === "complete_reply") {
525 } else if (msg_type === "complete_reply") {
526 cell.finish_completing(content.matched_text, content.matches);
526 cell.finish_completing(content.matched_text, content.matches);
527 };
527 };
528 var payload = content.payload || [];
528 var payload = content.payload || [];
529 this.handle_payload(cell, payload);
529 this.handle_payload(cell, payload);
530 };
530 };
531
531
532
532
533 Notebook.prototype.handle_payload = function (cell, payload) {
533 Notebook.prototype.handle_payload = function (cell, payload) {
534 var l = payload.length;
534 var l = payload.length;
535 for (var i=0; i<l; i++) {
535 for (var i=0; i<l; i++) {
536 if (payload[i].source === 'IPython.zmq.page.page') {
536 if (payload[i].source === 'IPython.zmq.page.page') {
537 IPython.pager.clear();
537 IPython.pager.clear();
538 IPython.pager.expand();
538 IPython.pager.expand();
539 IPython.pager.append_text(payload[i].text);
539 IPython.pager.append_text(payload[i].text);
540 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
540 } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
541 var index = this.find_cell_index(cell);
541 var index = this.find_cell_index(cell);
542 var new_cell = this.insert_code_cell_after(index);
542 var new_cell = this.insert_code_cell_after(index);
543 new_cell.set_code(payload[i].text);
543 new_cell.set_code(payload[i].text);
544 this.dirty = true;
544 this.dirty = true;
545 }
545 }
546 };
546 };
547 };
547 };
548
548
549
549
550 Notebook.prototype.handle_iopub_reply = function (e) {
550 Notebook.prototype.handle_iopub_reply = function (e) {
551 reply = $.parseJSON(e.data);
551 reply = $.parseJSON(e.data);
552 var content = reply.content;
552 var content = reply.content;
553 // console.log(reply);
553 // console.log(reply);
554 var msg_type = reply.header.msg_type;
554 var msg_type = reply.header.msg_type;
555 var cell = this.cell_for_msg(reply.parent_header.msg_id);
555 var cell = this.cell_for_msg(reply.parent_header.msg_id);
556 var output_types = ['stream','display_data','pyout','pyerr'];
556 var output_types = ['stream','display_data','pyout','pyerr'];
557 if (output_types.indexOf(msg_type) >= 0) {
557 if (output_types.indexOf(msg_type) >= 0) {
558 this.handle_output(cell, msg_type, content);
558 this.handle_output(cell, msg_type, content);
559 } else if (msg_type === 'status') {
559 } else if (msg_type === 'status') {
560 if (content.execution_state === 'busy') {
560 if (content.execution_state === 'busy') {
561 IPython.kernel_status_widget.status_busy();
561 IPython.kernel_status_widget.status_busy();
562 } else if (content.execution_state === 'idle') {
562 } else if (content.execution_state === 'idle') {
563 IPython.kernel_status_widget.status_idle();
563 IPython.kernel_status_widget.status_idle();
564 } else if (content.execution_state === 'dead') {
564 } else if (content.execution_state === 'dead') {
565 this.handle_status_dead();
565 this.handle_status_dead();
566 };
566 };
567 }
567 }
568 };
568 };
569
569
570
570
571 Notebook.prototype.handle_status_dead = function () {
571 Notebook.prototype.handle_status_dead = function () {
572 var that = this;
572 var that = this;
573 this.kernel.stop_channels();
573 this.kernel.stop_channels();
574 var dialog = $('<div/>');
574 var dialog = $('<div/>');
575 dialog.html('The kernel has died, would you like to restart it? If you do not restart the kernel, you will be able to save the notebook, but running code will not work until the notebook is reopened.');
575 dialog.html('The kernel has died, would you like to restart it? If you do not restart the kernel, you will be able to save the notebook, but running code will not work until the notebook is reopened.');
576 $(document).append(dialog);
576 $(document).append(dialog);
577 dialog.dialog({
577 dialog.dialog({
578 resizable: false,
578 resizable: false,
579 modal: true,
579 modal: true,
580 title: "Dead kernel",
580 title: "Dead kernel",
581 buttons : {
581 buttons : {
582 "Yes": function () {
582 "Yes": function () {
583 that.start_kernel();
583 that.start_kernel();
584 $(this).dialog('close');
584 $(this).dialog('close');
585 },
585 },
586 "No": function () {
586 "No": function () {
587 $(this).dialog('close');
587 $(this).dialog('close');
588 }
588 }
589 }
589 }
590 });
590 });
591 };
591 };
592
592
593
593
594 Notebook.prototype.handle_output = function (cell, msg_type, content) {
594 Notebook.prototype.handle_output = function (cell, msg_type, content) {
595 var json = {};
595 var json = {};
596 json.output_type = msg_type;
596 json.output_type = msg_type;
597 if (msg_type === "stream") {
597 if (msg_type === "stream") {
598 json.text = utils.fixConsole(content.data + '\n');
598 json.text = utils.fixConsole(content.data + '\n');
599 } else if (msg_type === "display_data") {
599 } else if (msg_type === "display_data") {
600 json = this.convert_mime_types(json, content.data);
600 json = this.convert_mime_types(json, content.data);
601 } else if (msg_type === "pyout") {
601 } else if (msg_type === "pyout") {
602 json.prompt_number = content.execution_count;
602 json.prompt_number = content.execution_count;
603 json = this.convert_mime_types(json, content.data);
603 json = this.convert_mime_types(json, content.data);
604 } else if (msg_type === "pyerr") {
604 } else if (msg_type === "pyerr") {
605 json.ename = content.ename;
605 json.ename = content.ename;
606 json.evalue = content.evalue;
606 json.evalue = content.evalue;
607 var traceback = [];
607 var traceback = [];
608 for (var i=0; i<content.traceback.length; i++) {
608 for (var i=0; i<content.traceback.length; i++) {
609 traceback.push(utils.fixConsole(content.traceback[i]));
609 traceback.push(utils.fixConsole(content.traceback[i]));
610 }
610 }
611 json.traceback = traceback;
611 json.traceback = traceback;
612 };
612 };
613 cell.append_output(json);
613 cell.append_output(json);
614 this.dirty = true;
614 this.dirty = true;
615 };
615 };
616
616
617
617
618 Notebook.prototype.convert_mime_types = function (json, data) {
618 Notebook.prototype.convert_mime_types = function (json, data) {
619 if (data['text/plain'] !== undefined) {
619 if (data['text/plain'] !== undefined) {
620 json.text = utils.fixConsole(data['text/plain']);
620 json.text = utils.fixConsole(data['text/plain']);
621 };
621 };
622 if (data['text/html'] !== undefined) {
622 if (data['text/html'] !== undefined) {
623 json.html = data['text/html'];
623 json.html = data['text/html'];
624 };
624 };
625 if (data['image/svg+xml'] !== undefined) {
625 if (data['image/svg+xml'] !== undefined) {
626 json.svg = data['image/svg+xml'];
626 json.svg = data['image/svg+xml'];
627 };
627 };
628 if (data['image/png'] !== undefined) {
628 if (data['image/png'] !== undefined) {
629 json.png = data['image/png'];
629 json.png = data['image/png'];
630 };
630 };
631 if (data['image/jpeg'] !== undefined) {
631 if (data['image/jpeg'] !== undefined) {
632 json.jpeg = data['image/jpeg'];
632 json.jpeg = data['image/jpeg'];
633 };
633 };
634 if (data['text/latex'] !== undefined) {
634 if (data['text/latex'] !== undefined) {
635 json.latex = data['text/latex'];
635 json.latex = data['text/latex'];
636 };
636 };
637 if (data['application/json'] !== undefined) {
637 if (data['application/json'] !== undefined) {
638 json.json = data['application/json'];
638 json.json = data['application/json'];
639 };
639 };
640 if (data['application/javascript'] !== undefined) {
640 if (data['application/javascript'] !== undefined) {
641 json.javascript = data['application/javascript'];
641 json.javascript = data['application/javascript'];
642 }
642 }
643 return json;
643 return json;
644 };
644 };
645
645
646
646
647 Notebook.prototype.execute_selected_cell = function (options) {
647 Notebook.prototype.execute_selected_cell = function (options) {
648 // add_new: should a new cell be added if we are at the end of the nb
648 // add_new: should a new cell be added if we are at the end of the nb
649 // terminal: execute in terminal mode, which stays in the current cell
649 // terminal: execute in terminal mode, which stays in the current cell
650 default_options = {terminal: false, add_new: true}
650 default_options = {terminal: false, add_new: true}
651 $.extend(default_options, options)
651 $.extend(default_options, options)
652 var that = this;
652 var that = this;
653 var cell = that.selected_cell();
653 var cell = that.selected_cell();
654 var cell_index = that.find_cell_index(cell);
654 var cell_index = that.find_cell_index(cell);
655 if (cell instanceof IPython.CodeCell) {
655 if (cell instanceof IPython.CodeCell) {
656 cell.clear_output();
656 cell.clear_output();
657 var code = cell.get_code();
657 var code = cell.get_code();
658 var msg_id = that.kernel.execute(cell.get_code());
658 var msg_id = that.kernel.execute(cell.get_code());
659 that.msg_cell_map[msg_id] = cell.cell_id;
659 that.msg_cell_map[msg_id] = cell.cell_id;
660 } else if (cell instanceof IPython.HTMLCell) {
660 } else if (cell instanceof IPython.HTMLCell) {
661 cell.render();
661 cell.render();
662 }
662 }
663 if (default_options.terminal) {
663 if (default_options.terminal) {
664 cell.clear_input();
664 cell.clear_input();
665 } else {
665 } else {
666 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
666 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
667 that.insert_code_cell_after();
667 that.insert_code_cell_after();
668 // If we are adding a new cell at the end, scroll down to show it.
668 // If we are adding a new cell at the end, scroll down to show it.
669 that.scroll_to_bottom();
669 that.scroll_to_bottom();
670 } else {
670 } else {
671 that.select(cell_index+1);
671 that.select(cell_index+1);
672 };
672 };
673 };
673 };
674 this.dirty = true;
674 this.dirty = true;
675 };
675 };
676
676
677
677
678 Notebook.prototype.execute_all_cells = function () {
678 Notebook.prototype.execute_all_cells = function () {
679 var ncells = this.ncells();
679 var ncells = this.ncells();
680 for (var i=0; i<ncells; i++) {
680 for (var i=0; i<ncells; i++) {
681 this.select(i);
681 this.select(i);
682 this.execute_selected_cell({add_new:false});
682 this.execute_selected_cell({add_new:false});
683 };
683 };
684 this.scroll_to_bottom();
684 this.scroll_to_bottom();
685 };
685 };
686
686
687
687
688 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
688 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
689 var msg_id = this.kernel.complete(line, cursor_pos);
689 var msg_id = this.kernel.complete(line, cursor_pos);
690 this.msg_cell_map[msg_id] = cell.cell_id;
690 this.msg_cell_map[msg_id] = cell.cell_id;
691 };
691 };
692
692
693 // Persistance and loading
693 // Persistance and loading
694
694
695
695
696 Notebook.prototype.fromJSON = function (data) {
696 Notebook.prototype.fromJSON = function (data) {
697 var ncells = this.ncells();
697 var ncells = this.ncells();
698 for (var i=0; i<ncells; i++) {
698 for (var i=0; i<ncells; i++) {
699 // Always delete cell 0 as they get renumbered as they are deleted.
699 // Always delete cell 0 as they get renumbered as they are deleted.
700 this.delete_cell(0);
700 this.delete_cell(0);
701 };
701 };
702 // Only handle 1 worksheet for now.
702 // Only handle 1 worksheet for now.
703 var worksheet = data.worksheets[0];
703 var worksheet = data.worksheets[0];
704 if (worksheet !== undefined) {
704 if (worksheet !== undefined) {
705 var new_cells = worksheet.cells;
705 var new_cells = worksheet.cells;
706 ncells = new_cells.length;
706 ncells = new_cells.length;
707 var cell_data = null;
707 var cell_data = null;
708 var new_cell = null;
708 var new_cell = null;
709 for (var i=0; i<ncells; i++) {
709 for (var i=0; i<ncells; i++) {
710 cell_data = new_cells[i];
710 cell_data = new_cells[i];
711 if (cell_data.cell_type == 'code') {
711 if (cell_data.cell_type == 'code') {
712 new_cell = this.insert_code_cell_after();
712 new_cell = this.insert_code_cell_after();
713 new_cell.fromJSON(cell_data);
713 new_cell.fromJSON(cell_data);
714 } else if (cell_data.cell_type === 'html') {
714 } else if (cell_data.cell_type === 'html') {
715 new_cell = this.insert_html_cell_after();
715 new_cell = this.insert_html_cell_after();
716 new_cell.fromJSON(cell_data);
716 new_cell.fromJSON(cell_data);
717 } else if (cell_data.cell_type === 'markdown') {
717 } else if (cell_data.cell_type === 'markdown') {
718 new_cell = this.insert_markdown_cell_after();
718 new_cell = this.insert_markdown_cell_after();
719 new_cell.fromJSON(cell_data);
719 new_cell.fromJSON(cell_data);
720 };
720 };
721 };
721 };
722 };
722 };
723 };
723 };
724
724
725
725
726 Notebook.prototype.toJSON = function () {
726 Notebook.prototype.toJSON = function () {
727 var cells = this.cells();
727 var cells = this.cells();
728 var ncells = cells.length;
728 var ncells = cells.length;
729 cell_array = new Array(ncells);
729 cell_array = new Array(ncells);
730 for (var i=0; i<ncells; i++) {
730 for (var i=0; i<ncells; i++) {
731 cell_array[i] = cells[i].toJSON();
731 cell_array[i] = cells[i].toJSON();
732 };
732 };
733 data = {
733 data = {
734 // Only handle 1 worksheet for now.
734 // Only handle 1 worksheet for now.
735 worksheets : [{cells:cell_array}]
735 worksheets : [{cells:cell_array}]
736 }
736 }
737 return data
737 return data
738 };
738 };
739
739
740 Notebook.prototype.save_notebook = function () {
740 Notebook.prototype.save_notebook = function () {
741 if (IPython.save_widget.test_notebook_name()) {
741 if (IPython.save_widget.test_notebook_name()) {
742 var notebook_id = IPython.save_widget.get_notebook_id();
742 var notebook_id = IPython.save_widget.get_notebook_id();
743 var nbname = IPython.save_widget.get_notebook_name();
743 var nbname = IPython.save_widget.get_notebook_name();
744 // We may want to move the name/id/nbformat logic inside toJSON?
744 // We may want to move the name/id/nbformat logic inside toJSON?
745 var data = this.toJSON();
745 var data = this.toJSON();
746 data.name = nbname;
746 data.name = nbname;
747 data.nbformat = 2;
747 data.nbformat = 2;
748 data.id = notebook_id
749 // We do the call with settings so we can set cache to false.
748 // We do the call with settings so we can set cache to false.
750 var settings = {
749 var settings = {
751 processData : false,
750 processData : false,
752 cache : false,
751 cache : false,
753 type : "PUT",
752 type : "PUT",
754 data : JSON.stringify(data),
753 data : JSON.stringify(data),
755 headers : {'Content-Type': 'application/json'},
754 headers : {'Content-Type': 'application/json'},
756 success : $.proxy(this.notebook_saved,this)
755 success : $.proxy(this.notebook_saved,this)
757 };
756 };
758 IPython.save_widget.status_saving();
757 IPython.save_widget.status_saving();
759 $.ajax("/notebooks/" + notebook_id, settings);
758 $.ajax("/notebooks/" + notebook_id, settings);
760 };
759 };
761 };
760 };
762
761
763
762
764 Notebook.prototype.notebook_saved = function (data, status, xhr) {
763 Notebook.prototype.notebook_saved = function (data, status, xhr) {
765 this.dirty = false;
764 this.dirty = false;
766 setTimeout($.proxy(IPython.save_widget.status_save,IPython.save_widget),500);
765 setTimeout($.proxy(IPython.save_widget.status_save,IPython.save_widget),500);
767 }
766 }
768
767
769
768
770 Notebook.prototype.load_notebook = function (callback) {
769 Notebook.prototype.load_notebook = function (callback) {
771 var that = this;
770 var that = this;
772 var notebook_id = IPython.save_widget.get_notebook_id();
771 var notebook_id = IPython.save_widget.get_notebook_id();
773 // We do the call with settings so we can set cache to false.
772 // We do the call with settings so we can set cache to false.
774 var settings = {
773 var settings = {
775 processData : false,
774 processData : false,
776 cache : false,
775 cache : false,
777 type : "GET",
776 type : "GET",
778 dataType : "json",
777 dataType : "json",
779 success : function (data, status, xhr) {
778 success : function (data, status, xhr) {
780 that.notebook_loaded(data, status, xhr);
779 that.notebook_loaded(data, status, xhr);
781 if (callback !== undefined) {
780 if (callback !== undefined) {
782 callback();
781 callback();
783 };
782 };
784 }
783 }
785 };
784 };
786 IPython.save_widget.status_loading();
785 IPython.save_widget.status_loading();
787 $.ajax("/notebooks/" + notebook_id, settings);
786 $.ajax("/notebooks/" + notebook_id, settings);
788 }
787 }
789
788
790
789
791 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
790 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
792 this.fromJSON(data);
791 this.fromJSON(data);
793 if (this.ncells() === 0) {
792 if (this.ncells() === 0) {
794 this.insert_code_cell_after();
793 this.insert_code_cell_after();
795 };
794 };
796 IPython.save_widget.status_save();
795 IPython.save_widget.status_save();
797 IPython.save_widget.set_notebook_name(data.name);
796 IPython.save_widget.set_notebook_name(data.name);
798 this.start_kernel();
797 this.start_kernel();
799 this.dirty = false;
798 this.dirty = false;
800 // fromJSON always selects the last cell inserted. We need to wait
799 // fromJSON always selects the last cell inserted. We need to wait
801 // until that is done before scrolling to the top.
800 // until that is done before scrolling to the top.
802 setTimeout(function () {
801 setTimeout(function () {
803 IPython.notebook.select(0);
802 IPython.notebook.select(0);
804 IPython.notebook.scroll_to_top();
803 IPython.notebook.scroll_to_top();
805 }, 50);
804 }, 50);
806 };
805 };
807
806
808 IPython.Notebook = Notebook;
807 IPython.Notebook = Notebook;
809
808
810 return IPython;
809 return IPython;
811
810
812 }(IPython));
811 }(IPython));
813
812
@@ -1,136 +1,132 b''
1 """The basic dict based notebook format."""
1 """The basic dict based notebook format."""
2
2
3 import pprint
3 import pprint
4 import uuid
4 import uuid
5
5
6 from IPython.utils.ipstruct import Struct
6 from IPython.utils.ipstruct import Struct
7
7
8
8
9 class NotebookNode(Struct):
9 class NotebookNode(Struct):
10 pass
10 pass
11
11
12
12
13 def from_dict(d):
13 def from_dict(d):
14 if isinstance(d, dict):
14 if isinstance(d, dict):
15 newd = NotebookNode()
15 newd = NotebookNode()
16 for k,v in d.items():
16 for k,v in d.items():
17 newd[k] = from_dict(v)
17 newd[k] = from_dict(v)
18 return newd
18 return newd
19 elif isinstance(d, (tuple, list)):
19 elif isinstance(d, (tuple, list)):
20 return [from_dict(i) for i in d]
20 return [from_dict(i) for i in d]
21 else:
21 else:
22 return d
22 return d
23
23
24
24
25 def new_output(output_type=None, output_text=None, output_png=None,
25 def new_output(output_type=None, output_text=None, output_png=None,
26 output_html=None, output_svg=None, output_latex=None, output_json=None,
26 output_html=None, output_svg=None, output_latex=None, output_json=None,
27 output_javascript=None, output_jpeg=None, prompt_number=None,
27 output_javascript=None, output_jpeg=None, prompt_number=None,
28 etype=None, evalue=None, traceback=None):
28 etype=None, evalue=None, traceback=None):
29 """Create a new code cell with input and output"""
29 """Create a new code cell with input and output"""
30 output = NotebookNode()
30 output = NotebookNode()
31 if output_type is not None:
31 if output_type is not None:
32 output.output_type = unicode(output_type)
32 output.output_type = unicode(output_type)
33
33
34 if output_type != 'pyerr':
34 if output_type != 'pyerr':
35 if output_text is not None:
35 if output_text is not None:
36 output.text = unicode(output_text)
36 output.text = unicode(output_text)
37 if output_png is not None:
37 if output_png is not None:
38 output.png = bytes(output_png)
38 output.png = bytes(output_png)
39 if output_jpeg is not None:
39 if output_jpeg is not None:
40 output.jpeg = bytes(output_jpeg)
40 output.jpeg = bytes(output_jpeg)
41 if output_html is not None:
41 if output_html is not None:
42 output.html = unicode(output_html)
42 output.html = unicode(output_html)
43 if output_svg is not None:
43 if output_svg is not None:
44 output.svg = unicode(output_svg)
44 output.svg = unicode(output_svg)
45 if output_latex is not None:
45 if output_latex is not None:
46 output.latex = unicode(output_latex)
46 output.latex = unicode(output_latex)
47 if output_json is not None:
47 if output_json is not None:
48 output.json = unicode(output_json)
48 output.json = unicode(output_json)
49 if output_javascript is not None:
49 if output_javascript is not None:
50 output.javascript = unicode(output_javascript)
50 output.javascript = unicode(output_javascript)
51
51
52 if output_type == u'pyout':
52 if output_type == u'pyout':
53 if prompt_number is not None:
53 if prompt_number is not None:
54 output.prompt_number = int(prompt_number)
54 output.prompt_number = int(prompt_number)
55
55
56 if output_type == u'pyerr':
56 if output_type == u'pyerr':
57 if etype is not None:
57 if etype is not None:
58 output.etype = unicode(etype)
58 output.etype = unicode(etype)
59 if evalue is not None:
59 if evalue is not None:
60 output.evalue = unicode(evalue)
60 output.evalue = unicode(evalue)
61 if traceback is not None:
61 if traceback is not None:
62 output.traceback = [unicode(frame) for frame in list(traceback)]
62 output.traceback = [unicode(frame) for frame in list(traceback)]
63
63
64 return output
64 return output
65
65
66
66
67 def new_code_cell(input=None, prompt_number=None, outputs=None,
67 def new_code_cell(input=None, prompt_number=None, outputs=None,
68 language=u'python', collapsed=False):
68 language=u'python', collapsed=False):
69 """Create a new code cell with input and output"""
69 """Create a new code cell with input and output"""
70 cell = NotebookNode()
70 cell = NotebookNode()
71 cell.cell_type = u'code'
71 cell.cell_type = u'code'
72 if language is not None:
72 if language is not None:
73 cell.language = unicode(language)
73 cell.language = unicode(language)
74 if input is not None:
74 if input is not None:
75 cell.input = unicode(input)
75 cell.input = unicode(input)
76 if prompt_number is not None:
76 if prompt_number is not None:
77 cell.prompt_number = int(prompt_number)
77 cell.prompt_number = int(prompt_number)
78 if outputs is None:
78 if outputs is None:
79 cell.outputs = []
79 cell.outputs = []
80 else:
80 else:
81 cell.outputs = outputs
81 cell.outputs = outputs
82 if collapsed is not None:
82 if collapsed is not None:
83 cell.collapsed = bool(collapsed)
83 cell.collapsed = bool(collapsed)
84
84
85 return cell
85 return cell
86
86
87 def new_text_cell(cell_type, source=None, rendered=None):
87 def new_text_cell(cell_type, source=None, rendered=None):
88 """Create a new text cell."""
88 """Create a new text cell."""
89 cell = NotebookNode()
89 cell = NotebookNode()
90 if source is not None:
90 if source is not None:
91 cell.source = unicode(source)
91 cell.source = unicode(source)
92 if rendered is not None:
92 if rendered is not None:
93 cell.rendered = unicode(rendered)
93 cell.rendered = unicode(rendered)
94 cell.cell_type = cell_type
94 cell.cell_type = cell_type
95 return cell
95 return cell
96
96
97
97
98 def new_worksheet(name=None, cells=None):
98 def new_worksheet(name=None, cells=None):
99 """Create a worksheet by name with with a list of cells."""
99 """Create a worksheet by name with with a list of cells."""
100 ws = NotebookNode()
100 ws = NotebookNode()
101 if name is not None:
101 if name is not None:
102 ws.name = unicode(name)
102 ws.name = unicode(name)
103 if cells is None:
103 if cells is None:
104 ws.cells = []
104 ws.cells = []
105 else:
105 else:
106 ws.cells = list(cells)
106 ws.cells = list(cells)
107 return ws
107 return ws
108
108
109
109
110 def new_notebook(name=None, id=None, worksheets=None, author=None, email=None,
110 def new_notebook(name=None, worksheets=None, author=None, email=None,
111 created=None, saved=None, license=None):
111 created=None, saved=None, license=None):
112 """Create a notebook by name, id and a list of worksheets."""
112 """Create a notebook by name, id and a list of worksheets."""
113 nb = NotebookNode()
113 nb = NotebookNode()
114 nb.nbformat = 2
114 nb.nbformat = 2
115 if name is not None:
115 if name is not None:
116 nb.name = unicode(name)
116 nb.name = unicode(name)
117 if id is None:
118 nb.id = unicode(uuid.uuid4())
119 else:
120 nb.id = unicode(id)
121 if worksheets is None:
117 if worksheets is None:
122 nb.worksheets = []
118 nb.worksheets = []
123 else:
119 else:
124 nb.worksheets = list(worksheets)
120 nb.worksheets = list(worksheets)
125 if author is not None:
121 if author is not None:
126 nb.author = unicode(author)
122 nb.author = unicode(author)
127 if email is not None:
123 if email is not None:
128 nb.email = unicode(email)
124 nb.email = unicode(email)
129 if created is not None:
125 if created is not None:
130 nb.created = unicode(created)
126 nb.created = unicode(created)
131 if saved is not None:
127 if saved is not None:
132 nb.saved = unicode(saved)
128 nb.saved = unicode(saved)
133 if license is not None:
129 if license is not None:
134 nb.license = unicode(license)
130 nb.license = unicode(license)
135 return nb
131 return nb
136
132
@@ -1,228 +1,226 b''
1 """Read and write notebook files as XML."""
1 """Read and write notebook files as XML."""
2
2
3 from base64 import encodestring, decodestring
3 from base64 import encodestring, decodestring
4 from xml.etree import ElementTree as ET
4 from xml.etree import ElementTree as ET
5
5
6 from .rwbase import NotebookReader, NotebookWriter
6 from .rwbase import NotebookReader, NotebookWriter
7 from .nbbase import (
7 from .nbbase import (
8 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
8 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
9 )
9 )
10
10
11 def indent(elem, level=0):
11 def indent(elem, level=0):
12 i = "\n" + level*" "
12 i = "\n" + level*" "
13 if len(elem):
13 if len(elem):
14 if not elem.text or not elem.text.strip():
14 if not elem.text or not elem.text.strip():
15 elem.text = i + " "
15 elem.text = i + " "
16 if not elem.tail or not elem.tail.strip():
16 if not elem.tail or not elem.tail.strip():
17 elem.tail = i
17 elem.tail = i
18 for elem in elem:
18 for elem in elem:
19 indent(elem, level+1)
19 indent(elem, level+1)
20 if not elem.tail or not elem.tail.strip():
20 if not elem.tail or not elem.tail.strip():
21 elem.tail = i
21 elem.tail = i
22 else:
22 else:
23 if level and (not elem.tail or not elem.tail.strip()):
23 if level and (not elem.tail or not elem.tail.strip()):
24 elem.tail = i
24 elem.tail = i
25
25
26
26
27 def _get_text(e, tag):
27 def _get_text(e, tag):
28 sub_e = e.find(tag)
28 sub_e = e.find(tag)
29 if sub_e is None:
29 if sub_e is None:
30 return None
30 return None
31 else:
31 else:
32 return sub_e.text
32 return sub_e.text
33
33
34
34
35 def _set_text(nbnode, attr, parent, tag):
35 def _set_text(nbnode, attr, parent, tag):
36 if attr in nbnode:
36 if attr in nbnode:
37 e = ET.SubElement(parent, tag)
37 e = ET.SubElement(parent, tag)
38 e.text = nbnode[attr]
38 e.text = nbnode[attr]
39
39
40
40
41 def _get_int(e, tag):
41 def _get_int(e, tag):
42 sub_e = e.find(tag)
42 sub_e = e.find(tag)
43 if sub_e is None:
43 if sub_e is None:
44 return None
44 return None
45 else:
45 else:
46 return int(sub_e.text)
46 return int(sub_e.text)
47
47
48
48
49 def _set_int(nbnode, attr, parent, tag):
49 def _set_int(nbnode, attr, parent, tag):
50 if attr in nbnode:
50 if attr in nbnode:
51 e = ET.SubElement(parent, tag)
51 e = ET.SubElement(parent, tag)
52 e.text = unicode(nbnode[attr])
52 e.text = unicode(nbnode[attr])
53
53
54
54
55 def _get_bool(e, tag):
55 def _get_bool(e, tag):
56 sub_e = e.find(tag)
56 sub_e = e.find(tag)
57 if sub_e is None:
57 if sub_e is None:
58 return None
58 return None
59 else:
59 else:
60 return bool(int(sub_e.text))
60 return bool(int(sub_e.text))
61
61
62
62
63 def _set_bool(nbnode, attr, parent, tag):
63 def _set_bool(nbnode, attr, parent, tag):
64 if attr in nbnode:
64 if attr in nbnode:
65 e = ET.SubElement(parent, tag)
65 e = ET.SubElement(parent, tag)
66 if nbnode[attr]:
66 if nbnode[attr]:
67 e.text = u'1'
67 e.text = u'1'
68 else:
68 else:
69 e.text = u'0'
69 e.text = u'0'
70
70
71
71
72 def _get_binary(e, tag):
72 def _get_binary(e, tag):
73 sub_e = e.find(tag)
73 sub_e = e.find(tag)
74 if sub_e is None:
74 if sub_e is None:
75 return None
75 return None
76 else:
76 else:
77 return decodestring(sub_e.text)
77 return decodestring(sub_e.text)
78
78
79
79
80 def _set_binary(nbnode, attr, parent, tag):
80 def _set_binary(nbnode, attr, parent, tag):
81 if attr in nbnode:
81 if attr in nbnode:
82 e = ET.SubElement(parent, tag)
82 e = ET.SubElement(parent, tag)
83 e.text = encodestring(nbnode[attr])
83 e.text = encodestring(nbnode[attr])
84
84
85
85
86 class XMLReader(NotebookReader):
86 class XMLReader(NotebookReader):
87
87
88 def reads(self, s, **kwargs):
88 def reads(self, s, **kwargs):
89 root = ET.fromstring(s)
89 root = ET.fromstring(s)
90 return self.to_notebook(root, **kwargs)
90 return self.to_notebook(root, **kwargs)
91
91
92 def to_notebook(self, root, **kwargs):
92 def to_notebook(self, root, **kwargs):
93 nbname = _get_text(root,u'name')
93 nbname = _get_text(root,u'name')
94 nbid = _get_text(root,u'id')
95 nbauthor = _get_text(root,u'author')
94 nbauthor = _get_text(root,u'author')
96 nbemail = _get_text(root,u'email')
95 nbemail = _get_text(root,u'email')
97 nblicense = _get_text(root,u'license')
96 nblicense = _get_text(root,u'license')
98 nbcreated = _get_text(root,u'created')
97 nbcreated = _get_text(root,u'created')
99 nbsaved = _get_text(root,u'saved')
98 nbsaved = _get_text(root,u'saved')
100
99
101 worksheets = []
100 worksheets = []
102 for ws_e in root.find(u'worksheets').getiterator(u'worksheet'):
101 for ws_e in root.find(u'worksheets').getiterator(u'worksheet'):
103 wsname = _get_text(ws_e,u'name')
102 wsname = _get_text(ws_e,u'name')
104 cells = []
103 cells = []
105 for cell_e in ws_e.find(u'cells').getiterator():
104 for cell_e in ws_e.find(u'cells').getiterator():
106 if cell_e.tag == u'codecell':
105 if cell_e.tag == u'codecell':
107 input = _get_text(cell_e,u'input')
106 input = _get_text(cell_e,u'input')
108 prompt_number = _get_int(cell_e,u'prompt_number')
107 prompt_number = _get_int(cell_e,u'prompt_number')
109 collapsed = _get_bool(cell_e,u'collapsed')
108 collapsed = _get_bool(cell_e,u'collapsed')
110 language = _get_text(cell_e,u'language')
109 language = _get_text(cell_e,u'language')
111 outputs = []
110 outputs = []
112 for output_e in cell_e.find(u'outputs').getiterator(u'output'):
111 for output_e in cell_e.find(u'outputs').getiterator(u'output'):
113 output_type = _get_text(output_e,u'output_type')
112 output_type = _get_text(output_e,u'output_type')
114 output_text = _get_text(output_e,u'text')
113 output_text = _get_text(output_e,u'text')
115 output_png = _get_binary(output_e,u'png')
114 output_png = _get_binary(output_e,u'png')
116 output_jpeg = _get_binary(output_e,u'jpeg')
115 output_jpeg = _get_binary(output_e,u'jpeg')
117 output_svg = _get_text(output_e,u'svg')
116 output_svg = _get_text(output_e,u'svg')
118 output_html = _get_text(output_e,u'html')
117 output_html = _get_text(output_e,u'html')
119 output_latex = _get_text(output_e,u'latex')
118 output_latex = _get_text(output_e,u'latex')
120 output_json = _get_text(output_e,u'json')
119 output_json = _get_text(output_e,u'json')
121 output_javascript = _get_text(output_e,u'javascript')
120 output_javascript = _get_text(output_e,u'javascript')
122
121
123 out_prompt_number = _get_int(output_e,u'prompt_number')
122 out_prompt_number = _get_int(output_e,u'prompt_number')
124 etype = _get_text(output_e,u'etype')
123 etype = _get_text(output_e,u'etype')
125 evalue = _get_text(output_e,u'evalue')
124 evalue = _get_text(output_e,u'evalue')
126 traceback = []
125 traceback = []
127 traceback_e = output_e.find(u'traceback')
126 traceback_e = output_e.find(u'traceback')
128 if traceback_e is not None:
127 if traceback_e is not None:
129 for frame_e in traceback_e.getiterator(u'frame'):
128 for frame_e in traceback_e.getiterator(u'frame'):
130 traceback.append(frame_e.text)
129 traceback.append(frame_e.text)
131 if len(traceback) == 0:
130 if len(traceback) == 0:
132 traceback = None
131 traceback = None
133 output = new_output(output_type=output_type,output_png=output_png,
132 output = new_output(output_type=output_type,output_png=output_png,
134 output_text=output_text, output_svg=output_svg,
133 output_text=output_text, output_svg=output_svg,
135 output_html=output_html, output_latex=output_latex,
134 output_html=output_html, output_latex=output_latex,
136 output_json=output_json, output_javascript=output_javascript,
135 output_json=output_json, output_javascript=output_javascript,
137 output_jpeg=output_jpeg, prompt_number=out_prompt_number,
136 output_jpeg=output_jpeg, prompt_number=out_prompt_number,
138 etype=etype, evalue=evalue, traceback=traceback
137 etype=etype, evalue=evalue, traceback=traceback
139 )
138 )
140 outputs.append(output)
139 outputs.append(output)
141 cc = new_code_cell(input=input,prompt_number=prompt_number,
140 cc = new_code_cell(input=input,prompt_number=prompt_number,
142 language=language,outputs=outputs,collapsed=collapsed)
141 language=language,outputs=outputs,collapsed=collapsed)
143 cells.append(cc)
142 cells.append(cc)
144 if cell_e.tag == u'htmlcell':
143 if cell_e.tag == u'htmlcell':
145 source = _get_text(cell_e,u'source')
144 source = _get_text(cell_e,u'source')
146 rendered = _get_text(cell_e,u'rendered')
145 rendered = _get_text(cell_e,u'rendered')
147 cells.append(new_text_cell(u'html', source=source, rendered=rendered))
146 cells.append(new_text_cell(u'html', source=source, rendered=rendered))
148 if cell_e.tag == u'markdowncell':
147 if cell_e.tag == u'markdowncell':
149 source = _get_text(cell_e,u'source')
148 source = _get_text(cell_e,u'source')
150 rendered = _get_text(cell_e,u'rendered')
149 rendered = _get_text(cell_e,u'rendered')
151 cells.append(new_text_cell(u'markdown', source=source, rendered=rendered))
150 cells.append(new_text_cell(u'markdown', source=source, rendered=rendered))
152 ws = new_worksheet(name=wsname,cells=cells)
151 ws = new_worksheet(name=wsname,cells=cells)
153 worksheets.append(ws)
152 worksheets.append(ws)
154
153
155 nb = new_notebook(name=nbname,id=nbid,worksheets=worksheets,author=nbauthor,
154 nb = new_notebook(name=nbname,worksheets=worksheets,author=nbauthor,
156 email=nbemail,license=nblicense,saved=nbsaved,created=nbcreated)
155 email=nbemail,license=nblicense,saved=nbsaved,created=nbcreated)
157 return nb
156 return nb
158
157
159
158
160 class XMLWriter(NotebookWriter):
159 class XMLWriter(NotebookWriter):
161
160
162 def writes(self, nb, **kwargs):
161 def writes(self, nb, **kwargs):
163 nb_e = ET.Element(u'notebook')
162 nb_e = ET.Element(u'notebook')
164 _set_text(nb,u'name',nb_e,u'name')
163 _set_text(nb,u'name',nb_e,u'name')
165 _set_text(nb,u'id',nb_e,u'id')
166 _set_text(nb,u'author',nb_e,u'author')
164 _set_text(nb,u'author',nb_e,u'author')
167 _set_text(nb,u'email',nb_e,u'email')
165 _set_text(nb,u'email',nb_e,u'email')
168 _set_text(nb,u'license',nb_e,u'license')
166 _set_text(nb,u'license',nb_e,u'license')
169 _set_text(nb,u'created',nb_e,u'created')
167 _set_text(nb,u'created',nb_e,u'created')
170 _set_text(nb,u'saved',nb_e,u'saved')
168 _set_text(nb,u'saved',nb_e,u'saved')
171 _set_int(nb,u'nbformat',nb_e,u'nbformat')
169 _set_int(nb,u'nbformat',nb_e,u'nbformat')
172 wss_e = ET.SubElement(nb_e,u'worksheets')
170 wss_e = ET.SubElement(nb_e,u'worksheets')
173 for ws in nb.worksheets:
171 for ws in nb.worksheets:
174 ws_e = ET.SubElement(wss_e, u'worksheet')
172 ws_e = ET.SubElement(wss_e, u'worksheet')
175 _set_text(ws,u'name',ws_e,u'name')
173 _set_text(ws,u'name',ws_e,u'name')
176 cells_e = ET.SubElement(ws_e,u'cells')
174 cells_e = ET.SubElement(ws_e,u'cells')
177 for cell in ws.cells:
175 for cell in ws.cells:
178 cell_type = cell.cell_type
176 cell_type = cell.cell_type
179 if cell_type == u'code':
177 if cell_type == u'code':
180 cell_e = ET.SubElement(cells_e, u'codecell')
178 cell_e = ET.SubElement(cells_e, u'codecell')
181 _set_text(cell,u'input',cell_e,u'input')
179 _set_text(cell,u'input',cell_e,u'input')
182 _set_text(cell,u'language',cell_e,u'language')
180 _set_text(cell,u'language',cell_e,u'language')
183 _set_int(cell,u'prompt_number',cell_e,u'prompt_number')
181 _set_int(cell,u'prompt_number',cell_e,u'prompt_number')
184 _set_bool(cell,u'collapsed',cell_e,u'collapsed')
182 _set_bool(cell,u'collapsed',cell_e,u'collapsed')
185 outputs_e = ET.SubElement(cell_e, u'outputs')
183 outputs_e = ET.SubElement(cell_e, u'outputs')
186 for output in cell.outputs:
184 for output in cell.outputs:
187 output_e = ET.SubElement(outputs_e, u'output')
185 output_e = ET.SubElement(outputs_e, u'output')
188 _set_text(output,u'output_type',output_e,u'output_type')
186 _set_text(output,u'output_type',output_e,u'output_type')
189 _set_text(output,u'text',output_e,u'text')
187 _set_text(output,u'text',output_e,u'text')
190 _set_binary(output,u'png',output_e,u'png')
188 _set_binary(output,u'png',output_e,u'png')
191 _set_binary(output,u'jpeg',output_e,u'jpeg')
189 _set_binary(output,u'jpeg',output_e,u'jpeg')
192 _set_text(output,u'html',output_e,u'html')
190 _set_text(output,u'html',output_e,u'html')
193 _set_text(output,u'svg',output_e,u'svg')
191 _set_text(output,u'svg',output_e,u'svg')
194 _set_text(output,u'latex',output_e,u'latex')
192 _set_text(output,u'latex',output_e,u'latex')
195 _set_text(output,u'json',output_e,u'json')
193 _set_text(output,u'json',output_e,u'json')
196 _set_text(output,u'javascript',output_e,u'javascript')
194 _set_text(output,u'javascript',output_e,u'javascript')
197 _set_int(output,u'prompt_number',output_e,u'prompt_number')
195 _set_int(output,u'prompt_number',output_e,u'prompt_number')
198 _set_text(output,u'etype',output_e,u'etype')
196 _set_text(output,u'etype',output_e,u'etype')
199 _set_text(output,u'evalue',output_e,u'evalue')
197 _set_text(output,u'evalue',output_e,u'evalue')
200 if u'traceback' in output:
198 if u'traceback' in output:
201 tb_e = ET.SubElement(output_e, u'traceback')
199 tb_e = ET.SubElement(output_e, u'traceback')
202 for frame in output.traceback:
200 for frame in output.traceback:
203 frame_e = ET.SubElement(tb_e, u'frame')
201 frame_e = ET.SubElement(tb_e, u'frame')
204 frame_e.text = frame
202 frame_e.text = frame
205 elif cell_type == u'html':
203 elif cell_type == u'html':
206 cell_e = ET.SubElement(cells_e, u'htmlcell')
204 cell_e = ET.SubElement(cells_e, u'htmlcell')
207 _set_text(cell,u'source',cell_e,u'source')
205 _set_text(cell,u'source',cell_e,u'source')
208 _set_text(cell,u'rendered',cell_e,u'rendered')
206 _set_text(cell,u'rendered',cell_e,u'rendered')
209 elif cell_type == u'markdown':
207 elif cell_type == u'markdown':
210 cell_e = ET.SubElement(cells_e, u'markdowncell')
208 cell_e = ET.SubElement(cells_e, u'markdowncell')
211 _set_text(cell,u'source',cell_e,u'source')
209 _set_text(cell,u'source',cell_e,u'source')
212 _set_text(cell,u'rendered',cell_e,u'rendered')
210 _set_text(cell,u'rendered',cell_e,u'rendered')
213
211
214 indent(nb_e)
212 indent(nb_e)
215 txt = ET.tostring(nb_e, encoding="utf-8")
213 txt = ET.tostring(nb_e, encoding="utf-8")
216 txt = '<?xml version="1.0" encoding="utf-8"?>\n' + txt
214 txt = '<?xml version="1.0" encoding="utf-8"?>\n' + txt
217 return txt
215 return txt
218
216
219
217
220 _reader = XMLReader()
218 _reader = XMLReader()
221 _writer = XMLWriter()
219 _writer = XMLWriter()
222
220
223 reads = _reader.reads
221 reads = _reader.reads
224 read = _reader.read
222 read = _reader.read
225 to_notebook = _reader.to_notebook
223 to_notebook = _reader.to_notebook
226 write = _writer.write
224 write = _writer.write
227 writes = _writer.writes
225 writes = _writer.writes
228
226
@@ -1,90 +1,89 b''
1 from unittest import TestCase
1 from unittest import TestCase
2
2
3 from ..nbbase import (
3 from ..nbbase import (
4 NotebookNode,
4 NotebookNode,
5 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
5 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
6 )
6 )
7
7
8 class TestCell(TestCase):
8 class TestCell(TestCase):
9
9
10 def test_empty_code_cell(self):
10 def test_empty_code_cell(self):
11 cc = new_code_cell()
11 cc = new_code_cell()
12 self.assertEquals(cc.cell_type,'code')
12 self.assertEquals(cc.cell_type,'code')
13 self.assertEquals('input' not in cc, True)
13 self.assertEquals('input' not in cc, True)
14 self.assertEquals('prompt_number' not in cc, True)
14 self.assertEquals('prompt_number' not in cc, True)
15 self.assertEquals(cc.outputs, [])
15 self.assertEquals(cc.outputs, [])
16 self.assertEquals(cc.collapsed, False)
16 self.assertEquals(cc.collapsed, False)
17
17
18 def test_code_cell(self):
18 def test_code_cell(self):
19 cc = new_code_cell(input='a=10', prompt_number=0, collapsed=True)
19 cc = new_code_cell(input='a=10', prompt_number=0, collapsed=True)
20 cc.outputs = [new_output(output_type='pyout',
20 cc.outputs = [new_output(output_type='pyout',
21 output_svg='foo',output_text='10',prompt_number=0)]
21 output_svg='foo',output_text='10',prompt_number=0)]
22 self.assertEquals(cc.input, u'a=10')
22 self.assertEquals(cc.input, u'a=10')
23 self.assertEquals(cc.prompt_number, 0)
23 self.assertEquals(cc.prompt_number, 0)
24 self.assertEquals(cc.language, u'python')
24 self.assertEquals(cc.language, u'python')
25 self.assertEquals(cc.outputs[0].svg, u'foo')
25 self.assertEquals(cc.outputs[0].svg, u'foo')
26 self.assertEquals(cc.outputs[0].text, u'10')
26 self.assertEquals(cc.outputs[0].text, u'10')
27 self.assertEquals(cc.outputs[0].prompt_number, 0)
27 self.assertEquals(cc.outputs[0].prompt_number, 0)
28 self.assertEquals(cc.collapsed, True)
28 self.assertEquals(cc.collapsed, True)
29
29
30 def test_pyerr(self):
30 def test_pyerr(self):
31 o = new_output(output_type=u'pyerr', etype=u'NameError',
31 o = new_output(output_type=u'pyerr', etype=u'NameError',
32 evalue=u'Name not found', traceback=[u'frame 0', u'frame 1', u'frame 2']
32 evalue=u'Name not found', traceback=[u'frame 0', u'frame 1', u'frame 2']
33 )
33 )
34 self.assertEquals(o.output_type, u'pyerr')
34 self.assertEquals(o.output_type, u'pyerr')
35 self.assertEquals(o.etype, u'NameError')
35 self.assertEquals(o.etype, u'NameError')
36 self.assertEquals(o.evalue, u'Name not found')
36 self.assertEquals(o.evalue, u'Name not found')
37 self.assertEquals(o.traceback, [u'frame 0', u'frame 1', u'frame 2'])
37 self.assertEquals(o.traceback, [u'frame 0', u'frame 1', u'frame 2'])
38
38
39 def test_empty_html_cell(self):
39 def test_empty_html_cell(self):
40 tc = new_text_cell(u'html')
40 tc = new_text_cell(u'html')
41 self.assertEquals(tc.cell_type, u'html')
41 self.assertEquals(tc.cell_type, u'html')
42 self.assertEquals('source' not in tc, True)
42 self.assertEquals('source' not in tc, True)
43 self.assertEquals('rendered' not in tc, True)
43 self.assertEquals('rendered' not in tc, True)
44
44
45 def test_html_cell(self):
45 def test_html_cell(self):
46 tc = new_text_cell(u'html', 'hi', 'hi')
46 tc = new_text_cell(u'html', 'hi', 'hi')
47 self.assertEquals(tc.source, u'hi')
47 self.assertEquals(tc.source, u'hi')
48 self.assertEquals(tc.rendered, u'hi')
48 self.assertEquals(tc.rendered, u'hi')
49
49
50 def test_empty_markdown_cell(self):
50 def test_empty_markdown_cell(self):
51 tc = new_text_cell(u'markdown')
51 tc = new_text_cell(u'markdown')
52 self.assertEquals(tc.cell_type, u'markdown')
52 self.assertEquals(tc.cell_type, u'markdown')
53 self.assertEquals('source' not in tc, True)
53 self.assertEquals('source' not in tc, True)
54 self.assertEquals('rendered' not in tc, True)
54 self.assertEquals('rendered' not in tc, True)
55
55
56 def test_markdown_cell(self):
56 def test_markdown_cell(self):
57 tc = new_text_cell(u'markdown', 'hi', 'hi')
57 tc = new_text_cell(u'markdown', 'hi', 'hi')
58 self.assertEquals(tc.source, u'hi')
58 self.assertEquals(tc.source, u'hi')
59 self.assertEquals(tc.rendered, u'hi')
59 self.assertEquals(tc.rendered, u'hi')
60
60
61
61
62 class TestWorksheet(TestCase):
62 class TestWorksheet(TestCase):
63
63
64 def test_empty_worksheet(self):
64 def test_empty_worksheet(self):
65 ws = new_worksheet()
65 ws = new_worksheet()
66 self.assertEquals(ws.cells,[])
66 self.assertEquals(ws.cells,[])
67 self.assertEquals('name' not in ws, True)
67 self.assertEquals('name' not in ws, True)
68
68
69 def test_worksheet(self):
69 def test_worksheet(self):
70 cells = [new_code_cell(), new_text_cell(u'html')]
70 cells = [new_code_cell(), new_text_cell(u'html')]
71 ws = new_worksheet(cells=cells,name='foo')
71 ws = new_worksheet(cells=cells,name='foo')
72 self.assertEquals(ws.cells,cells)
72 self.assertEquals(ws.cells,cells)
73 self.assertEquals(ws.name,u'foo')
73 self.assertEquals(ws.name,u'foo')
74
74
75 class TestNotebook(TestCase):
75 class TestNotebook(TestCase):
76
76
77 def test_empty_notebook(self):
77 def test_empty_notebook(self):
78 nb = new_notebook()
78 nb = new_notebook()
79 self.assertEquals('id' in nb, True)
80 self.assertEquals(nb.worksheets, [])
79 self.assertEquals(nb.worksheets, [])
81 self.assertEquals('name' not in nb, True)
80 self.assertEquals('name' not in nb, True)
82 self.assertEquals(nb.nbformat,2)
81 self.assertEquals(nb.nbformat,2)
83
82
84 def test_notebook(self):
83 def test_notebook(self):
85 worksheets = [new_worksheet(),new_worksheet()]
84 worksheets = [new_worksheet(),new_worksheet()]
86 nb = new_notebook(name='foo',worksheets=worksheets)
85 nb = new_notebook(name='foo',worksheets=worksheets)
87 self.assertEquals(nb.name,u'foo')
86 self.assertEquals(nb.name,u'foo')
88 self.assertEquals(nb.worksheets,worksheets)
87 self.assertEquals(nb.worksheets,worksheets)
89 self.assertEquals(nb.nbformat,2)
88 self.assertEquals(nb.nbformat,2)
90
89
General Comments 0
You need to be logged in to leave comments. Login now