Show More
@@ -19,6 +19,7 b' var IPython = (function (IPython) {' | |||
|
19 | 19 | this.read_only = false; |
|
20 | 20 | this.selected = false; |
|
21 | 21 | this.element = null; |
|
22 | this.metadata = {}; | |
|
22 | 23 | this.create_element(); |
|
23 | 24 | if (this.element !== null) { |
|
24 | 25 | this.element.data("cell", this); |
@@ -90,10 +91,16 b' var IPython = (function (IPython) {' | |||
|
90 | 91 | |
|
91 | 92 | |
|
92 | 93 | Cell.prototype.toJSON = function () { |
|
94 | var data = {}; | |
|
95 | data.metadata = this.metadata; | |
|
96 | return data; | |
|
93 | 97 | }; |
|
94 | 98 | |
|
95 | 99 | |
|
96 | 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 | 22 | this.code_mirror = null; |
|
23 | 23 | this.input_prompt_number = null; |
|
24 | 24 | this.tooltip_on_tab = true; |
|
25 | this.collapsed = false; | |
|
25 | 26 | IPython.Cell.apply(this, arguments); |
|
26 | 27 | }; |
|
27 | 28 | |
@@ -200,17 +201,20 b' var IPython = (function (IPython) {' | |||
|
200 | 201 | |
|
201 | 202 | |
|
202 | 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 | 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 | 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 | 268 | // JSON serialization |
|
265 | 269 | |
|
266 | 270 | CodeCell.prototype.fromJSON = function (data) { |
|
271 | IPython.Cell.prototype.fromJSON.apply(this, arguments); | |
|
267 | 272 | if (data.cell_type === 'code') { |
|
268 | 273 | if (data.input !== undefined) { |
|
269 | 274 | this.set_text(data.input); |
@@ -289,7 +294,7 b' var IPython = (function (IPython) {' | |||
|
289 | 294 | |
|
290 | 295 | |
|
291 | 296 | CodeCell.prototype.toJSON = function () { |
|
292 | var data = {}; | |
|
297 | var data = IPython.Cell.prototype.toJSON.apply(this); | |
|
293 | 298 | data.input = this.get_text(); |
|
294 | 299 | data.cell_type = 'code'; |
|
295 | 300 | if (this.input_prompt_number) { |
@@ -25,11 +25,14 b' var IPython = (function (IPython) {' | |||
|
25 | 25 | this.paste_enabled = false; |
|
26 | 26 | this.dirty = false; |
|
27 | 27 | this.metadata = {}; |
|
28 | // single worksheet for now | |
|
29 | this.worksheet_metadata = {}; | |
|
28 | 30 | this.control_key_active = false; |
|
29 | 31 | this.notebook_id = null; |
|
30 | 32 | this.notebook_name = null; |
|
31 | 33 | this.notebook_name_blacklist_re = /[\/\\:]/; |
|
32 | 34 | this.nbformat = 3 // Increment this when changing the nbformat |
|
35 | this.nbformat_minor = 0 // Increment this when changing the nbformat | |
|
33 | 36 | this.style(); |
|
34 | 37 | this.create_elements(); |
|
35 | 38 | this.bind_events(); |
@@ -1018,6 +1021,9 b' var IPython = (function (IPython) {' | |||
|
1018 | 1021 | // Only handle 1 worksheet for now. |
|
1019 | 1022 | var worksheet = data.worksheets[0]; |
|
1020 | 1023 | if (worksheet !== undefined) { |
|
1024 | if (worksheet.metadata) { | |
|
1025 | this.worksheet_metadata = worksheet.metadata; | |
|
1026 | } | |
|
1021 | 1027 | var new_cells = worksheet.cells; |
|
1022 | 1028 | ncells = new_cells.length; |
|
1023 | 1029 | var cell_data = null; |
@@ -1034,6 +1040,27 b' var IPython = (function (IPython) {' | |||
|
1034 | 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 | 1074 | var data = { |
|
1048 | 1075 | // Only handle 1 worksheet for now. |
|
1049 |
worksheets : [{ |
|
|
1076 | worksheets : [{ | |
|
1077 | cells: cell_array, | |
|
1078 | metadata: this.worksheet_metadata | |
|
1079 | }], | |
|
1050 | 1080 | metadata : this.metadata |
|
1051 | 1081 | }; |
|
1052 | 1082 | return data; |
@@ -1057,6 +1087,7 b' var IPython = (function (IPython) {' | |||
|
1057 | 1087 | var data = this.toJSON(); |
|
1058 | 1088 | data.metadata.name = this.notebook_name; |
|
1059 | 1089 | data.nbformat = this.nbformat; |
|
1090 | data.nbformat_minor = this.nbformat_minor; | |
|
1060 | 1091 | // We do the call with settings so we can set cache to false. |
|
1061 | 1092 | var settings = { |
|
1062 | 1093 | processData : false, |
@@ -1133,6 +1164,31 b' var IPython = (function (IPython) {' | |||
|
1133 | 1164 | }, |
|
1134 | 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 | 1193 | // Create the kernel after the notebook is completely loaded to prevent |
|
1138 | 1194 | // code execution upon loading, which is a security risk. |
@@ -155,6 +155,7 b' var IPython = (function (IPython) {' | |||
|
155 | 155 | |
|
156 | 156 | |
|
157 | 157 | TextCell.prototype.fromJSON = function (data) { |
|
158 | IPython.Cell.prototype.fromJSON.apply(this, arguments); | |
|
158 | 159 | if (data.cell_type === this.cell_type) { |
|
159 | 160 | if (data.source !== undefined) { |
|
160 | 161 | this.set_text(data.source); |
@@ -170,7 +171,7 b' var IPython = (function (IPython) {' | |||
|
170 | 171 | |
|
171 | 172 | |
|
172 | 173 | TextCell.prototype.toJSON = function () { |
|
173 | var data = {}; | |
|
174 | var data = IPython.Cell.prototype.toJSON.apply(this); | |
|
174 | 175 | data.cell_type = this.cell_type; |
|
175 | 176 | data.source = this.get_text(); |
|
176 | 177 | return data; |
@@ -28,7 +28,8 b' from IPython.nbformat import v1' | |||
|
28 | 28 | from IPython.nbformat.v3 import ( |
|
29 | 29 | NotebookNode, |
|
30 | 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 | 39 | current_nbformat = nbformat |
|
40 | current_nbformat_minor = nbformat_minor | |
|
41 | ||
|
39 | 42 | |
|
40 | 43 | |
|
41 | 44 | class NBFormatError(Exception): |
@@ -45,24 +48,30 b' class NBFormatError(Exception):' | |||
|
45 | 48 | def parse_json(s, **kwargs): |
|
46 | 49 | """Parse a string into a (nbformat, dict) tuple.""" |
|
47 | 50 | d = json.loads(s, **kwargs) |
|
48 | nbf = d.get('nbformat',1) | |
|
49 | return nbf, d | |
|
51 | nbf = d.get('nbformat', 1) | |
|
52 | nbm = d.get('nbformat_minor', 0) | |
|
53 | return nbf, nbm, d | |
|
50 | 54 | |
|
51 | 55 | |
|
52 | 56 | def parse_py(s, **kwargs): |
|
53 | 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 | 62 | m = re.search(pattern,s) |
|
56 | 63 | if m is not None: |
|
57 |
|
|
|
58 | else: | |
|
59 | nbf = current_nbformat | |
|
60 | return nbf, s | |
|
64 | digits = m.group('nbformat').split('.') | |
|
65 | nbf = int(digits[0]) | |
|
66 | if len(digits) > 1: | |
|
67 | nbm = int(digits[1]) | |
|
68 | ||
|
69 | return nbf, nbm, s | |
|
61 | 70 | |
|
62 | 71 | |
|
63 | 72 | def reads_json(s, **kwargs): |
|
64 | 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 | 75 | if nbf == 1: |
|
67 | 76 | nb = v1.to_notebook_json(d, **kwargs) |
|
68 | 77 | nb = v3.convert_to_this_nbformat(nb, orig_version=1) |
@@ -71,6 +80,7 b' def reads_json(s, **kwargs):' | |||
|
71 | 80 | nb = v3.convert_to_this_nbformat(nb, orig_version=2) |
|
72 | 81 | elif nbf == 3: |
|
73 | 82 | nb = v3.to_notebook_json(d, **kwargs) |
|
83 | nb = v3.convert_to_this_nbformat(nb, orig_version=3, orig_minor=minor) | |
|
74 | 84 | else: |
|
75 | 85 | raise NBFormatError('Unsupported JSON nbformat version: %i' % nbf) |
|
76 | 86 | return nb |
@@ -82,7 +92,7 b' def writes_json(nb, **kwargs):' | |||
|
82 | 92 | |
|
83 | 93 | def reads_py(s, **kwargs): |
|
84 | 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 | 96 | if nbf == 2: |
|
87 | 97 | nb = v2.to_notebook_py(s, **kwargs) |
|
88 | 98 | elif nbf == 3: |
@@ -19,7 +19,7 b' Authors:' | |||
|
19 | 19 | from .nbbase import ( |
|
20 | 20 | NotebookNode, |
|
21 | 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 | 25 | from .nbjson import reads as reads_json, writes as writes_json |
@@ -17,7 +17,8 b' Authors:' | |||
|
17 | 17 | #----------------------------------------------------------------------------- |
|
18 | 18 | |
|
19 | 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 | 24 | from IPython.nbformat import v2 |
@@ -26,7 +27,7 b' from IPython.nbformat import v2' | |||
|
26 | 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 | 31 | """Convert a notebook to the v3 format. |
|
31 | 32 | |
|
32 | 33 | Parameters |
@@ -35,16 +36,23 b' def convert_to_this_nbformat(nb, orig_version=2):' | |||
|
35 | 36 | The Python representation of the notebook to convert. |
|
36 | 37 | orig_version : int |
|
37 | 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 | 42 | if orig_version == 1: |
|
40 | 43 | nb = v2.convert_to_this_nbformat(nb) |
|
41 | 44 | orig_version = 2 |
|
42 | 45 | if orig_version == 2: |
|
43 | 46 | # Mark the original nbformat so consumers know it has been converted. |
|
44 |
nb.nbformat = |
|
|
47 | nb.nbformat = nbformat | |
|
48 | nb.nbformat_minor = nbformat_minor | |
|
49 | ||
|
45 | 50 | nb.orig_nbformat = 2 |
|
46 | 51 | return nb |
|
47 | 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 | 56 | return nb |
|
49 | 57 | else: |
|
50 | 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 | 33 | # Change this when incrementing the nbformat version |
|
34 | 34 | nbformat = 3 |
|
35 | nbformat_minor = 0 | |
|
35 | 36 | |
|
36 | 37 | class NotebookNode(Struct): |
|
37 | 38 | pass |
@@ -92,7 +93,7 b' def new_output(output_type=None, output_text=None, output_png=None,' | |||
|
92 | 93 | |
|
93 | 94 | |
|
94 | 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 | 97 | """Create a new code cell with input and output""" |
|
97 | 98 | cell = NotebookNode() |
|
98 | 99 | cell.cell_type = u'code' |
@@ -108,10 +109,11 b' def new_code_cell(input=None, prompt_number=None, outputs=None,' | |||
|
108 | 109 | cell.outputs = outputs |
|
109 | 110 | if collapsed is not None: |
|
110 | 111 | cell.collapsed = bool(collapsed) |
|
112 | cell.metadata = NotebookNode(metadata or {}) | |
|
111 | 113 | |
|
112 | 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 | 117 | """Create a new text cell.""" |
|
116 | 118 | cell = NotebookNode() |
|
117 | 119 | # VERSIONHACK: plaintext -> raw |
@@ -122,11 +124,12 b' def new_text_cell(cell_type, source=None, rendered=None):' | |||
|
122 | 124 | cell.source = unicode(source) |
|
123 | 125 | if rendered is not None: |
|
124 | 126 | cell.rendered = unicode(rendered) |
|
127 | cell.metadata = NotebookNode(metadata or {}) | |
|
125 | 128 | cell.cell_type = cell_type |
|
126 | 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 | 133 | """Create a new section cell with a given integer level.""" |
|
131 | 134 | cell = NotebookNode() |
|
132 | 135 | cell.cell_type = u'heading' |
@@ -135,10 +138,11 b' def new_heading_cell(source=None, rendered=None, level=1):' | |||
|
135 | 138 | if rendered is not None: |
|
136 | 139 | cell.rendered = unicode(rendered) |
|
137 | 140 | cell.level = int(level) |
|
141 | cell.metadata = NotebookNode(metadata or {}) | |
|
138 | 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 | 146 | """Create a worksheet by name with with a list of cells.""" |
|
143 | 147 | ws = NotebookNode() |
|
144 | 148 | if name is not None: |
@@ -147,6 +151,7 b' def new_worksheet(name=None, cells=None):' | |||
|
147 | 151 | ws.cells = [] |
|
148 | 152 | else: |
|
149 | 153 | ws.cells = list(cells) |
|
154 | ws.metadata = NotebookNode(metadata or {}) | |
|
150 | 155 | return ws |
|
151 | 156 | |
|
152 | 157 | |
@@ -154,6 +159,7 b' def new_notebook(name=None, metadata=None, worksheets=None):' | |||
|
154 | 159 | """Create a notebook by name, id and a list of worksheets.""" |
|
155 | 160 | nb = NotebookNode() |
|
156 | 161 | nb.nbformat = nbformat |
|
162 | nb.nbformat_minor = nbformat_minor | |
|
157 | 163 | if worksheets is None: |
|
158 | 164 | nb.worksheets = [] |
|
159 | 165 | else: |
@@ -20,7 +20,7 b' import re' | |||
|
20 | 20 | from .rwbase import NotebookReader, NotebookWriter |
|
21 | 21 | from .nbbase import ( |
|
22 | 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 | 153 | def writes(self, nb, **kwargs): |
|
154 | 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 | 159 | for ws in nb.worksheets: |
|
157 | 160 | for cell in ws.cells: |
|
158 | 161 | if cell.cell_type == u'code': |
@@ -6,7 +6,7 b' from base64 import encodestring' | |||
|
6 | 6 | from ..nbbase import ( |
|
7 | 7 | NotebookNode, |
|
8 | 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 | 12 | # some random base64-encoded *bytes* |
@@ -108,7 +108,7 b' nb0 = new_notebook(' | |||
|
108 | 108 | ) |
|
109 | 109 | |
|
110 | 110 | nb0_py = u"""# -*- coding: utf-8 -*- |
|
111 | # <nbformat>%i</nbformat> | |
|
111 | # <nbformat>%i.%i</nbformat> | |
|
112 | 112 | |
|
113 | 113 | # <htmlcell> |
|
114 | 114 | |
@@ -148,6 +148,6 b' b = 5' | |||
|
148 | 148 | |
|
149 | 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