##// END OF EJS Templates
Markdown cells are now saved and restored in notebooks.
Brian E. Granger -
Show More
@@ -1,718 +1,721 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.msg_cell_map = {};
16 this.msg_cell_map = {};
17 this.style();
17 this.style();
18 this.create_elements();
18 this.create_elements();
19 this.bind_events();
19 this.bind_events();
20 };
20 };
21
21
22
22
23 Notebook.prototype.style = function () {
23 Notebook.prototype.style = function () {
24 $('div#notebook').addClass('border-box-sizing');
24 $('div#notebook').addClass('border-box-sizing');
25 };
25 };
26
26
27
27
28 Notebook.prototype.create_elements = function () {
28 Notebook.prototype.create_elements = function () {
29 // We add this end_space div to the end of the notebook div to:
29 // We add this end_space div to the end of the notebook div to:
30 // i) provide a margin between the last cell and the end of the notebook
30 // i) provide a margin between the last cell and the end of the notebook
31 // ii) to prevent the div from scrolling up when the last cell is being
31 // ii) to prevent the div from scrolling up when the last cell is being
32 // edited, but is too low on the page, which browsers will do automatically.
32 // edited, but is too low on the page, which browsers will do automatically.
33 this.element.append($('<div class="end_space"></div>').height(50));
33 this.element.append($('<div class="end_space"></div>').height(50));
34 $('div#notebook').addClass('border-box-sizing');
34 $('div#notebook').addClass('border-box-sizing');
35 };
35 };
36
36
37
37
38 Notebook.prototype.bind_events = function () {
38 Notebook.prototype.bind_events = function () {
39 var that = this;
39 var that = this;
40 $(document).keydown(function (event) {
40 $(document).keydown(function (event) {
41 // console.log(event);
41 // console.log(event);
42 if (event.which === 38) {
42 if (event.which === 38) {
43 var cell = that.selected_cell();
43 var cell = that.selected_cell();
44 if (cell.at_top()) {
44 if (cell.at_top()) {
45 event.preventDefault();
45 event.preventDefault();
46 that.select_prev();
46 that.select_prev();
47 };
47 };
48 } else if (event.which === 40) {
48 } else if (event.which === 40) {
49 var cell = that.selected_cell();
49 var cell = that.selected_cell();
50 if (cell.at_bottom()) {
50 if (cell.at_bottom()) {
51 event.preventDefault();
51 event.preventDefault();
52 that.select_next();
52 that.select_next();
53 };
53 };
54 } else if (event.which === 13 && event.shiftKey) {
54 } else if (event.which === 13 && event.shiftKey) {
55 that.execute_selected_cell();
55 that.execute_selected_cell();
56 return false;
56 return false;
57 } else if (event.which === 13 && event.ctrlKey) {
57 } else if (event.which === 13 && event.ctrlKey) {
58 that.execute_selected_cell({terminal:true});
58 that.execute_selected_cell({terminal:true});
59 return false;
59 return false;
60 };
60 };
61 });
61 });
62
62
63 this.element.bind('collapse_pager', function () {
63 this.element.bind('collapse_pager', function () {
64 var app_height = $('div#main_app').height(); // content height
64 var app_height = $('div#main_app').height(); // content height
65 var splitter_height = $('div#pager_splitter').outerHeight(true);
65 var splitter_height = $('div#pager_splitter').outerHeight(true);
66 var new_height = app_height - splitter_height;
66 var new_height = app_height - splitter_height;
67 that.element.animate({height : new_height + 'px'}, 'fast');
67 that.element.animate({height : new_height + 'px'}, 'fast');
68 });
68 });
69
69
70 this.element.bind('expand_pager', function () {
70 this.element.bind('expand_pager', function () {
71 var app_height = $('div#main_app').height(); // content height
71 var app_height = $('div#main_app').height(); // content height
72 var splitter_height = $('div#pager_splitter').outerHeight(true);
72 var splitter_height = $('div#pager_splitter').outerHeight(true);
73 var pager_height = $('div#pager').outerHeight(true);
73 var pager_height = $('div#pager').outerHeight(true);
74 var new_height = app_height - pager_height - splitter_height;
74 var new_height = app_height - pager_height - splitter_height;
75 that.element.animate({height : new_height + 'px'}, 'fast');
75 that.element.animate({height : new_height + 'px'}, 'fast');
76 });
76 });
77
77
78 this.element.bind('collapse_left_panel', function () {
78 this.element.bind('collapse_left_panel', function () {
79 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
79 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
80 var new_margin = splitter_width;
80 var new_margin = splitter_width;
81 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
81 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
82 });
82 });
83
83
84 this.element.bind('expand_left_panel', function () {
84 this.element.bind('expand_left_panel', function () {
85 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
85 var splitter_width = $('div#left_panel_splitter').outerWidth(true);
86 var left_panel_width = IPython.left_panel.width;
86 var left_panel_width = IPython.left_panel.width;
87 var new_margin = splitter_width + left_panel_width;
87 var new_margin = splitter_width + left_panel_width;
88 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
88 $('div#notebook_panel').animate({marginLeft : new_margin + 'px'}, 'fast');
89 });
89 });
90 };
90 };
91
91
92
92
93 Notebook.prototype.scroll_to_bottom = function () {
93 Notebook.prototype.scroll_to_bottom = function () {
94 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
94 this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
95 };
95 };
96
96
97
97
98 Notebook.prototype.scroll_to_top = function () {
98 Notebook.prototype.scroll_to_top = function () {
99 this.element.animate({scrollTop:0}, 0);
99 this.element.animate({scrollTop:0}, 0);
100 };
100 };
101
101
102
102
103 // Cell indexing, retrieval, etc.
103 // Cell indexing, retrieval, etc.
104
104
105
105
106 Notebook.prototype.cell_elements = function () {
106 Notebook.prototype.cell_elements = function () {
107 return this.element.children("div.cell");
107 return this.element.children("div.cell");
108 }
108 }
109
109
110
110
111 Notebook.prototype.ncells = function (cell) {
111 Notebook.prototype.ncells = function (cell) {
112 return this.cell_elements().length;
112 return this.cell_elements().length;
113 }
113 }
114
114
115
115
116 // TODO: we are often calling cells as cells()[i], which we should optimize
116 // TODO: we are often calling cells as cells()[i], which we should optimize
117 // to cells(i) or a new method.
117 // to cells(i) or a new method.
118 Notebook.prototype.cells = function () {
118 Notebook.prototype.cells = function () {
119 return this.cell_elements().toArray().map(function (e) {
119 return this.cell_elements().toArray().map(function (e) {
120 return $(e).data("cell");
120 return $(e).data("cell");
121 });
121 });
122 }
122 }
123
123
124
124
125 Notebook.prototype.find_cell_index = function (cell) {
125 Notebook.prototype.find_cell_index = function (cell) {
126 var result = null;
126 var result = null;
127 this.cell_elements().filter(function (index) {
127 this.cell_elements().filter(function (index) {
128 if ($(this).data("cell") === cell) {
128 if ($(this).data("cell") === cell) {
129 result = index;
129 result = index;
130 };
130 };
131 });
131 });
132 return result;
132 return result;
133 };
133 };
134
134
135
135
136 Notebook.prototype.index_or_selected = function (index) {
136 Notebook.prototype.index_or_selected = function (index) {
137 return index || this.selected_index() || 0;
137 return index || this.selected_index() || 0;
138 }
138 }
139
139
140
140
141 Notebook.prototype.select = function (index) {
141 Notebook.prototype.select = function (index) {
142 if (index !== undefined && index >= 0 && index < this.ncells()) {
142 if (index !== undefined && index >= 0 && index < this.ncells()) {
143 if (this.selected_index() !== null) {
143 if (this.selected_index() !== null) {
144 this.selected_cell().unselect();
144 this.selected_cell().unselect();
145 };
145 };
146 this.cells()[index].select();
146 this.cells()[index].select();
147 if (index === (this.ncells()-1)) {
147 if (index === (this.ncells()-1)) {
148 this.scroll_to_bottom();
148 this.scroll_to_bottom();
149 };
149 };
150 };
150 };
151 return this;
151 return this;
152 };
152 };
153
153
154
154
155 Notebook.prototype.select_next = function () {
155 Notebook.prototype.select_next = function () {
156 var index = this.selected_index();
156 var index = this.selected_index();
157 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
157 if (index !== null && index >= 0 && (index+1) < this.ncells()) {
158 this.select(index+1);
158 this.select(index+1);
159 };
159 };
160 return this;
160 return this;
161 };
161 };
162
162
163
163
164 Notebook.prototype.select_prev = function () {
164 Notebook.prototype.select_prev = function () {
165 var index = this.selected_index();
165 var index = this.selected_index();
166 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
166 if (index !== null && index >= 0 && (index-1) < this.ncells()) {
167 this.select(index-1);
167 this.select(index-1);
168 };
168 };
169 return this;
169 return this;
170 };
170 };
171
171
172
172
173 Notebook.prototype.selected_index = function () {
173 Notebook.prototype.selected_index = function () {
174 var result = null;
174 var result = null;
175 this.cell_elements().filter(function (index) {
175 this.cell_elements().filter(function (index) {
176 if ($(this).data("cell").selected === true) {
176 if ($(this).data("cell").selected === true) {
177 result = index;
177 result = index;
178 };
178 };
179 });
179 });
180 return result;
180 return result;
181 };
181 };
182
182
183
183
184 Notebook.prototype.cell_for_msg = function (msg_id) {
184 Notebook.prototype.cell_for_msg = function (msg_id) {
185 var cell_id = this.msg_cell_map[msg_id];
185 var cell_id = this.msg_cell_map[msg_id];
186 var result = null;
186 var result = null;
187 this.cell_elements().filter(function (index) {
187 this.cell_elements().filter(function (index) {
188 cell = $(this).data("cell");
188 cell = $(this).data("cell");
189 if (cell.cell_id === cell_id) {
189 if (cell.cell_id === cell_id) {
190 result = cell;
190 result = cell;
191 };
191 };
192 });
192 });
193 return result;
193 return result;
194 };
194 };
195
195
196
196
197 Notebook.prototype.selected_cell = function () {
197 Notebook.prototype.selected_cell = function () {
198 return this.cell_elements().eq(this.selected_index()).data("cell");
198 return this.cell_elements().eq(this.selected_index()).data("cell");
199 }
199 }
200
200
201
201
202 // Cell insertion, deletion and moving.
202 // Cell insertion, deletion and moving.
203
203
204
204
205 Notebook.prototype.delete_cell = function (index) {
205 Notebook.prototype.delete_cell = function (index) {
206 var i = index || this.selected_index();
206 var i = index || this.selected_index();
207 if (i !== null && i >= 0 && i < this.ncells()) {
207 if (i !== null && i >= 0 && i < this.ncells()) {
208 this.cell_elements().eq(i).remove();
208 this.cell_elements().eq(i).remove();
209 if (i === (this.ncells())) {
209 if (i === (this.ncells())) {
210 this.select(i-1);
210 this.select(i-1);
211 } else {
211 } else {
212 this.select(i);
212 this.select(i);
213 };
213 };
214 };
214 };
215 return this;
215 return this;
216 };
216 };
217
217
218
218
219 Notebook.prototype.append_cell = function (cell) {
219 Notebook.prototype.append_cell = function (cell) {
220 this.element.find('div.end_space').before(cell.element);
220 this.element.find('div.end_space').before(cell.element);
221 return this;
221 return this;
222 };
222 };
223
223
224
224
225 Notebook.prototype.insert_cell_after = function (cell, index) {
225 Notebook.prototype.insert_cell_after = function (cell, index) {
226 var ncells = this.ncells();
226 var ncells = this.ncells();
227 if (ncells === 0) {
227 if (ncells === 0) {
228 this.append_cell(cell);
228 this.append_cell(cell);
229 return this;
229 return this;
230 };
230 };
231 if (index >= 0 && index < ncells) {
231 if (index >= 0 && index < ncells) {
232 this.cell_elements().eq(index).after(cell.element);
232 this.cell_elements().eq(index).after(cell.element);
233 };
233 };
234 return this
234 return this
235 };
235 };
236
236
237
237
238 Notebook.prototype.insert_cell_before = function (cell, index) {
238 Notebook.prototype.insert_cell_before = 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).before(cell.element);
245 this.cell_elements().eq(index).before(cell.element);
246 };
246 };
247 return this;
247 return this;
248 };
248 };
249
249
250
250
251 Notebook.prototype.move_cell_up = function (index) {
251 Notebook.prototype.move_cell_up = function (index) {
252 var i = index || this.selected_index();
252 var i = index || this.selected_index();
253 if (i !== null && i < this.ncells() && i > 0) {
253 if (i !== null && i < this.ncells() && i > 0) {
254 var pivot = this.cell_elements().eq(i-1);
254 var pivot = this.cell_elements().eq(i-1);
255 var tomove = this.cell_elements().eq(i);
255 var tomove = this.cell_elements().eq(i);
256 if (pivot !== null && tomove !== null) {
256 if (pivot !== null && tomove !== null) {
257 tomove.detach();
257 tomove.detach();
258 pivot.before(tomove);
258 pivot.before(tomove);
259 this.select(i-1);
259 this.select(i-1);
260 };
260 };
261 };
261 };
262 return this;
262 return this;
263 }
263 }
264
264
265
265
266 Notebook.prototype.move_cell_down = function (index) {
266 Notebook.prototype.move_cell_down = function (index) {
267 var i = index || this.selected_index();
267 var i = index || this.selected_index();
268 if (i !== null && i < (this.ncells()-1) && i >= 0) {
268 if (i !== null && i < (this.ncells()-1) && 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.after(tomove);
273 pivot.after(tomove);
274 this.select(i+1);
274 this.select(i+1);
275 };
275 };
276 };
276 };
277 return this;
277 return this;
278 }
278 }
279
279
280
280
281 Notebook.prototype.sort_cells = function () {
281 Notebook.prototype.sort_cells = function () {
282 var ncells = this.ncells();
282 var ncells = this.ncells();
283 var sindex = this.selected_index();
283 var sindex = this.selected_index();
284 var swapped;
284 var swapped;
285 do {
285 do {
286 swapped = false
286 swapped = false
287 for (var i=1; i<ncells; i++) {
287 for (var i=1; i<ncells; i++) {
288 current = this.cell_elements().eq(i).data("cell");
288 current = this.cell_elements().eq(i).data("cell");
289 previous = this.cell_elements().eq(i-1).data("cell");
289 previous = this.cell_elements().eq(i-1).data("cell");
290 if (previous.input_prompt_number > current.input_prompt_number) {
290 if (previous.input_prompt_number > current.input_prompt_number) {
291 this.move_cell_up(i);
291 this.move_cell_up(i);
292 swapped = true;
292 swapped = true;
293 };
293 };
294 };
294 };
295 } while (swapped);
295 } while (swapped);
296 this.select(sindex);
296 this.select(sindex);
297 return this;
297 return this;
298 };
298 };
299
299
300
300
301 Notebook.prototype.insert_code_cell_before = function (index) {
301 Notebook.prototype.insert_code_cell_before = function (index) {
302 // TODO: Bounds check for i
302 // TODO: Bounds check for i
303 var i = this.index_or_selected(index);
303 var i = this.index_or_selected(index);
304 var cell = new IPython.CodeCell(this);
304 var cell = new IPython.CodeCell(this);
305 cell.set_input_prompt();
305 cell.set_input_prompt();
306 this.insert_cell_before(cell, i);
306 this.insert_cell_before(cell, i);
307 this.select(this.find_cell_index(cell));
307 this.select(this.find_cell_index(cell));
308 return cell;
308 return cell;
309 }
309 }
310
310
311
311
312 Notebook.prototype.insert_code_cell_after = function (index) {
312 Notebook.prototype.insert_code_cell_after = function (index) {
313 // TODO: Bounds check for i
313 // TODO: Bounds check for i
314 var i = this.index_or_selected(index);
314 var i = this.index_or_selected(index);
315 var cell = new IPython.CodeCell(this);
315 var cell = new IPython.CodeCell(this);
316 cell.set_input_prompt();
316 cell.set_input_prompt();
317 this.insert_cell_after(cell, i);
317 this.insert_cell_after(cell, i);
318 this.select(this.find_cell_index(cell));
318 this.select(this.find_cell_index(cell));
319 return cell;
319 return cell;
320 }
320 }
321
321
322
322
323 Notebook.prototype.insert_html_cell_before = function (index) {
323 Notebook.prototype.insert_html_cell_before = function (index) {
324 // TODO: Bounds check for i
324 // TODO: Bounds check for i
325 var i = this.index_or_selected(index);
325 var i = this.index_or_selected(index);
326 var cell = new IPython.HTMLCell(this);
326 var cell = new IPython.HTMLCell(this);
327 cell.config_mathjax();
327 cell.config_mathjax();
328 this.insert_cell_before(cell, i);
328 this.insert_cell_before(cell, i);
329 this.select(this.find_cell_index(cell));
329 this.select(this.find_cell_index(cell));
330 return cell;
330 return cell;
331 }
331 }
332
332
333
333
334 Notebook.prototype.insert_html_cell_after = function (index) {
334 Notebook.prototype.insert_html_cell_after = function (index) {
335 // TODO: Bounds check for i
335 // TODO: Bounds check for i
336 var i = this.index_or_selected(index);
336 var i = this.index_or_selected(index);
337 var cell = new IPython.HTMLCell(this);
337 var cell = new IPython.HTMLCell(this);
338 cell.config_mathjax();
338 cell.config_mathjax();
339 this.insert_cell_after(cell, i);
339 this.insert_cell_after(cell, i);
340 this.select(this.find_cell_index(cell));
340 this.select(this.find_cell_index(cell));
341 return cell;
341 return cell;
342 }
342 }
343
343
344
344
345 Notebook.prototype.insert_markdown_cell_before = function (index) {
345 Notebook.prototype.insert_markdown_cell_before = function (index) {
346 // TODO: Bounds check for i
346 // TODO: Bounds check for i
347 var i = this.index_or_selected(index);
347 var i = this.index_or_selected(index);
348 var cell = new IPython.MarkdownCell(this);
348 var cell = new IPython.MarkdownCell(this);
349 cell.config_mathjax();
349 cell.config_mathjax();
350 this.insert_cell_before(cell, i);
350 this.insert_cell_before(cell, i);
351 this.select(this.find_cell_index(cell));
351 this.select(this.find_cell_index(cell));
352 return cell;
352 return cell;
353 }
353 }
354
354
355
355
356 Notebook.prototype.insert_markdown_cell_after = function (index) {
356 Notebook.prototype.insert_markdown_cell_after = function (index) {
357 // TODO: Bounds check for i
357 // TODO: Bounds check for i
358 var i = this.index_or_selected(index);
358 var i = this.index_or_selected(index);
359 var cell = new IPython.MarkdownCell(this);
359 var cell = new IPython.MarkdownCell(this);
360 cell.config_mathjax();
360 cell.config_mathjax();
361 this.insert_cell_after(cell, i);
361 this.insert_cell_after(cell, i);
362 this.select(this.find_cell_index(cell));
362 this.select(this.find_cell_index(cell));
363 return cell;
363 return cell;
364 }
364 }
365
365
366
366
367 Notebook.prototype.to_code = function (index) {
367 Notebook.prototype.to_code = function (index) {
368 // TODO: Bounds check for i
368 // TODO: Bounds check for i
369 var i = this.index_or_selected(index);
369 var i = this.index_or_selected(index);
370 var source_element = this.cell_elements().eq(i);
370 var source_element = this.cell_elements().eq(i);
371 var source_cell = source_element.data("cell");
371 var source_cell = source_element.data("cell");
372 if (source_cell instanceof IPython.HTMLCell ||
372 if (source_cell instanceof IPython.HTMLCell ||
373 source_cell instanceof IPython.MarkdownCell) {
373 source_cell instanceof IPython.MarkdownCell) {
374 this.insert_code_cell_after(i);
374 this.insert_code_cell_after(i);
375 var target_cell = this.cells()[i+1];
375 var target_cell = this.cells()[i+1];
376 target_cell.set_code(source_cell.get_source());
376 target_cell.set_code(source_cell.get_source());
377 source_element.remove();
377 source_element.remove();
378 };
378 };
379 };
379 };
380
380
381
381
382 Notebook.prototype.to_markdown = function (index) {
382 Notebook.prototype.to_markdown = function (index) {
383 // TODO: Bounds check for i
383 // TODO: Bounds check for i
384 var i = this.index_or_selected(index);
384 var i = this.index_or_selected(index);
385 var source_element = this.cell_elements().eq(i);
385 var source_element = this.cell_elements().eq(i);
386 var source_cell = source_element.data("cell");
386 var source_cell = source_element.data("cell");
387 var target_cell = null;
387 var target_cell = null;
388 if (source_cell instanceof IPython.CodeCell) {
388 if (source_cell instanceof IPython.CodeCell) {
389 this.insert_markdown_cell_after(i);
389 this.insert_markdown_cell_after(i);
390 var target_cell = this.cells()[i+1];
390 var target_cell = this.cells()[i+1];
391 var text = source_cell.get_code();
391 var text = source_cell.get_code();
392 } else if (source_cell instanceof IPython.HTMLCell) {
392 } else if (source_cell instanceof IPython.HTMLCell) {
393 this.insert_markdown_cell_after(i);
393 this.insert_markdown_cell_after(i);
394 var target_cell = this.cells()[i+1];
394 var target_cell = this.cells()[i+1];
395 var text = source_cell.get_source();
395 var text = source_cell.get_source();
396 if (text === source_cell.placeholder) {
396 if (text === source_cell.placeholder) {
397 text = target_cell.placeholder;
397 text = target_cell.placeholder;
398 }
398 }
399 }
399 }
400 if (target_cell !== null) {
400 if (target_cell !== null) {
401 if (text === "") {text = target_cell.placeholder;};
401 if (text === "") {text = target_cell.placeholder;};
402 target_cell.set_source(text);
402 target_cell.set_source(text);
403 source_element.remove();
403 source_element.remove();
404 target_cell.edit();
404 target_cell.edit();
405 }
405 }
406 };
406 };
407
407
408
408
409 Notebook.prototype.to_html = function (index) {
409 Notebook.prototype.to_html = function (index) {
410 // TODO: Bounds check for i
410 // TODO: Bounds check for i
411 var i = this.index_or_selected(index);
411 var i = this.index_or_selected(index);
412 var source_element = this.cell_elements().eq(i);
412 var source_element = this.cell_elements().eq(i);
413 var source_cell = source_element.data("cell");
413 var source_cell = source_element.data("cell");
414 var target_cell = null;
414 var target_cell = null;
415 if (source_cell instanceof IPython.CodeCell) {
415 if (source_cell instanceof IPython.CodeCell) {
416 this.insert_html_cell_after(i);
416 this.insert_html_cell_after(i);
417 var target_cell = this.cells()[i+1];
417 var target_cell = this.cells()[i+1];
418 var text = source_cell.get_code();
418 var text = source_cell.get_code();
419 } else if (source_cell instanceof IPython.MarkdownCell) {
419 } else if (source_cell instanceof IPython.MarkdownCell) {
420 this.insert_html_cell_after(i);
420 this.insert_html_cell_after(i);
421 var target_cell = this.cells()[i+1];
421 var target_cell = this.cells()[i+1];
422 var text = source_cell.get_source();
422 var text = source_cell.get_source();
423 if (text === source_cell.placeholder) {
423 if (text === source_cell.placeholder) {
424 text = target_cell.placeholder;
424 text = target_cell.placeholder;
425 }
425 }
426 }
426 }
427 if (target_cell !== null) {
427 if (target_cell !== null) {
428 if (text === "") {text = target_cell.placeholder;};
428 if (text === "") {text = target_cell.placeholder;};
429 target_cell.set_source(text);
429 target_cell.set_source(text);
430 source_element.remove();
430 source_element.remove();
431 target_cell.edit();
431 target_cell.edit();
432 }
432 }
433 };
433 };
434
434
435
435
436 // Cell collapsing
436 // Cell collapsing
437
437
438 Notebook.prototype.collapse = function (index) {
438 Notebook.prototype.collapse = function (index) {
439 var i = this.index_or_selected(index);
439 var i = this.index_or_selected(index);
440 this.cells()[i].collapse();
440 this.cells()[i].collapse();
441 };
441 };
442
442
443
443
444 Notebook.prototype.expand = function (index) {
444 Notebook.prototype.expand = function (index) {
445 var i = this.index_or_selected(index);
445 var i = this.index_or_selected(index);
446 this.cells()[i].expand();
446 this.cells()[i].expand();
447 };
447 };
448
448
449
449
450 // Kernel related things
450 // Kernel related things
451
451
452 Notebook.prototype.start_kernel = function () {
452 Notebook.prototype.start_kernel = function () {
453 this.kernel = new IPython.Kernel();
453 this.kernel = new IPython.Kernel();
454 var notebook_id = IPython.save_widget.get_notebook_id();
454 var notebook_id = IPython.save_widget.get_notebook_id();
455 this.kernel.start_kernel(notebook_id, $.proxy(this.kernel_started, this));
455 this.kernel.start_kernel(notebook_id, $.proxy(this.kernel_started, this));
456 };
456 };
457
457
458
458
459 Notebook.prototype.handle_shell_reply = function (e) {
459 Notebook.prototype.handle_shell_reply = function (e) {
460 reply = $.parseJSON(e.data);
460 reply = $.parseJSON(e.data);
461 var header = reply.header;
461 var header = reply.header;
462 var content = reply.content;
462 var content = reply.content;
463 var msg_type = header.msg_type;
463 var msg_type = header.msg_type;
464 // console.log(reply);
464 // console.log(reply);
465 var cell = this.cell_for_msg(reply.parent_header.msg_id);
465 var cell = this.cell_for_msg(reply.parent_header.msg_id);
466 if (msg_type === "execute_reply") {
466 if (msg_type === "execute_reply") {
467 cell.set_input_prompt(content.execution_count);
467 cell.set_input_prompt(content.execution_count);
468 } else if (msg_type === "complete_reply") {
468 } else if (msg_type === "complete_reply") {
469 cell.finish_completing(content.matched_text, content.matches);
469 cell.finish_completing(content.matched_text, content.matches);
470 };
470 };
471 var payload = content.payload || [];
471 var payload = content.payload || [];
472 this.handle_payload(payload);
472 this.handle_payload(payload);
473 };
473 };
474
474
475
475
476 Notebook.prototype.handle_payload = function (payload) {
476 Notebook.prototype.handle_payload = function (payload) {
477 var l = payload.length;
477 var l = payload.length;
478 if (l > 0) {
478 if (l > 0) {
479 IPython.pager.clear();
479 IPython.pager.clear();
480 IPython.pager.expand();
480 IPython.pager.expand();
481 };
481 };
482 for (var i=0; i<l; i++) {
482 for (var i=0; i<l; i++) {
483 IPython.pager.append_text(payload[i].text);
483 IPython.pager.append_text(payload[i].text);
484 };
484 };
485 };
485 };
486
486
487
487
488 Notebook.prototype.handle_iopub_reply = function (e) {
488 Notebook.prototype.handle_iopub_reply = function (e) {
489 reply = $.parseJSON(e.data);
489 reply = $.parseJSON(e.data);
490 var content = reply.content;
490 var content = reply.content;
491 // console.log(reply);
491 // console.log(reply);
492 var msg_type = reply.header.msg_type;
492 var msg_type = reply.header.msg_type;
493 var cell = this.cell_for_msg(reply.parent_header.msg_id);
493 var cell = this.cell_for_msg(reply.parent_header.msg_id);
494 var output_types = ['stream','display_data','pyout','pyerr'];
494 var output_types = ['stream','display_data','pyout','pyerr'];
495 if (output_types.indexOf(msg_type) >= 0) {
495 if (output_types.indexOf(msg_type) >= 0) {
496 this.handle_output(cell, msg_type, content);
496 this.handle_output(cell, msg_type, content);
497 } else if (msg_type === "status") {
497 } else if (msg_type === "status") {
498 if (content.execution_state === "busy") {
498 if (content.execution_state === "busy") {
499 IPython.kernel_status_widget.status_busy();
499 IPython.kernel_status_widget.status_busy();
500 } else if (content.execution_state === "idle") {
500 } else if (content.execution_state === "idle") {
501 IPython.kernel_status_widget.status_idle();
501 IPython.kernel_status_widget.status_idle();
502 };
502 };
503 }
503 }
504 };
504 };
505
505
506
506
507 Notebook.prototype.handle_output = function (cell, msg_type, content) {
507 Notebook.prototype.handle_output = function (cell, msg_type, content) {
508 var json = {};
508 var json = {};
509 json.output_type = msg_type;
509 json.output_type = msg_type;
510 if (msg_type === "stream") {
510 if (msg_type === "stream") {
511 json.text = content.data + '\n';
511 json.text = content.data + '\n';
512 } else if (msg_type === "display_data") {
512 } else if (msg_type === "display_data") {
513 json = this.convert_mime_types(json, content.data);
513 json = this.convert_mime_types(json, content.data);
514 } else if (msg_type === "pyout") {
514 } else if (msg_type === "pyout") {
515 json.prompt_number = content.execution_count;
515 json.prompt_number = content.execution_count;
516 json = this.convert_mime_types(json, content.data);
516 json = this.convert_mime_types(json, content.data);
517 } else if (msg_type === "pyerr") {
517 } else if (msg_type === "pyerr") {
518 json.ename = content.ename;
518 json.ename = content.ename;
519 json.evalue = content.evalue;
519 json.evalue = content.evalue;
520 json.traceback = content.traceback;
520 json.traceback = content.traceback;
521 };
521 };
522 cell.append_output(json);
522 cell.append_output(json);
523 };
523 };
524
524
525
525
526 Notebook.prototype.convert_mime_types = function (json, data) {
526 Notebook.prototype.convert_mime_types = function (json, data) {
527 if (data['text/plain'] !== undefined) {
527 if (data['text/plain'] !== undefined) {
528 json.text = data['text/plain'];
528 json.text = data['text/plain'];
529 };
529 };
530 if (data['text/html'] !== undefined) {
530 if (data['text/html'] !== undefined) {
531 json.html = data['text/html'];
531 json.html = data['text/html'];
532 };
532 };
533 if (data['image/svg+xml'] !== undefined) {
533 if (data['image/svg+xml'] !== undefined) {
534 json.svg = data['image/svg+xml'];
534 json.svg = data['image/svg+xml'];
535 };
535 };
536 if (data['image/png'] !== undefined) {
536 if (data['image/png'] !== undefined) {
537 json.png = data['image/png'];
537 json.png = data['image/png'];
538 };
538 };
539 if (data['text/latex'] !== undefined) {
539 if (data['text/latex'] !== undefined) {
540 json.latex = data['text/latex'];
540 json.latex = data['text/latex'];
541 };
541 };
542 if (data['application/json'] !== undefined) {
542 if (data['application/json'] !== undefined) {
543 json.json = data['application/json'];
543 json.json = data['application/json'];
544 };
544 };
545 if (data['application/javascript'] !== undefined) {
545 if (data['application/javascript'] !== undefined) {
546 json.javascript = data['application/javascript'];
546 json.javascript = data['application/javascript'];
547 }
547 }
548 return json;
548 return json;
549 };
549 };
550
550
551 Notebook.prototype.kernel_started = function () {
551 Notebook.prototype.kernel_started = function () {
552 console.log("Kernel started: ", this.kernel.kernel_id);
552 console.log("Kernel started: ", this.kernel.kernel_id);
553 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
553 this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
554 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
554 this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
555 };
555 };
556
556
557
557
558 Notebook.prototype.execute_selected_cell = function (options) {
558 Notebook.prototype.execute_selected_cell = function (options) {
559 // add_new: should a new cell be added if we are at the end of the nb
559 // add_new: should a new cell be added if we are at the end of the nb
560 // terminal: execute in terminal mode, which stays in the current cell
560 // terminal: execute in terminal mode, which stays in the current cell
561 default_options = {terminal: false, add_new: true}
561 default_options = {terminal: false, add_new: true}
562 $.extend(default_options, options)
562 $.extend(default_options, options)
563 var that = this;
563 var that = this;
564 var cell = that.selected_cell();
564 var cell = that.selected_cell();
565 var cell_index = that.find_cell_index(cell);
565 var cell_index = that.find_cell_index(cell);
566 if (cell instanceof IPython.CodeCell) {
566 if (cell instanceof IPython.CodeCell) {
567 cell.clear_output();
567 cell.clear_output();
568 var code = cell.get_code();
568 var code = cell.get_code();
569 var msg_id = that.kernel.execute(cell.get_code());
569 var msg_id = that.kernel.execute(cell.get_code());
570 that.msg_cell_map[msg_id] = cell.cell_id;
570 that.msg_cell_map[msg_id] = cell.cell_id;
571 } else if (cell instanceof IPython.HTMLCell) {
571 } else if (cell instanceof IPython.HTMLCell) {
572 cell.render();
572 cell.render();
573 }
573 }
574 if (default_options.terminal) {
574 if (default_options.terminal) {
575 cell.clear_input();
575 cell.clear_input();
576 } else {
576 } else {
577 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
577 if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
578 that.insert_code_cell_after();
578 that.insert_code_cell_after();
579 // If we are adding a new cell at the end, scroll down to show it.
579 // If we are adding a new cell at the end, scroll down to show it.
580 that.scroll_to_bottom();
580 that.scroll_to_bottom();
581 } else {
581 } else {
582 that.select(cell_index+1);
582 that.select(cell_index+1);
583 };
583 };
584 };
584 };
585 };
585 };
586
586
587
587
588 Notebook.prototype.execute_all_cells = function () {
588 Notebook.prototype.execute_all_cells = function () {
589 var ncells = this.ncells();
589 var ncells = this.ncells();
590 for (var i=0; i<ncells; i++) {
590 for (var i=0; i<ncells; i++) {
591 this.select(i);
591 this.select(i);
592 this.execute_selected_cell({add_new:false});
592 this.execute_selected_cell({add_new:false});
593 };
593 };
594 this.scroll_to_bottom();
594 this.scroll_to_bottom();
595 };
595 };
596
596
597
597
598 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
598 Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
599 var msg_id = this.kernel.complete(line, cursor_pos);
599 var msg_id = this.kernel.complete(line, cursor_pos);
600 this.msg_cell_map[msg_id] = cell.cell_id;
600 this.msg_cell_map[msg_id] = cell.cell_id;
601 };
601 };
602
602
603 // Persistance and loading
603 // Persistance and loading
604
604
605
605
606 Notebook.prototype.fromJSON = function (data) {
606 Notebook.prototype.fromJSON = function (data) {
607 var ncells = this.ncells();
607 var ncells = this.ncells();
608 for (var i=0; i<ncells; i++) {
608 for (var i=0; i<ncells; i++) {
609 // Always delete cell 0 as they get renumbered as they are deleted.
609 // Always delete cell 0 as they get renumbered as they are deleted.
610 this.delete_cell(0);
610 this.delete_cell(0);
611 };
611 };
612 // Only handle 1 worksheet for now.
612 // Only handle 1 worksheet for now.
613 var worksheet = data.worksheets[0];
613 var worksheet = data.worksheets[0];
614 if (worksheet !== undefined) {
614 if (worksheet !== undefined) {
615 var new_cells = worksheet.cells;
615 var new_cells = worksheet.cells;
616 ncells = new_cells.length;
616 ncells = new_cells.length;
617 var cell_data = null;
617 var cell_data = null;
618 var new_cell = null;
618 var new_cell = null;
619 for (var i=0; i<ncells; i++) {
619 for (var i=0; i<ncells; i++) {
620 cell_data = new_cells[i];
620 cell_data = new_cells[i];
621 if (cell_data.cell_type == 'code') {
621 if (cell_data.cell_type == 'code') {
622 new_cell = this.insert_code_cell_after();
622 new_cell = this.insert_code_cell_after();
623 new_cell.fromJSON(cell_data);
623 new_cell.fromJSON(cell_data);
624 } else if (cell_data.cell_type === 'html') {
624 } else if (cell_data.cell_type === 'html') {
625 new_cell = this.insert_html_cell_after();
625 new_cell = this.insert_html_cell_after();
626 new_cell.fromJSON(cell_data);
626 new_cell.fromJSON(cell_data);
627 } else if (cell_data.cell_type === 'markdown') {
628 new_cell = this.insert_markdown_cell_after();
629 new_cell.fromJSON(cell_data);
627 };
630 };
628 };
631 };
629 };
632 };
630 };
633 };
631
634
632
635
633 Notebook.prototype.toJSON = function () {
636 Notebook.prototype.toJSON = function () {
634 var cells = this.cells();
637 var cells = this.cells();
635 var ncells = cells.length;
638 var ncells = cells.length;
636 cell_array = new Array(ncells);
639 cell_array = new Array(ncells);
637 for (var i=0; i<ncells; i++) {
640 for (var i=0; i<ncells; i++) {
638 cell_array[i] = cells[i].toJSON();
641 cell_array[i] = cells[i].toJSON();
639 };
642 };
640 data = {
643 data = {
641 // Only handle 1 worksheet for now.
644 // Only handle 1 worksheet for now.
642 worksheets : [{cells:cell_array}]
645 worksheets : [{cells:cell_array}]
643 }
646 }
644 return data
647 return data
645 };
648 };
646
649
647 Notebook.prototype.save_notebook = function () {
650 Notebook.prototype.save_notebook = function () {
648 if (IPython.save_widget.test_notebook_name()) {
651 if (IPython.save_widget.test_notebook_name()) {
649 var notebook_id = IPython.save_widget.get_notebook_id();
652 var notebook_id = IPython.save_widget.get_notebook_id();
650 var nbname = IPython.save_widget.get_notebook_name();
653 var nbname = IPython.save_widget.get_notebook_name();
651 // We may want to move the name/id/nbformat logic inside toJSON?
654 // We may want to move the name/id/nbformat logic inside toJSON?
652 var data = this.toJSON();
655 var data = this.toJSON();
653 data.name = nbname;
656 data.name = nbname;
654 data.nbformat = 2;
657 data.nbformat = 2;
655 data.id = notebook_id
658 data.id = notebook_id
656 // We do the call with settings so we can set cache to false.
659 // We do the call with settings so we can set cache to false.
657 var settings = {
660 var settings = {
658 processData : false,
661 processData : false,
659 cache : false,
662 cache : false,
660 type : "PUT",
663 type : "PUT",
661 data : JSON.stringify(data),
664 data : JSON.stringify(data),
662 headers : {'Content-Type': 'application/json'},
665 headers : {'Content-Type': 'application/json'},
663 success : $.proxy(this.notebook_saved,this)
666 success : $.proxy(this.notebook_saved,this)
664 };
667 };
665 IPython.save_widget.status_saving();
668 IPython.save_widget.status_saving();
666 $.ajax("/notebooks/" + notebook_id, settings);
669 $.ajax("/notebooks/" + notebook_id, settings);
667 };
670 };
668 };
671 };
669
672
670
673
671 Notebook.prototype.notebook_saved = function (data, status, xhr) {
674 Notebook.prototype.notebook_saved = function (data, status, xhr) {
672 IPython.save_widget.status_save();
675 IPython.save_widget.status_save();
673 }
676 }
674
677
675
678
676 Notebook.prototype.load_notebook = function (callback) {
679 Notebook.prototype.load_notebook = function (callback) {
677 var that = this;
680 var that = this;
678 var notebook_id = IPython.save_widget.get_notebook_id();
681 var notebook_id = IPython.save_widget.get_notebook_id();
679 // We do the call with settings so we can set cache to false.
682 // We do the call with settings so we can set cache to false.
680 var settings = {
683 var settings = {
681 processData : false,
684 processData : false,
682 cache : false,
685 cache : false,
683 type : "GET",
686 type : "GET",
684 dataType : "json",
687 dataType : "json",
685 success : function (data, status, xhr) {
688 success : function (data, status, xhr) {
686 that.notebook_loaded(data, status, xhr);
689 that.notebook_loaded(data, status, xhr);
687 if (callback !== undefined) {
690 if (callback !== undefined) {
688 callback();
691 callback();
689 };
692 };
690 }
693 }
691 };
694 };
692 IPython.save_widget.status_loading();
695 IPython.save_widget.status_loading();
693 $.ajax("/notebooks/" + notebook_id, settings);
696 $.ajax("/notebooks/" + notebook_id, settings);
694 }
697 }
695
698
696
699
697 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
700 Notebook.prototype.notebook_loaded = function (data, status, xhr) {
698 this.fromJSON(data);
701 this.fromJSON(data);
699 if (this.ncells() === 0) {
702 if (this.ncells() === 0) {
700 this.insert_code_cell_after();
703 this.insert_code_cell_after();
701 };
704 };
702 IPython.save_widget.status_save();
705 IPython.save_widget.status_save();
703 IPython.save_widget.set_notebook_name(data.name);
706 IPython.save_widget.set_notebook_name(data.name);
704 this.start_kernel();
707 this.start_kernel();
705 // fromJSON always selects the last cell inserted. We need to wait
708 // fromJSON always selects the last cell inserted. We need to wait
706 // until that is done before scrolling to the top.
709 // until that is done before scrolling to the top.
707 setTimeout(function () {
710 setTimeout(function () {
708 IPython.notebook.select(0);
711 IPython.notebook.select(0);
709 IPython.notebook.scroll_to_top();
712 IPython.notebook.scroll_to_top();
710 }, 50);
713 }, 50);
711 };
714 };
712
715
713 IPython.Notebook = Notebook;
716 IPython.Notebook = Notebook;
714
717
715 return IPython;
718 return IPython;
716
719
717 }(IPython));
720 }(IPython));
718
721
@@ -1,249 +1,249 b''
1
1
2 //============================================================================
2 //============================================================================
3 // TextCell
3 // TextCell
4 //============================================================================
4 //============================================================================
5
5
6 var IPython = (function (IPython) {
6 var IPython = (function (IPython) {
7
7
8 // TextCell base class
8 // TextCell base class
9
9
10 var TextCell = function (notebook) {
10 var TextCell = function (notebook) {
11 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
11 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
12 this.placeholder = this.placeholder || '';
12 this.placeholder = this.placeholder || '';
13 IPython.Cell.apply(this, arguments);
13 IPython.Cell.apply(this, arguments);
14 this.rendered = false;
14 this.rendered = false;
15 this.cell_type = this.cell_type || 'text';
15 this.cell_type = this.cell_type || 'text';
16 };
16 };
17
17
18
18
19 TextCell.prototype = new IPython.Cell();
19 TextCell.prototype = new IPython.Cell();
20
20
21
21
22 TextCell.prototype.create_element = function () {
22 TextCell.prototype.create_element = function () {
23 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
23 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
24 var input_area = $('<div/>').addClass('text_cell_input');
24 var input_area = $('<div/>').addClass('text_cell_input');
25 this.code_mirror = CodeMirror(input_area.get(0), {
25 this.code_mirror = CodeMirror(input_area.get(0), {
26 indentUnit : 4,
26 indentUnit : 4,
27 enterMode : 'flat',
27 enterMode : 'flat',
28 tabMode: 'shift',
28 tabMode: 'shift',
29 mode: this.code_mirror_mode,
29 mode: this.code_mirror_mode,
30 theme: 'default',
30 theme: 'default',
31 value: this.placeholder
31 value: this.placeholder
32 });
32 });
33 // The tabindex=-1 makes this div focusable.
33 // The tabindex=-1 makes this div focusable.
34 var render_area = $('<div/>').addClass('text_cell_render').
34 var render_area = $('<div/>').addClass('text_cell_render').
35 addClass('rendered_html').attr('tabindex','-1');
35 addClass('rendered_html').attr('tabindex','-1');
36 cell.append(input_area).append(render_area);
36 cell.append(input_area).append(render_area);
37 this.element = cell;
37 this.element = cell;
38 };
38 };
39
39
40
40
41 TextCell.prototype.bind_events = function () {
41 TextCell.prototype.bind_events = function () {
42 IPython.Cell.prototype.bind_events.apply(this);
42 IPython.Cell.prototype.bind_events.apply(this);
43 var that = this;
43 var that = this;
44 this.element.keydown(function (event) {
44 this.element.keydown(function (event) {
45 if (event.which === 13) {
45 if (event.which === 13) {
46 if (that.rendered) {
46 if (that.rendered) {
47 that.edit();
47 that.edit();
48 event.preventDefault();
48 event.preventDefault();
49 };
49 };
50 };
50 };
51 });
51 });
52 };
52 };
53
53
54
54
55 TextCell.prototype.select = function () {
55 TextCell.prototype.select = function () {
56 IPython.Cell.prototype.select.apply(this);
56 IPython.Cell.prototype.select.apply(this);
57 var output = this.element.find("div.text_cell_render");
57 var output = this.element.find("div.text_cell_render");
58 output.trigger('focus');
58 output.trigger('focus');
59 };
59 };
60
60
61
61
62 TextCell.prototype.edit = function () {
62 TextCell.prototype.edit = function () {
63 if (this.rendered === true) {
63 if (this.rendered === true) {
64 var text_cell = this.element;
64 var text_cell = this.element;
65 var output = text_cell.find("div.text_cell_render");
65 var output = text_cell.find("div.text_cell_render");
66 output.hide();
66 output.hide();
67 text_cell.find('div.text_cell_input').show();
67 text_cell.find('div.text_cell_input').show();
68 this.code_mirror.focus();
68 this.code_mirror.focus();
69 this.code_mirror.refresh();
69 this.code_mirror.refresh();
70 this.rendered = false;
70 this.rendered = false;
71 };
71 };
72 };
72 };
73
73
74
74
75 // Subclasses must define render.
75 // Subclasses must define render.
76 TextCell.prototype.render = function () {};
76 TextCell.prototype.render = function () {};
77
77
78
78
79 TextCell.prototype.config_mathjax = function () {
79 TextCell.prototype.config_mathjax = function () {
80 var text_cell = this.element;
80 var text_cell = this.element;
81 var that = this;
81 var that = this;
82 text_cell.click(function () {
82 text_cell.click(function () {
83 that.edit();
83 that.edit();
84 }).focusout(function () {
84 }).focusout(function () {
85 that.render();
85 that.render();
86 });
86 });
87
87
88 text_cell.trigger("focusout");
88 text_cell.trigger("focusout");
89 };
89 };
90
90
91
91
92 TextCell.prototype.get_source = function() {
92 TextCell.prototype.get_source = function() {
93 return this.code_mirror.getValue();
93 return this.code_mirror.getValue();
94 };
94 };
95
95
96
96
97 TextCell.prototype.set_source = function(text) {
97 TextCell.prototype.set_source = function(text) {
98 this.code_mirror.setValue(text);
98 this.code_mirror.setValue(text);
99 this.code_mirror.refresh();
99 this.code_mirror.refresh();
100 };
100 };
101
101
102
102
103 TextCell.prototype.get_rendered = function(text) {
103 TextCell.prototype.get_rendered = function(text) {
104 return this.element.find('div.text_cell_render').html();
104 return this.element.find('div.text_cell_render').html();
105 };
105 };
106
106
107
107
108 TextCell.prototype.set_rendered = function(text) {
108 TextCell.prototype.set_rendered = function(text) {
109 this.element.find('div.text_cell_render').html(text);
109 this.element.find('div.text_cell_render').html(text);
110 };
110 };
111
111
112
112
113 TextCell.prototype.at_top = function () {
113 TextCell.prototype.at_top = function () {
114 if (this.rendered) {
114 if (this.rendered) {
115 return true;
115 return true;
116 } else {
116 } else {
117 return false;
117 return false;
118 }
118 }
119 };
119 };
120
120
121
121
122 TextCell.prototype.at_bottom = function () {
122 TextCell.prototype.at_bottom = function () {
123 if (this.rendered) {
123 if (this.rendered) {
124 return true;
124 return true;
125 } else {
125 } else {
126 return false;
126 return false;
127 }
127 }
128 };
128 };
129
129
130
130
131 TextCell.prototype.fromJSON = function (data) {
131 TextCell.prototype.fromJSON = function (data) {
132 if (data.cell_type === this.cell_type) {
132 if (data.cell_type === this.cell_type) {
133 if (data.source !== undefined) {
133 if (data.source !== undefined) {
134 this.set_source(data.source);
134 this.set_source(data.source);
135 this.set_rendered(data.source);
135 this.set_rendered(data.rendered);
136 };
136 };
137 };
137 };
138 }
138 }
139
139
140
140
141 TextCell.prototype.toJSON = function () {
141 TextCell.prototype.toJSON = function () {
142 var data = {}
142 var data = {}
143 data.cell_type = this.cell_type;
143 data.cell_type = this.cell_type;
144 data.source = this.get_source();
144 data.source = this.get_source();
145 data.rendered = this.get_rendered();
145 data.rendered = this.get_rendered();
146 return data;
146 return data;
147 };
147 };
148
148
149
149
150 // HTMLCell
150 // HTMLCell
151
151
152 var HTMLCell = function (notebook) {
152 var HTMLCell = function (notebook) {
153 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
153 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
154 IPython.TextCell.apply(this, arguments);
154 IPython.TextCell.apply(this, arguments);
155 this.cell_type = 'html';
155 this.cell_type = 'html';
156 };
156 };
157
157
158
158
159 HTMLCell.prototype = new TextCell();
159 HTMLCell.prototype = new TextCell();
160
160
161
161
162 HTMLCell.prototype.render = function () {
162 HTMLCell.prototype.render = function () {
163 if (this.rendered === false) {
163 if (this.rendered === false) {
164 var text = this.get_source();
164 var text = this.get_source();
165 if (text === "") {text = this.placeholder;};
165 if (text === "") {text = this.placeholder;};
166 this.set_rendered(text);
166 this.set_rendered(text);
167 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
167 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
168 this.element.find('div.text_cell_input').hide();
168 this.element.find('div.text_cell_input').hide();
169 this.element.find("div.text_cell_render").show();
169 this.element.find("div.text_cell_render").show();
170 this.rendered = true;
170 this.rendered = true;
171 };
171 };
172 };
172 };
173
173
174
174
175 // MarkdownCell
175 // MarkdownCell
176
176
177 var MarkdownCell = function (notebook) {
177 var MarkdownCell = function (notebook) {
178 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
178 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
179 IPython.TextCell.apply(this, arguments);
179 IPython.TextCell.apply(this, arguments);
180 this.cell_type = 'markdown';
180 this.cell_type = 'markdown';
181 };
181 };
182
182
183
183
184 MarkdownCell.prototype = new TextCell();
184 MarkdownCell.prototype = new TextCell();
185
185
186
186
187 MarkdownCell.prototype.render = function () {
187 MarkdownCell.prototype.render = function () {
188 if (this.rendered === false) {
188 if (this.rendered === false) {
189 var text = this.get_source();
189 var text = this.get_source();
190 if (text === "") {text = this.placeholder;};
190 if (text === "") {text = this.placeholder;};
191 var html = IPython.markdown_converter.makeHtml(text);
191 var html = IPython.markdown_converter.makeHtml(text);
192 this.set_rendered(html);
192 this.set_rendered(html);
193 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
193 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
194 this.element.find('div.text_cell_input').hide();
194 this.element.find('div.text_cell_input').hide();
195 this.element.find("div.text_cell_render").show();
195 this.element.find("div.text_cell_render").show();
196 this.rendered = true;
196 this.rendered = true;
197 };
197 };
198 };
198 };
199
199
200
200
201 // RSTCell
201 // RSTCell
202
202
203 var RSTCell = function (notebook) {
203 var RSTCell = function (notebook) {
204 this.placeholder = "Type *ReStructured Text* and LaTeX: $\\alpha^2$";
204 this.placeholder = "Type *ReStructured Text* and LaTeX: $\\alpha^2$";
205 IPython.TextCell.apply(this, arguments);
205 IPython.TextCell.apply(this, arguments);
206 this.cell_type = 'rst';
206 this.cell_type = 'rst';
207 };
207 };
208
208
209
209
210 RSTCell.prototype = new TextCell();
210 RSTCell.prototype = new TextCell();
211
211
212
212
213 RSTCell.prototype.render = function () {
213 RSTCell.prototype.render = function () {
214 if (this.rendered === false) {
214 if (this.rendered === false) {
215 var text = this.get_source();
215 var text = this.get_source();
216 if (text === "") {text = this.placeholder;};
216 if (text === "") {text = this.placeholder;};
217 var settings = {
217 var settings = {
218 processData : false,
218 processData : false,
219 cache : false,
219 cache : false,
220 type : "POST",
220 type : "POST",
221 data : text,
221 data : text,
222 headers : {'Content-Type': 'application/x-rst'},
222 headers : {'Content-Type': 'application/x-rst'},
223 success : $.proxy(this.handle_render,this)
223 success : $.proxy(this.handle_render,this)
224 };
224 };
225 $.ajax("/rstservice/render", settings);
225 $.ajax("/rstservice/render", settings);
226 this.element.find('div.text_cell_input').hide();
226 this.element.find('div.text_cell_input').hide();
227 this.element.find("div.text_cell_render").show();
227 this.element.find("div.text_cell_render").show();
228 this.set_rendered("Rendering...");
228 this.set_rendered("Rendering...");
229 };
229 };
230 };
230 };
231
231
232
232
233 RSTCell.prototype.handle_render = function (data, status, xhr) {
233 RSTCell.prototype.handle_render = function (data, status, xhr) {
234 this.set_rendered(data);
234 this.set_rendered(data);
235 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
235 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
236 this.rendered = true;
236 this.rendered = true;
237 };
237 };
238
238
239
239
240 IPython.TextCell = TextCell;
240 IPython.TextCell = TextCell;
241 IPython.HTMLCell = HTMLCell;
241 IPython.HTMLCell = HTMLCell;
242 IPython.MarkdownCell = MarkdownCell;
242 IPython.MarkdownCell = MarkdownCell;
243 IPython.RSTCell = RSTCell;
243 IPython.RSTCell = RSTCell;
244
244
245
245
246 return IPython;
246 return IPython;
247
247
248 }(IPython));
248 }(IPython));
249
249
@@ -1,195 +1,195 b''
1 import json
1 import json
2 from xml.etree import ElementTree as ET
2 from xml.etree import ElementTree as ET
3 import re
3 import re
4
4
5 from IPython.nbformat import v2
5 from IPython.nbformat import v2
6 from IPython.nbformat import v1
6 from IPython.nbformat import v1
7
7
8 from IPython.nbformat.v2 import (
8 from IPython.nbformat.v2 import (
9 NotebookNode,
9 NotebookNode,
10 new_code_cell, new_html_cell, new_notebook, new_output, new_worksheet
10 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet
11 )
11 )
12
12
13
13
14 current_nbformat = 2
14 current_nbformat = 2
15
15
16
16
17 class NBFormatError(Exception):
17 class NBFormatError(Exception):
18 pass
18 pass
19
19
20
20
21 def parse_json(s, **kwargs):
21 def parse_json(s, **kwargs):
22 """Parse a string into a (nbformat, dict) tuple."""
22 """Parse a string into a (nbformat, dict) tuple."""
23 d = json.loads(s, **kwargs)
23 d = json.loads(s, **kwargs)
24 nbformat = d.get('nbformat',1)
24 nbformat = d.get('nbformat',1)
25 return nbformat, d
25 return nbformat, d
26
26
27
27
28 def parse_xml(s, **kwargs):
28 def parse_xml(s, **kwargs):
29 """Parse a string into a (nbformat, etree) tuple."""
29 """Parse a string into a (nbformat, etree) tuple."""
30 root = ET.fromstring(s)
30 root = ET.fromstring(s)
31 nbformat_e = root.find('nbformat')
31 nbformat_e = root.find('nbformat')
32 if nbformat_e is not None:
32 if nbformat_e is not None:
33 nbformat = int(nbformat_e.text)
33 nbformat = int(nbformat_e.text)
34 else:
34 else:
35 raise NBFormatError('No nbformat version found')
35 raise NBFormatError('No nbformat version found')
36 return nbformat, root
36 return nbformat, root
37
37
38
38
39 def parse_py(s, **kwargs):
39 def parse_py(s, **kwargs):
40 """Parse a string into a (nbformat, string) tuple."""
40 """Parse a string into a (nbformat, string) tuple."""
41 pattern = r'# <nbformat>(?P<nbformat>\d+)</nbformat>'
41 pattern = r'# <nbformat>(?P<nbformat>\d+)</nbformat>'
42 m = re.search(pattern,s)
42 m = re.search(pattern,s)
43 if m is not None:
43 if m is not None:
44 nbformat = int(m.group('nbformat'))
44 nbformat = int(m.group('nbformat'))
45 else:
45 else:
46 nbformat = 2
46 nbformat = 2
47 return nbformat, s
47 return nbformat, s
48
48
49
49
50 def reads_json(s, **kwargs):
50 def reads_json(s, **kwargs):
51 """Read a JSON notebook from a string and return the NotebookNode object."""
51 """Read a JSON notebook from a string and return the NotebookNode object."""
52 nbformat, d = parse_json(s, **kwargs)
52 nbformat, d = parse_json(s, **kwargs)
53 if nbformat == 1:
53 if nbformat == 1:
54 nb = v1.to_notebook_json(d, **kwargs)
54 nb = v1.to_notebook_json(d, **kwargs)
55 nb = v2.convert_to_this_nbformat(nb, orig_version=1)
55 nb = v2.convert_to_this_nbformat(nb, orig_version=1)
56 elif nbformat == 2:
56 elif nbformat == 2:
57 nb = v2.to_notebook_json(d, **kwargs)
57 nb = v2.to_notebook_json(d, **kwargs)
58 else:
58 else:
59 raise NBFormatError('Unsupported JSON nbformat version: %i' % nbformat)
59 raise NBFormatError('Unsupported JSON nbformat version: %i' % nbformat)
60 return nb
60 return nb
61
61
62
62
63 def writes_json(nb, **kwargs):
63 def writes_json(nb, **kwargs):
64 return v2.writes_json(nb, **kwargs)
64 return v2.writes_json(nb, **kwargs)
65
65
66
66
67 def reads_xml(s, **kwargs):
67 def reads_xml(s, **kwargs):
68 """Read an XML notebook from a string and return the NotebookNode object."""
68 """Read an XML notebook from a string and return the NotebookNode object."""
69 nbformat, root = parse_xml(s, **kwargs)
69 nbformat, root = parse_xml(s, **kwargs)
70 if nbformat == 2:
70 if nbformat == 2:
71 nb = v2.to_notebook_xml(root, **kwargs)
71 nb = v2.to_notebook_xml(root, **kwargs)
72 else:
72 else:
73 raise NBFormatError('Unsupported XML nbformat version: %i' % nbformat)
73 raise NBFormatError('Unsupported XML nbformat version: %i' % nbformat)
74 return nb
74 return nb
75
75
76
76
77 def writes_xml(nb, **kwargs):
77 def writes_xml(nb, **kwargs):
78 return v2.writes_xml(nb, **kwargs)
78 return v2.writes_xml(nb, **kwargs)
79
79
80
80
81 def reads_py(s, **kwargs):
81 def reads_py(s, **kwargs):
82 """Read a .py notebook from a string and return the NotebookNode object."""
82 """Read a .py notebook from a string and return the NotebookNode object."""
83 nbformat, s = parse_py(s, **kwargs)
83 nbformat, s = parse_py(s, **kwargs)
84 if nbformat == 2:
84 if nbformat == 2:
85 nb = v2.to_notebook_py(s, **kwargs)
85 nb = v2.to_notebook_py(s, **kwargs)
86 else:
86 else:
87 raise NBFormatError('Unsupported PY nbformat version: %i' % nbformat)
87 raise NBFormatError('Unsupported PY nbformat version: %i' % nbformat)
88 return nb
88 return nb
89
89
90
90
91 def writes_py(nb, **kwargs):
91 def writes_py(nb, **kwargs):
92 return v2.writes_py(nb, **kwargs)
92 return v2.writes_py(nb, **kwargs)
93
93
94
94
95 # High level API
95 # High level API
96
96
97
97
98 def reads(s, format, **kwargs):
98 def reads(s, format, **kwargs):
99 """Read a notebook from a string and return the NotebookNode object.
99 """Read a notebook from a string and return the NotebookNode object.
100
100
101 This function properly handles notebooks of any version. The notebook
101 This function properly handles notebooks of any version. The notebook
102 returned will always be in the current version's format.
102 returned will always be in the current version's format.
103
103
104 Parameters
104 Parameters
105 ----------
105 ----------
106 s : str
106 s : str
107 The raw string to read the notebook from.
107 The raw string to read the notebook from.
108 format : ('xml','json','py')
108 format : ('xml','json','py')
109 The format that the string is in.
109 The format that the string is in.
110
110
111 Returns
111 Returns
112 -------
112 -------
113 nb : NotebookNode
113 nb : NotebookNode
114 The notebook that was read.
114 The notebook that was read.
115 """
115 """
116 if format == 'xml':
116 if format == 'xml':
117 return reads_xml(s, **kwargs)
117 return reads_xml(s, **kwargs)
118 elif format == 'json':
118 elif format == 'json':
119 return reads_json(s, **kwargs)
119 return reads_json(s, **kwargs)
120 elif format == 'py':
120 elif format == 'py':
121 return reads_py(s, **kwargs)
121 return reads_py(s, **kwargs)
122 else:
122 else:
123 raise NBFormatError('Unsupported format: %s' % format)
123 raise NBFormatError('Unsupported format: %s' % format)
124
124
125
125
126 def writes(nb, format, **kwargs):
126 def writes(nb, format, **kwargs):
127 """Write a notebook to a string in a given format in the current nbformat version.
127 """Write a notebook to a string in a given format in the current nbformat version.
128
128
129 This function always writes the notebook in the current nbformat version.
129 This function always writes the notebook in the current nbformat version.
130
130
131 Parameters
131 Parameters
132 ----------
132 ----------
133 nb : NotebookNode
133 nb : NotebookNode
134 The notebook to write.
134 The notebook to write.
135 format : ('xml','json','py')
135 format : ('xml','json','py')
136 The format to write the notebook in.
136 The format to write the notebook in.
137
137
138 Returns
138 Returns
139 -------
139 -------
140 s : str
140 s : str
141 The notebook string.
141 The notebook string.
142 """
142 """
143 if format == 'xml':
143 if format == 'xml':
144 return writes_xml(nb, **kwargs)
144 return writes_xml(nb, **kwargs)
145 elif format == 'json':
145 elif format == 'json':
146 return writes_json(nb, **kwargs)
146 return writes_json(nb, **kwargs)
147 elif format == 'py':
147 elif format == 'py':
148 return writes_py(nb, **kwargs)
148 return writes_py(nb, **kwargs)
149 else:
149 else:
150 raise NBFormatError('Unsupported format: %s' % format)
150 raise NBFormatError('Unsupported format: %s' % format)
151
151
152
152
153 def read(fp, format, **kwargs):
153 def read(fp, format, **kwargs):
154 """Read a notebook from a file and return the NotebookNode object.
154 """Read a notebook from a file and return the NotebookNode object.
155
155
156 This function properly handles notebooks of any version. The notebook
156 This function properly handles notebooks of any version. The notebook
157 returned will always be in the current version's format.
157 returned will always be in the current version's format.
158
158
159 Parameters
159 Parameters
160 ----------
160 ----------
161 fp : file
161 fp : file
162 Any file-like object with a read method.
162 Any file-like object with a read method.
163 format : ('xml','json','py')
163 format : ('xml','json','py')
164 The format that the string is in.
164 The format that the string is in.
165
165
166 Returns
166 Returns
167 -------
167 -------
168 nb : NotebookNode
168 nb : NotebookNode
169 The notebook that was read.
169 The notebook that was read.
170 """
170 """
171 return reads(fp.read(), format, **kwargs)
171 return reads(fp.read(), format, **kwargs)
172
172
173
173
174 def write(nb, fp, format, **kwargs):
174 def write(nb, fp, format, **kwargs):
175 """Write a notebook to a file in a given format in the current nbformat version.
175 """Write a notebook to a file in a given format in the current nbformat version.
176
176
177 This function always writes the notebook in the current nbformat version.
177 This function always writes the notebook in the current nbformat version.
178
178
179 Parameters
179 Parameters
180 ----------
180 ----------
181 nb : NotebookNode
181 nb : NotebookNode
182 The notebook to write.
182 The notebook to write.
183 fp : file
183 fp : file
184 Any file-like object with a write method.
184 Any file-like object with a write method.
185 format : ('xml','json','py')
185 format : ('xml','json','py')
186 The format to write the notebook in.
186 The format to write the notebook in.
187
187
188 Returns
188 Returns
189 -------
189 -------
190 s : str
190 s : str
191 The notebook string.
191 The notebook string.
192 """
192 """
193 return fp.write(writes(nb, format, **kwargs))
193 return fp.write(writes(nb, format, **kwargs))
194
194
195
195
@@ -1,21 +1,21 b''
1
1
2 from .nbbase import (
2 from .nbbase import (
3 NotebookNode,
3 NotebookNode,
4 new_code_cell, new_html_cell, new_notebook, new_output, new_worksheet
4 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet
5 )
5 )
6
6
7 from .nbjson import reads as reads_json, writes as writes_json
7 from .nbjson import reads as reads_json, writes as writes_json
8 from .nbjson import reads as read_json, writes as write_json
8 from .nbjson import reads as read_json, writes as write_json
9 from .nbjson import to_notebook as to_notebook_json
9 from .nbjson import to_notebook as to_notebook_json
10
10
11 from .nbxml import reads as reads_xml, writes as writes_xml
11 from .nbxml import reads as reads_xml, writes as writes_xml
12 from .nbxml import reads as read_xml, writes as write_xml
12 from .nbxml import reads as read_xml, writes as write_xml
13 from .nbxml import to_notebook as to_notebook_xml
13 from .nbxml import to_notebook as to_notebook_xml
14
14
15 from .nbpy import reads as reads_py, writes as writes_py
15 from .nbpy import reads as reads_py, writes as writes_py
16 from .nbpy import reads as read_py, writes as write_py
16 from .nbpy import reads as read_py, writes as write_py
17 from .nbpy import to_notebook as to_notebook_py
17 from .nbpy import to_notebook as to_notebook_py
18
18
19 from .convert import convert_to_this_nbformat
19 from .convert import convert_to_this_nbformat
20
20
21
21
@@ -1,20 +1,20 b''
1 from .nbbase import (
1 from .nbbase import (
2 new_code_cell, new_html_cell, new_worksheet, new_notebook, new_output
2 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
3 )
3 )
4
4
5 def convert_to_this_nbformat(nb, orig_version=1):
5 def convert_to_this_nbformat(nb, orig_version=1):
6 if orig_version == 1:
6 if orig_version == 1:
7 newnb = new_notebook()
7 newnb = new_notebook()
8 ws = new_worksheet()
8 ws = new_worksheet()
9 for cell in nb.cells:
9 for cell in nb.cells:
10 if cell.cell_type == 'code':
10 if cell.cell_type == u'code':
11 newcell = new_code_cell(input=cell.get('code'),prompt_number=cell.get('prompt_number'))
11 newcell = new_code_cell(input=cell.get('code'),prompt_number=cell.get('prompt_number'))
12 elif cell.cell_type == 'text':
12 elif cell.cell_type == u'text':
13 newcell = new_html_cell(source=cell.get('text'))
13 newcell = new_text_cell(u'markdown',source=cell.get('text'))
14 ws.cells.append(newcell)
14 ws.cells.append(newcell)
15 newnb.worksheets.append(ws)
15 newnb.worksheets.append(ws)
16 return newnb
16 return newnb
17 else:
17 else:
18 raise ValueError('Cannot convert a notebook from v%s to v2' % orig_version)
18 raise ValueError('Cannot convert a notebook from v%s to v2' % orig_version)
19
19
20
20
@@ -1,104 +1,106 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, prompt_number=None):
27 output_javascript=None, prompt_number=None):
28 """Create a new code cell with input and output"""
28 """Create a new code cell with input and output"""
29 output = NotebookNode()
29 output = NotebookNode()
30 if output_type is not None:
30 if output_type is not None:
31 output.output_type = unicode(output_type)
31 output.output_type = unicode(output_type)
32 if output_text is not None:
32 if output_text is not None:
33 output.text = unicode(output_text)
33 output.text = unicode(output_text)
34 if output_png is not None:
34 if output_png is not None:
35 output.png = bytes(output_png)
35 output.png = bytes(output_png)
36 if output_html is not None:
36 if output_html is not None:
37 output.html = unicode(output_html)
37 output.html = unicode(output_html)
38 if output_svg is not None:
38 if output_svg is not None:
39 output.svg = unicode(output_svg)
39 output.svg = unicode(output_svg)
40 if output_latex is not None:
40 if output_latex is not None:
41 output.latex = unicode(output_latex)
41 output.latex = unicode(output_latex)
42 if output_json is not None:
42 if output_json is not None:
43 output.json = unicode(output_json)
43 output.json = unicode(output_json)
44 if output_javascript is not None:
44 if output_javascript is not None:
45 output.javascript = unicode(output_javascript)
45 output.javascript = unicode(output_javascript)
46 if prompt_number is not None:
46 if prompt_number is not None:
47 output.prompt_number = int(prompt_number)
47 output.prompt_number = int(prompt_number)
48 return output
48 return output
49
49
50
50
51 def new_code_cell(input=None, prompt_number=None, outputs=None, language=u'python'):
51 def new_code_cell(input=None, prompt_number=None, outputs=None, language=u'python'):
52 """Create a new code cell with input and output"""
52 """Create a new code cell with input and output"""
53 cell = NotebookNode()
53 cell = NotebookNode()
54 cell.cell_type = u'code'
54 cell.cell_type = u'code'
55 if language is not None:
55 if language is not None:
56 cell.language = unicode(language)
56 cell.language = unicode(language)
57 if input is not None:
57 if input is not None:
58 cell.input = unicode(input)
58 cell.input = unicode(input)
59 if prompt_number is not None:
59 if prompt_number is not None:
60 cell.prompt_number = int(prompt_number)
60 cell.prompt_number = int(prompt_number)
61 if outputs is None:
61 if outputs is None:
62 cell.outputs = []
62 cell.outputs = []
63 else:
63 else:
64 cell.outputs = outputs
64 cell.outputs = outputs
65
65
66 return cell
66 return cell
67
67
68 def new_html_cell(source=None):
68 def new_text_cell(cell_type, source=None, rendered=None):
69 """Create a new text cell."""
69 """Create a new text cell."""
70 cell = NotebookNode()
70 cell = NotebookNode()
71 if source is not None:
71 if source is not None:
72 cell.source = unicode(source)
72 cell.source = unicode(source)
73 cell.cell_type = u'html'
73 if rendered is not None:
74 cell.rendered = unicode(rendered)
75 cell.cell_type = cell_type
74 return cell
76 return cell
75
77
76
78
77 def new_worksheet(name=None, cells=None):
79 def new_worksheet(name=None, cells=None):
78 """Create a worksheet by name with with a list of cells."""
80 """Create a worksheet by name with with a list of cells."""
79 ws = NotebookNode()
81 ws = NotebookNode()
80 if name is not None:
82 if name is not None:
81 ws.name = unicode(name)
83 ws.name = unicode(name)
82 if cells is None:
84 if cells is None:
83 ws.cells = []
85 ws.cells = []
84 else:
86 else:
85 ws.cells = list(cells)
87 ws.cells = list(cells)
86 return ws
88 return ws
87
89
88
90
89 def new_notebook(name=None, id=None, worksheets=None):
91 def new_notebook(name=None, id=None, worksheets=None):
90 """Create a notebook by name, id and a list of worksheets."""
92 """Create a notebook by name, id and a list of worksheets."""
91 nb = NotebookNode()
93 nb = NotebookNode()
92 nb.nbformat = 2
94 nb.nbformat = 2
93 if name is not None:
95 if name is not None:
94 nb.name = unicode(name)
96 nb.name = unicode(name)
95 if id is None:
97 if id is None:
96 nb.id = unicode(uuid.uuid4())
98 nb.id = unicode(uuid.uuid4())
97 else:
99 else:
98 nb.id = unicode(id)
100 nb.id = unicode(id)
99 if worksheets is None:
101 if worksheets is None:
100 nb.worksheets = []
102 nb.worksheets = []
101 else:
103 else:
102 nb.worksheets = list(worksheets)
104 nb.worksheets = list(worksheets)
103 return nb
105 return nb
104
106
@@ -1,168 +1,178 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_html_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_binary(e, tag):
55 def _get_binary(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 decodestring(sub_e.text)
60 return decodestring(sub_e.text)
61
61
62
62
63 def _set_binary(nbnode, attr, parent, tag):
63 def _set_binary(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 e.text = encodestring(nbnode[attr])
66 e.text = encodestring(nbnode[attr])
67
67
68
68
69 class XMLReader(NotebookReader):
69 class XMLReader(NotebookReader):
70
70
71 def reads(self, s, **kwargs):
71 def reads(self, s, **kwargs):
72 root = ET.fromstring(s)
72 root = ET.fromstring(s)
73 return self.to_notebook(root, **kwargs)
73 return self.to_notebook(root, **kwargs)
74
74
75 def to_notebook(self, root, **kwargs):
75 def to_notebook(self, root, **kwargs):
76 nbname = _get_text(root,'name')
76 nbname = _get_text(root,'name')
77 nbid = _get_text(root,'id')
77 nbid = _get_text(root,'id')
78
78
79 worksheets = []
79 worksheets = []
80 for ws_e in root.find('worksheets').getiterator('worksheet'):
80 for ws_e in root.find('worksheets').getiterator('worksheet'):
81 wsname = _get_text(ws_e,'name')
81 wsname = _get_text(ws_e,'name')
82 cells = []
82 cells = []
83 for cell_e in ws_e.find('cells').getiterator():
83 for cell_e in ws_e.find('cells').getiterator():
84 if cell_e.tag == 'codecell':
84 if cell_e.tag == 'codecell':
85 input = _get_text(cell_e,'input')
85 input = _get_text(cell_e,'input')
86 prompt_number = _get_int(cell_e,'prompt_number')
86 prompt_number = _get_int(cell_e,'prompt_number')
87 language = _get_text(cell_e,'language')
87 language = _get_text(cell_e,'language')
88 outputs = []
88 outputs = []
89 for output_e in cell_e.find('outputs').getiterator('output'):
89 for output_e in cell_e.find('outputs').getiterator('output'):
90 out_prompt_number = _get_int(output_e,'prompt_number')
90 out_prompt_number = _get_int(output_e,'prompt_number')
91 output_type = _get_text(output_e,'output_type')
91 output_type = _get_text(output_e,'output_type')
92 output_text = _get_text(output_e,'text')
92 output_text = _get_text(output_e,'text')
93 output_png = _get_binary(output_e,'png')
93 output_png = _get_binary(output_e,'png')
94 output_svg = _get_text(output_e,'svg')
94 output_svg = _get_text(output_e,'svg')
95 output_html = _get_text(output_e,'html')
95 output_html = _get_text(output_e,'html')
96 output_latex = _get_text(output_e,'latex')
96 output_latex = _get_text(output_e,'latex')
97 output_json = _get_text(output_e,'json')
97 output_json = _get_text(output_e,'json')
98 output_javascript = _get_text(output_e,'javascript')
98 output_javascript = _get_text(output_e,'javascript')
99 output = new_output(output_type=output_type,output_png=output_png,
99 output = new_output(output_type=output_type,output_png=output_png,
100 output_text=output_text,output_svg=output_svg,
100 output_text=output_text,output_svg=output_svg,
101 output_html=output_html,output_latex=output_latex,
101 output_html=output_html,output_latex=output_latex,
102 output_json=output_json,output_javascript=output_javascript,
102 output_json=output_json,output_javascript=output_javascript,
103 prompt_number=out_prompt_number
103 prompt_number=out_prompt_number
104 )
104 )
105 outputs.append(output)
105 outputs.append(output)
106 cc = new_code_cell(input=input,prompt_number=prompt_number,
106 cc = new_code_cell(input=input,prompt_number=prompt_number,
107 language=language,outputs=outputs)
107 language=language,outputs=outputs)
108 cells.append(cc)
108 cells.append(cc)
109 if cell_e.tag == 'htmlcell':
109 if cell_e.tag == 'htmlcell':
110 source = _get_text(cell_e,'source')
110 source = _get_text(cell_e,'source')
111 cells.append(new_html_cell(source=source))
111 rendered = _get_text(cell_e,'rendered')
112 cells.append(new_text_cell(u'html', source=source, rendered=rendered))
113 if cell_e.tag == 'markdowncell':
114 source = _get_text(cell_e,'source')
115 rendered = _get_text(cell_e,'rendered')
116 cells.append(new_text_cell(u'markdown', source=source, rendered=rendered))
112 ws = new_worksheet(name=wsname,cells=cells)
117 ws = new_worksheet(name=wsname,cells=cells)
113 worksheets.append(ws)
118 worksheets.append(ws)
114
119
115 nb = new_notebook(name=nbname,id=nbid,worksheets=worksheets)
120 nb = new_notebook(name=nbname,id=nbid,worksheets=worksheets)
116 return nb
121 return nb
117
122
118
123
119 class XMLWriter(NotebookWriter):
124 class XMLWriter(NotebookWriter):
120
125
121 def writes(self, nb, **kwargs):
126 def writes(self, nb, **kwargs):
122 nb_e = ET.Element('notebook')
127 nb_e = ET.Element('notebook')
123 _set_text(nb,'name',nb_e,'name')
128 _set_text(nb,'name',nb_e,'name')
124 _set_text(nb,'id',nb_e,'id')
129 _set_text(nb,'id',nb_e,'id')
125 _set_int(nb,'nbformat',nb_e,'nbformat')
130 _set_int(nb,'nbformat',nb_e,'nbformat')
126 wss_e = ET.SubElement(nb_e,'worksheets')
131 wss_e = ET.SubElement(nb_e,'worksheets')
127 for ws in nb.worksheets:
132 for ws in nb.worksheets:
128 ws_e = ET.SubElement(wss_e, 'worksheet')
133 ws_e = ET.SubElement(wss_e, 'worksheet')
129 _set_text(ws,'name',ws_e,'name')
134 _set_text(ws,'name',ws_e,'name')
130 cells_e = ET.SubElement(ws_e,'cells')
135 cells_e = ET.SubElement(ws_e,'cells')
131 for cell in ws.cells:
136 for cell in ws.cells:
132 cell_type = cell.cell_type
137 cell_type = cell.cell_type
133 if cell_type == 'code':
138 if cell_type == 'code':
134 cell_e = ET.SubElement(cells_e, 'codecell')
139 cell_e = ET.SubElement(cells_e, 'codecell')
135 _set_text(cell,'input',cell_e,'input')
140 _set_text(cell,'input',cell_e,'input')
136 _set_text(cell,'language',cell_e,'language')
141 _set_text(cell,'language',cell_e,'language')
137 _set_int(cell,'prompt_number',cell_e,'prompt_number')
142 _set_int(cell,'prompt_number',cell_e,'prompt_number')
138 outputs_e = ET.SubElement(cell_e, 'outputs')
143 outputs_e = ET.SubElement(cell_e, 'outputs')
139 for output in cell.outputs:
144 for output in cell.outputs:
140 output_e = ET.SubElement(outputs_e, 'output')
145 output_e = ET.SubElement(outputs_e, 'output')
141 _set_int(output,'prompt_number',output_e,'prompt_number')
146 _set_int(output,'prompt_number',output_e,'prompt_number')
142 _set_text(output,'output_type',output_e,'output_type')
147 _set_text(output,'output_type',output_e,'output_type')
143 _set_text(output,'text',output_e,'text')
148 _set_text(output,'text',output_e,'text')
144 _set_binary(output,'png',output_e,'png')
149 _set_binary(output,'png',output_e,'png')
145 _set_text(output,'html',output_e,'html')
150 _set_text(output,'html',output_e,'html')
146 _set_text(output,'svg',output_e,'svg')
151 _set_text(output,'svg',output_e,'svg')
147 _set_text(output,'latex',output_e,'latex')
152 _set_text(output,'latex',output_e,'latex')
148 _set_text(output,'json',output_e,'json')
153 _set_text(output,'json',output_e,'json')
149 _set_text(output,'javascript',output_e,'javascript')
154 _set_text(output,'javascript',output_e,'javascript')
150 elif cell_type == 'html':
155 elif cell_type == 'html':
151 cell_e = ET.SubElement(cells_e, 'htmlcell')
156 cell_e = ET.SubElement(cells_e, 'htmlcell')
152 _set_text(cell,'source',cell_e,'source')
157 _set_text(cell,'source',cell_e,'source')
158 _set_text(cell,'rendered',cell_e,'rendered')
159 elif cell_type == 'markdown':
160 cell_e = ET.SubElement(cells_e, 'markdowncell')
161 _set_text(cell,'source',cell_e,'source')
162 _set_text(cell,'rendered',cell_e,'rendered')
153
163
154 indent(nb_e)
164 indent(nb_e)
155 txt = ET.tostring(nb_e, encoding="utf-8")
165 txt = ET.tostring(nb_e, encoding="utf-8")
156 txt = '<?xml version="1.0" encoding="utf-8"?>\n' + txt
166 txt = '<?xml version="1.0" encoding="utf-8"?>\n' + txt
157 return txt
167 return txt
158
168
159
169
160 _reader = XMLReader()
170 _reader = XMLReader()
161 _writer = XMLWriter()
171 _writer = XMLWriter()
162
172
163 reads = _reader.reads
173 reads = _reader.reads
164 read = _reader.read
174 read = _reader.read
165 to_notebook = _reader.to_notebook
175 to_notebook = _reader.to_notebook
166 write = _writer.write
176 write = _writer.write
167 writes = _writer.writes
177 writes = _writer.writes
168
178
@@ -1,75 +1,83 b''
1 from ..nbbase import (
1 from ..nbbase import (
2 NotebookNode,
2 NotebookNode,
3 new_code_cell, new_html_cell, new_worksheet, new_notebook, new_output
3 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
4 )
4 )
5
5
6
6
7
7
8 ws = new_worksheet(name='worksheet1')
8 ws = new_worksheet(name='worksheet1')
9
9
10 ws.cells.append(new_html_cell(
10 ws.cells.append(new_text_cell(
11 source='Some NumPy Examples'
11 u'html',
12 source='Some NumPy Examples',
13 rendered='Some NumPy Examples'
12 ))
14 ))
13
15
14
16
15 ws.cells.append(new_code_cell(
17 ws.cells.append(new_code_cell(
16 input='import numpy',
18 input='import numpy',
17 prompt_number=1
19 prompt_number=1
18 ))
20 ))
19
21
22 ws.cells.append(new_text_cell(
23 u'markdown',
24 source='Some NumPy Examples',
25 rendered='Some NumPy Examples'
26 ))
27
20 ws.cells.append(new_code_cell(
28 ws.cells.append(new_code_cell(
21 input='a = numpy.random.rand(100)',
29 input='a = numpy.random.rand(100)',
22 prompt_number=2
30 prompt_number=2
23 ))
31 ))
24
32
25 ws.cells.append(new_code_cell(
33 ws.cells.append(new_code_cell(
26 input='print a',
34 input='print a',
27 prompt_number=3,
35 prompt_number=3,
28 outputs=[new_output(
36 outputs=[new_output(
29 output_type=u'pyout',
37 output_type=u'pyout',
30 output_text=u'<array a>',
38 output_text=u'<array a>',
31 output_html=u'The HTML rep',
39 output_html=u'The HTML rep',
32 output_latex=u'$a$',
40 output_latex=u'$a$',
33 output_png=b'data',
41 output_png=b'data',
34 output_svg=u'<svg>',
42 output_svg=u'<svg>',
35 output_json=u'json data',
43 output_json=u'json data',
36 output_javascript=u'var i=0;',
44 output_javascript=u'var i=0;',
37 prompt_number=3
45 prompt_number=3
38 ),new_output(
46 ),new_output(
39 output_type=u'display_data',
47 output_type=u'display_data',
40 output_text=u'<array a>',
48 output_text=u'<array a>',
41 output_html=u'The HTML rep',
49 output_html=u'The HTML rep',
42 output_latex=u'$a$',
50 output_latex=u'$a$',
43 output_png=b'data',
51 output_png=b'data',
44 output_svg=u'<svg>',
52 output_svg=u'<svg>',
45 output_json=u'json data',
53 output_json=u'json data',
46 output_javascript=u'var i=0;',
54 output_javascript=u'var i=0;',
47 prompt_number=4
55 prompt_number=4
48 )]
56 )]
49 ))
57 ))
50
58
51 nb0 = new_notebook(
59 nb0 = new_notebook(
52 name='nb0',
60 name='nb0',
53 worksheets=[ws, new_worksheet(name='worksheet2')]
61 worksheets=[ws, new_worksheet(name='worksheet2')]
54 )
62 )
55
63
56 nb0_py = """# <nbformat>2</nbformat>
64 nb0_py = """# <nbformat>2</nbformat>
57
65
58 # <codecell>
66 # <codecell>
59
67
60 import numpy
68 import numpy
61
69
62 # </codecell>
70 # </codecell>
63 # <codecell>
71 # <codecell>
64
72
65 a = numpy.random.rand(100)
73 a = numpy.random.rand(100)
66
74
67 # </codecell>
75 # </codecell>
68 # <codecell>
76 # <codecell>
69
77
70 print a
78 print a
71
79
72 # </codecell>
80 # </codecell>
73 """
81 """
74
82
75
83
@@ -1,66 +1,79 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_html_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
16
17 def test_code_cell(self):
17 def test_code_cell(self):
18 cc = new_code_cell(input='a=10', prompt_number=0)
18 cc = new_code_cell(input='a=10', prompt_number=0)
19 cc.outputs = [new_output(output_type='pyout',
19 cc.outputs = [new_output(output_type='pyout',
20 output_svg='foo',output_text='10',prompt_number=0)]
20 output_svg='foo',output_text='10',prompt_number=0)]
21 self.assertEquals(cc.input, u'a=10')
21 self.assertEquals(cc.input, u'a=10')
22 self.assertEquals(cc.prompt_number, 0)
22 self.assertEquals(cc.prompt_number, 0)
23 self.assertEquals(cc.language, u'python')
23 self.assertEquals(cc.language, u'python')
24 self.assertEquals(cc.outputs[0].svg, u'foo')
24 self.assertEquals(cc.outputs[0].svg, u'foo')
25 self.assertEquals(cc.outputs[0].text, u'10')
25 self.assertEquals(cc.outputs[0].text, u'10')
26 self.assertEquals(cc.outputs[0].prompt_number, 0)
26 self.assertEquals(cc.outputs[0].prompt_number, 0)
27
27
28 def test_empty_html_cell(self):
28 def test_empty_html_cell(self):
29 tc = new_html_cell()
29 tc = new_text_cell(u'html')
30 self.assertEquals(tc.cell_type, 'html')
30 self.assertEquals(tc.cell_type, u'html')
31 self.assertEquals('source' not in tc, True)
31 self.assertEquals('source' not in tc, True)
32 self.assertEquals('rendered' not in tc, True)
32
33
33 def test_html_cell(self):
34 def test_html_cell(self):
34 tc = new_html_cell('hi')
35 tc = new_text_cell(u'html', 'hi', 'hi')
35 self.assertEquals(tc.source, u'hi')
36 self.assertEquals(tc.source, u'hi')
37 self.assertEquals(tc.rendered, u'hi')
38
39 def test_empty_markdown_cell(self):
40 tc = new_text_cell(u'markdown')
41 self.assertEquals(tc.cell_type, u'markdown')
42 self.assertEquals('source' not in tc, True)
43 self.assertEquals('rendered' not in tc, True)
44
45 def test_markdown_cell(self):
46 tc = new_text_cell(u'markdown', 'hi', 'hi')
47 self.assertEquals(tc.source, u'hi')
48 self.assertEquals(tc.rendered, u'hi')
36
49
37
50
38 class TestWorksheet(TestCase):
51 class TestWorksheet(TestCase):
39
52
40 def test_empty_worksheet(self):
53 def test_empty_worksheet(self):
41 ws = new_worksheet()
54 ws = new_worksheet()
42 self.assertEquals(ws.cells,[])
55 self.assertEquals(ws.cells,[])
43 self.assertEquals('name' not in ws, True)
56 self.assertEquals('name' not in ws, True)
44
57
45 def test_worksheet(self):
58 def test_worksheet(self):
46 cells = [new_code_cell(), new_html_cell()]
59 cells = [new_code_cell(), new_text_cell(u'html')]
47 ws = new_worksheet(cells=cells,name='foo')
60 ws = new_worksheet(cells=cells,name='foo')
48 self.assertEquals(ws.cells,cells)
61 self.assertEquals(ws.cells,cells)
49 self.assertEquals(ws.name,u'foo')
62 self.assertEquals(ws.name,u'foo')
50
63
51 class TestNotebook(TestCase):
64 class TestNotebook(TestCase):
52
65
53 def test_empty_notebook(self):
66 def test_empty_notebook(self):
54 nb = new_notebook()
67 nb = new_notebook()
55 self.assertEquals('id' in nb, True)
68 self.assertEquals('id' in nb, True)
56 self.assertEquals(nb.worksheets, [])
69 self.assertEquals(nb.worksheets, [])
57 self.assertEquals('name' not in nb, True)
70 self.assertEquals('name' not in nb, True)
58 self.assertEquals(nb.nbformat,2)
71 self.assertEquals(nb.nbformat,2)
59
72
60 def test_notebook(self):
73 def test_notebook(self):
61 worksheets = [new_worksheet(),new_worksheet()]
74 worksheets = [new_worksheet(),new_worksheet()]
62 nb = new_notebook(name='foo',worksheets=worksheets)
75 nb = new_notebook(name='foo',worksheets=worksheets)
63 self.assertEquals(nb.name,u'foo')
76 self.assertEquals(nb.name,u'foo')
64 self.assertEquals(nb.worksheets,worksheets)
77 self.assertEquals(nb.worksheets,worksheets)
65 self.assertEquals(nb.nbformat,2)
78 self.assertEquals(nb.nbformat,2)
66
79
@@ -1,17 +1,17 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_html_cell, new_worksheet, new_notebook
5 new_code_cell, new_text_cell, new_worksheet, new_notebook
6 )
6 )
7
7
8 from ..nbpy import reads, writes
8 from ..nbpy import reads, writes
9 from .nbexamples import nb0, nb0_py
9 from .nbexamples import nb0, nb0_py
10
10
11
11
12 class TestPy(TestCase):
12 class TestPy(TestCase):
13
13
14 def test_write(self):
14 def test_write(self):
15 s = writes(nb0)
15 s = writes(nb0)
16 self.assertEquals(s,nb0_py)
16 self.assertEquals(s,nb0_py)
17
17
General Comments 0
You need to be logged in to leave comments. Login now