##// END OF EJS Templates
Merge pull request #1934 from minrk/cellmd...
Fernando Perez -
r7612:ca7d2a9c merge
parent child Browse files
Show More
@@ -19,6 +19,7 b' var IPython = (function (IPython) {'
19 this.read_only = false;
19 this.read_only = false;
20 this.selected = false;
20 this.selected = false;
21 this.element = null;
21 this.element = null;
22 this.metadata = {};
22 this.create_element();
23 this.create_element();
23 if (this.element !== null) {
24 if (this.element !== null) {
24 this.element.data("cell", this);
25 this.element.data("cell", this);
@@ -90,10 +91,16 b' var IPython = (function (IPython) {'
90
91
91
92
92 Cell.prototype.toJSON = function () {
93 Cell.prototype.toJSON = function () {
94 var data = {};
95 data.metadata = this.metadata;
96 return data;
93 };
97 };
94
98
95
99
96 Cell.prototype.fromJSON = function (data) {
100 Cell.prototype.fromJSON = function (data) {
101 if (data.metadata !== undefined) {
102 this.metadata = data.metadata;
103 }
97 };
104 };
98
105
99
106
@@ -22,6 +22,7 b' var IPython = (function (IPython) {'
22 this.code_mirror = null;
22 this.code_mirror = null;
23 this.input_prompt_number = null;
23 this.input_prompt_number = null;
24 this.tooltip_on_tab = true;
24 this.tooltip_on_tab = true;
25 this.collapsed = false;
25 IPython.Cell.apply(this, arguments);
26 IPython.Cell.apply(this, arguments);
26 };
27 };
27
28
@@ -200,17 +201,20 b' var IPython = (function (IPython) {'
200
201
201
202
202 CodeCell.prototype.collapse = function () {
203 CodeCell.prototype.collapse = function () {
203 this.output_area.collapse();
204 this.collapsed = true;
205 this.output_area.collapse();
204 };
206 };
205
207
206
208
207 CodeCell.prototype.expand = function () {
209 CodeCell.prototype.expand = function () {
208 this.output_area.expand();
210 this.collapsed = false;
211 this.output_area.expand();
209 };
212 };
210
213
211
214
212 CodeCell.prototype.toggle_output = function () {
215 CodeCell.prototype.toggle_output = function () {
213 this.output_area.toggle_output();
216 this.collapsed = Boolean(1 - this.collapsed);
217 this.output_area.toggle_output();
214 };
218 };
215
219
216
220
@@ -264,6 +268,7 b' var IPython = (function (IPython) {'
264 // JSON serialization
268 // JSON serialization
265
269
266 CodeCell.prototype.fromJSON = function (data) {
270 CodeCell.prototype.fromJSON = function (data) {
271 IPython.Cell.prototype.fromJSON.apply(this, arguments);
267 if (data.cell_type === 'code') {
272 if (data.cell_type === 'code') {
268 if (data.input !== undefined) {
273 if (data.input !== undefined) {
269 this.set_text(data.input);
274 this.set_text(data.input);
@@ -289,7 +294,7 b' var IPython = (function (IPython) {'
289
294
290
295
291 CodeCell.prototype.toJSON = function () {
296 CodeCell.prototype.toJSON = function () {
292 var data = {};
297 var data = IPython.Cell.prototype.toJSON.apply(this);
293 data.input = this.get_text();
298 data.input = this.get_text();
294 data.cell_type = 'code';
299 data.cell_type = 'code';
295 if (this.input_prompt_number) {
300 if (this.input_prompt_number) {
@@ -25,11 +25,14 b' var IPython = (function (IPython) {'
25 this.paste_enabled = false;
25 this.paste_enabled = false;
26 this.dirty = false;
26 this.dirty = false;
27 this.metadata = {};
27 this.metadata = {};
28 // single worksheet for now
29 this.worksheet_metadata = {};
28 this.control_key_active = false;
30 this.control_key_active = false;
29 this.notebook_id = null;
31 this.notebook_id = null;
30 this.notebook_name = null;
32 this.notebook_name = null;
31 this.notebook_name_blacklist_re = /[\/\\:]/;
33 this.notebook_name_blacklist_re = /[\/\\:]/;
32 this.nbformat = 3 // Increment this when changing the nbformat
34 this.nbformat = 3 // Increment this when changing the nbformat
35 this.nbformat_minor = 0 // Increment this when changing the nbformat
33 this.style();
36 this.style();
34 this.create_elements();
37 this.create_elements();
35 this.bind_events();
38 this.bind_events();
@@ -1018,6 +1021,9 b' var IPython = (function (IPython) {'
1018 // Only handle 1 worksheet for now.
1021 // Only handle 1 worksheet for now.
1019 var worksheet = data.worksheets[0];
1022 var worksheet = data.worksheets[0];
1020 if (worksheet !== undefined) {
1023 if (worksheet !== undefined) {
1024 if (worksheet.metadata) {
1025 this.worksheet_metadata = worksheet.metadata;
1026 }
1021 var new_cells = worksheet.cells;
1027 var new_cells = worksheet.cells;
1022 ncells = new_cells.length;
1028 ncells = new_cells.length;
1023 var cell_data = null;
1029 var cell_data = null;
@@ -1034,6 +1040,27 b' var IPython = (function (IPython) {'
1034 new_cell.fromJSON(cell_data);
1040 new_cell.fromJSON(cell_data);
1035 };
1041 };
1036 };
1042 };
1043 if (data.worksheets.length > 1) {
1044 var dialog = $('<div/>');
1045 dialog.html("This notebook has " + data.worksheets.length + " worksheets, " +
1046 "but this version of IPython can only handle the first. " +
1047 "If you save this notebook, worksheets after the first will be lost."
1048 );
1049 this.element.append(dialog);
1050 dialog.dialog({
1051 resizable: false,
1052 modal: true,
1053 title: "Multiple worksheets",
1054 closeText: "",
1055 close: function(event, ui) {$(this).dialog('destroy').remove();},
1056 buttons : {
1057 "OK": function () {
1058 $(this).dialog('close');
1059 }
1060 },
1061 width: 400
1062 });
1063 }
1037 };
1064 };
1038
1065
1039
1066
@@ -1046,7 +1073,10 b' var IPython = (function (IPython) {'
1046 };
1073 };
1047 var data = {
1074 var data = {
1048 // Only handle 1 worksheet for now.
1075 // Only handle 1 worksheet for now.
1049 worksheets : [{cells:cell_array}],
1076 worksheets : [{
1077 cells: cell_array,
1078 metadata: this.worksheet_metadata
1079 }],
1050 metadata : this.metadata
1080 metadata : this.metadata
1051 };
1081 };
1052 return data;
1082 return data;
@@ -1057,6 +1087,7 b' var IPython = (function (IPython) {'
1057 var data = this.toJSON();
1087 var data = this.toJSON();
1058 data.metadata.name = this.notebook_name;
1088 data.metadata.name = this.notebook_name;
1059 data.nbformat = this.nbformat;
1089 data.nbformat = this.nbformat;
1090 data.nbformat_minor = this.nbformat_minor;
1060 // We do the call with settings so we can set cache to false.
1091 // We do the call with settings so we can set cache to false.
1061 var settings = {
1092 var settings = {
1062 processData : false,
1093 processData : false,
@@ -1133,6 +1164,31 b' var IPython = (function (IPython) {'
1133 },
1164 },
1134 width: 400
1165 width: 400
1135 });
1166 });
1167 } else if (data.orig_nbformat_minor !== undefined && data.nbformat_minor !== data.orig_nbformat_minor) {
1168 var that = this;
1169 var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor;
1170 var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor;
1171 msg = "This notebook is version " + orig_vs + ", but we only fully support up to " +
1172 this_vs + ". You can still work with this notebook, but some features " +
1173 "introduced in later notebook versions may not be available."
1174
1175 var dialog = $('<div/>');
1176 dialog.html(msg);
1177 this.element.append(dialog);
1178 dialog.dialog({
1179 resizable: false,
1180 modal: true,
1181 title: "Newer Notebook",
1182 closeText: "",
1183 close: function(event, ui) {$(this).dialog('destroy').remove();},
1184 buttons : {
1185 "OK": function () {
1186 $(this).dialog('close');
1187 }
1188 },
1189 width: 400
1190 });
1191
1136 }
1192 }
1137 // Create the kernel after the notebook is completely loaded to prevent
1193 // Create the kernel after the notebook is completely loaded to prevent
1138 // code execution upon loading, which is a security risk.
1194 // code execution upon loading, which is a security risk.
@@ -155,6 +155,7 b' var IPython = (function (IPython) {'
155
155
156
156
157 TextCell.prototype.fromJSON = function (data) {
157 TextCell.prototype.fromJSON = function (data) {
158 IPython.Cell.prototype.fromJSON.apply(this, arguments);
158 if (data.cell_type === this.cell_type) {
159 if (data.cell_type === this.cell_type) {
159 if (data.source !== undefined) {
160 if (data.source !== undefined) {
160 this.set_text(data.source);
161 this.set_text(data.source);
@@ -170,7 +171,7 b' var IPython = (function (IPython) {'
170
171
171
172
172 TextCell.prototype.toJSON = function () {
173 TextCell.prototype.toJSON = function () {
173 var data = {};
174 var data = IPython.Cell.prototype.toJSON.apply(this);
174 data.cell_type = this.cell_type;
175 data.cell_type = this.cell_type;
175 data.source = this.get_text();
176 data.source = this.get_text();
176 return data;
177 return data;
@@ -28,7 +28,8 b' from IPython.nbformat import v1'
28 from IPython.nbformat.v3 import (
28 from IPython.nbformat.v3 import (
29 NotebookNode,
29 NotebookNode,
30 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
30 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
31 parse_filename, new_metadata, new_author, new_heading_cell, nbformat
31 parse_filename, new_metadata, new_author, new_heading_cell, nbformat,
32 nbformat_minor,
32 )
33 )
33
34
34 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
@@ -36,6 +37,8 b' from IPython.nbformat.v3 import ('
36 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
37
38
38 current_nbformat = nbformat
39 current_nbformat = nbformat
40 current_nbformat_minor = nbformat_minor
41
39
42
40
43
41 class NBFormatError(Exception):
44 class NBFormatError(Exception):
@@ -45,24 +48,30 b' class NBFormatError(Exception):'
45 def parse_json(s, **kwargs):
48 def parse_json(s, **kwargs):
46 """Parse a string into a (nbformat, dict) tuple."""
49 """Parse a string into a (nbformat, dict) tuple."""
47 d = json.loads(s, **kwargs)
50 d = json.loads(s, **kwargs)
48 nbf = d.get('nbformat',1)
51 nbf = d.get('nbformat', 1)
49 return nbf, d
52 nbm = d.get('nbformat_minor', 0)
53 return nbf, nbm, d
50
54
51
55
52 def parse_py(s, **kwargs):
56 def parse_py(s, **kwargs):
53 """Parse a string into a (nbformat, string) tuple."""
57 """Parse a string into a (nbformat, string) tuple."""
54 pattern = r'# <nbformat>(?P<nbformat>\d+)</nbformat>'
58 nbf = current_nbformat
59 nbm = current_nbformat_minor
60
61 pattern = r'# <nbformat>(?P<nbformat>\d+[\.\d+]*)</nbformat>'
55 m = re.search(pattern,s)
62 m = re.search(pattern,s)
56 if m is not None:
63 if m is not None:
57 nbf = int(m.group('nbformat'))
64 digits = m.group('nbformat').split('.')
58 else:
65 nbf = int(digits[0])
59 nbf = current_nbformat
66 if len(digits) > 1:
60 return nbf, s
67 nbm = int(digits[1])
68
69 return nbf, nbm, s
61
70
62
71
63 def reads_json(s, **kwargs):
72 def reads_json(s, **kwargs):
64 """Read a JSON notebook from a string and return the NotebookNode object."""
73 """Read a JSON notebook from a string and return the NotebookNode object."""
65 nbf, d = parse_json(s, **kwargs)
74 nbf, minor, d = parse_json(s, **kwargs)
66 if nbf == 1:
75 if nbf == 1:
67 nb = v1.to_notebook_json(d, **kwargs)
76 nb = v1.to_notebook_json(d, **kwargs)
68 nb = v3.convert_to_this_nbformat(nb, orig_version=1)
77 nb = v3.convert_to_this_nbformat(nb, orig_version=1)
@@ -71,6 +80,7 b' def reads_json(s, **kwargs):'
71 nb = v3.convert_to_this_nbformat(nb, orig_version=2)
80 nb = v3.convert_to_this_nbformat(nb, orig_version=2)
72 elif nbf == 3:
81 elif nbf == 3:
73 nb = v3.to_notebook_json(d, **kwargs)
82 nb = v3.to_notebook_json(d, **kwargs)
83 nb = v3.convert_to_this_nbformat(nb, orig_version=3, orig_minor=minor)
74 else:
84 else:
75 raise NBFormatError('Unsupported JSON nbformat version: %i' % nbf)
85 raise NBFormatError('Unsupported JSON nbformat version: %i' % nbf)
76 return nb
86 return nb
@@ -82,7 +92,7 b' def writes_json(nb, **kwargs):'
82
92
83 def reads_py(s, **kwargs):
93 def reads_py(s, **kwargs):
84 """Read a .py notebook from a string and return the NotebookNode object."""
94 """Read a .py notebook from a string and return the NotebookNode object."""
85 nbf, s = parse_py(s, **kwargs)
95 nbf, nbm, s = parse_py(s, **kwargs)
86 if nbf == 2:
96 if nbf == 2:
87 nb = v2.to_notebook_py(s, **kwargs)
97 nb = v2.to_notebook_py(s, **kwargs)
88 elif nbf == 3:
98 elif nbf == 3:
@@ -19,7 +19,7 b' Authors:'
19 from .nbbase import (
19 from .nbbase import (
20 NotebookNode,
20 NotebookNode,
21 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
21 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
22 new_metadata, new_author, new_heading_cell, nbformat
22 new_metadata, new_author, new_heading_cell, nbformat, nbformat_minor
23 )
23 )
24
24
25 from .nbjson import reads as reads_json, writes as writes_json
25 from .nbjson import reads as reads_json, writes as writes_json
@@ -17,7 +17,8 b' Authors:'
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 from .nbbase import (
19 from .nbbase import (
20 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
20 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
21 nbformat, nbformat_minor
21 )
22 )
22
23
23 from IPython.nbformat import v2
24 from IPython.nbformat import v2
@@ -26,7 +27,7 b' from IPython.nbformat import v2'
26 # Code
27 # Code
27 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
28
29
29 def convert_to_this_nbformat(nb, orig_version=2):
30 def convert_to_this_nbformat(nb, orig_version=2, orig_minor=0):
30 """Convert a notebook to the v3 format.
31 """Convert a notebook to the v3 format.
31
32
32 Parameters
33 Parameters
@@ -35,16 +36,23 b' def convert_to_this_nbformat(nb, orig_version=2):'
35 The Python representation of the notebook to convert.
36 The Python representation of the notebook to convert.
36 orig_version : int
37 orig_version : int
37 The original version of the notebook to convert.
38 The original version of the notebook to convert.
39 orig_minor : int
40 The original minor version of the notebook to convert (only relevant for v >= 3).
38 """
41 """
39 if orig_version == 1:
42 if orig_version == 1:
40 nb = v2.convert_to_this_nbformat(nb)
43 nb = v2.convert_to_this_nbformat(nb)
41 orig_version = 2
44 orig_version = 2
42 if orig_version == 2:
45 if orig_version == 2:
43 # Mark the original nbformat so consumers know it has been converted.
46 # Mark the original nbformat so consumers know it has been converted.
44 nb.nbformat = 3
47 nb.nbformat = nbformat
48 nb.nbformat_minor = nbformat_minor
49
45 nb.orig_nbformat = 2
50 nb.orig_nbformat = 2
46 return nb
51 return nb
47 elif orig_version == 3:
52 elif orig_version == 3:
53 if orig_minor != nbformat_minor:
54 nb.orig_nbformat_minor = orig_minor
55 nb.nbformat_minor = nbformat_minor
48 return nb
56 return nb
49 else:
57 else:
50 raise ValueError('Cannot convert a notebook from v%s to v3' % orig_version)
58 raise ValueError('Cannot convert a notebook from v%s to v3' % orig_version)
@@ -32,6 +32,7 b' from IPython.utils.ipstruct import Struct'
32
32
33 # Change this when incrementing the nbformat version
33 # Change this when incrementing the nbformat version
34 nbformat = 3
34 nbformat = 3
35 nbformat_minor = 0
35
36
36 class NotebookNode(Struct):
37 class NotebookNode(Struct):
37 pass
38 pass
@@ -92,7 +93,7 b' def new_output(output_type=None, output_text=None, output_png=None,'
92
93
93
94
94 def new_code_cell(input=None, prompt_number=None, outputs=None,
95 def new_code_cell(input=None, prompt_number=None, outputs=None,
95 language=u'python', collapsed=False):
96 language=u'python', collapsed=False, metadata=None):
96 """Create a new code cell with input and output"""
97 """Create a new code cell with input and output"""
97 cell = NotebookNode()
98 cell = NotebookNode()
98 cell.cell_type = u'code'
99 cell.cell_type = u'code'
@@ -108,10 +109,11 b' def new_code_cell(input=None, prompt_number=None, outputs=None,'
108 cell.outputs = outputs
109 cell.outputs = outputs
109 if collapsed is not None:
110 if collapsed is not None:
110 cell.collapsed = bool(collapsed)
111 cell.collapsed = bool(collapsed)
112 cell.metadata = NotebookNode(metadata or {})
111
113
112 return cell
114 return cell
113
115
114 def new_text_cell(cell_type, source=None, rendered=None):
116 def new_text_cell(cell_type, source=None, rendered=None, metadata=None):
115 """Create a new text cell."""
117 """Create a new text cell."""
116 cell = NotebookNode()
118 cell = NotebookNode()
117 # VERSIONHACK: plaintext -> raw
119 # VERSIONHACK: plaintext -> raw
@@ -122,11 +124,12 b' def new_text_cell(cell_type, source=None, rendered=None):'
122 cell.source = unicode(source)
124 cell.source = unicode(source)
123 if rendered is not None:
125 if rendered is not None:
124 cell.rendered = unicode(rendered)
126 cell.rendered = unicode(rendered)
127 cell.metadata = NotebookNode(metadata or {})
125 cell.cell_type = cell_type
128 cell.cell_type = cell_type
126 return cell
129 return cell
127
130
128
131
129 def new_heading_cell(source=None, rendered=None, level=1):
132 def new_heading_cell(source=None, rendered=None, level=1, metadata=None):
130 """Create a new section cell with a given integer level."""
133 """Create a new section cell with a given integer level."""
131 cell = NotebookNode()
134 cell = NotebookNode()
132 cell.cell_type = u'heading'
135 cell.cell_type = u'heading'
@@ -135,10 +138,11 b' def new_heading_cell(source=None, rendered=None, level=1):'
135 if rendered is not None:
138 if rendered is not None:
136 cell.rendered = unicode(rendered)
139 cell.rendered = unicode(rendered)
137 cell.level = int(level)
140 cell.level = int(level)
141 cell.metadata = NotebookNode(metadata or {})
138 return cell
142 return cell
139
143
140
144
141 def new_worksheet(name=None, cells=None):
145 def new_worksheet(name=None, cells=None, metadata=None):
142 """Create a worksheet by name with with a list of cells."""
146 """Create a worksheet by name with with a list of cells."""
143 ws = NotebookNode()
147 ws = NotebookNode()
144 if name is not None:
148 if name is not None:
@@ -147,6 +151,7 b' def new_worksheet(name=None, cells=None):'
147 ws.cells = []
151 ws.cells = []
148 else:
152 else:
149 ws.cells = list(cells)
153 ws.cells = list(cells)
154 ws.metadata = NotebookNode(metadata or {})
150 return ws
155 return ws
151
156
152
157
@@ -154,6 +159,7 b' def new_notebook(name=None, metadata=None, worksheets=None):'
154 """Create a notebook by name, id and a list of worksheets."""
159 """Create a notebook by name, id and a list of worksheets."""
155 nb = NotebookNode()
160 nb = NotebookNode()
156 nb.nbformat = nbformat
161 nb.nbformat = nbformat
162 nb.nbformat_minor = nbformat_minor
157 if worksheets is None:
163 if worksheets is None:
158 nb.worksheets = []
164 nb.worksheets = []
159 else:
165 else:
@@ -20,7 +20,7 b' import re'
20 from .rwbase import NotebookReader, NotebookWriter
20 from .rwbase import NotebookReader, NotebookWriter
21 from .nbbase import (
21 from .nbbase import (
22 new_code_cell, new_text_cell, new_worksheet,
22 new_code_cell, new_text_cell, new_worksheet,
23 new_notebook, new_heading_cell, nbformat
23 new_notebook, new_heading_cell, nbformat, nbformat_minor,
24 )
24 )
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
@@ -152,7 +152,10 b' class PyWriter(NotebookWriter):'
152
152
153 def writes(self, nb, **kwargs):
153 def writes(self, nb, **kwargs):
154 lines = [u'# -*- coding: utf-8 -*-']
154 lines = [u'# -*- coding: utf-8 -*-']
155 lines.extend([u'# <nbformat>%i</nbformat>' % nbformat,''])
155 lines.extend([
156 u'# <nbformat>%i.%i</nbformat>' % (nbformat, nbformat_minor),
157 u'',
158 ])
156 for ws in nb.worksheets:
159 for ws in nb.worksheets:
157 for cell in ws.cells:
160 for cell in ws.cells:
158 if cell.cell_type == u'code':
161 if cell.cell_type == u'code':
@@ -6,7 +6,7 b' from base64 import encodestring'
6 from ..nbbase import (
6 from ..nbbase import (
7 NotebookNode,
7 NotebookNode,
8 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
8 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
9 new_metadata, new_author, new_heading_cell, nbformat
9 new_metadata, new_author, new_heading_cell, nbformat, nbformat_minor
10 )
10 )
11
11
12 # some random base64-encoded *bytes*
12 # some random base64-encoded *bytes*
@@ -108,7 +108,7 b' nb0 = new_notebook('
108 )
108 )
109
109
110 nb0_py = u"""# -*- coding: utf-8 -*-
110 nb0_py = u"""# -*- coding: utf-8 -*-
111 # <nbformat>%i</nbformat>
111 # <nbformat>%i.%i</nbformat>
112
112
113 # <htmlcell>
113 # <htmlcell>
114
114
@@ -148,6 +148,6 b' b = 5'
148
148
149 print "ünîcødé"
149 print "ünîcødé"
150
150
151 """ % nbformat
151 """ % (nbformat, nbformat_minor)
152
152
153
153
General Comments 0
You need to be logged in to leave comments. Login now