##// END OF EJS Templates
Merge pull request #1331 from ellisonbg/celltypes...
Brian E. Granger -
r6037:069f64e8 merge
parent child Browse files
Show More
@@ -0,0 +1,74
1 """The main API for the v2 notebook format.
2
3 Authors:
4
5 * Brian Granger
6 """
7
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2011 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18
19 from .nbbase import (
20 NotebookNode,
21 new_code_cell, new_text_cell, new_notebook, new_output, new_worksheet,
22 new_metadata, new_author, new_heading_cell
23 )
24
25 from .nbjson import reads as reads_json, writes as writes_json
26 from .nbjson import reads as read_json, writes as write_json
27 from .nbjson import to_notebook as to_notebook_json
28
29 from .nbpy import reads as reads_py, writes as writes_py
30 from .nbpy import reads as read_py, writes as write_py
31 from .nbpy import to_notebook as to_notebook_py
32
33 from .convert import convert_to_this_nbformat
34
35 #-----------------------------------------------------------------------------
36 # Code
37 #-----------------------------------------------------------------------------
38
39 def parse_filename(fname):
40 """Parse a notebook filename.
41
42 This function takes a notebook filename and returns the notebook
43 format (json/py) and the notebook name. This logic can be
44 summarized as follows:
45
46 * notebook.ipynb -> (notebook.ipynb, notebook, json)
47 * notebook.json -> (notebook.json, notebook, json)
48 * notebook.py -> (notebook.py, notebook, py)
49 * notebook -> (notebook.ipynb, notebook, json)
50
51 Parameters
52 ----------
53 fname : unicode
54 The notebook filename. The filename can use a specific filename
55 extention (.ipynb, .json, .py) or none, in which case .ipynb will
56 be assumed.
57
58 Returns
59 -------
60 (fname, name, format) : (unicode, unicode, unicode)
61 The filename, notebook name and format.
62 """
63 if fname.endswith(u'.ipynb'):
64 format = u'json'
65 elif fname.endswith(u'.json'):
66 format = u'json'
67 elif fname.endswith(u'.py'):
68 format = u'py'
69 else:
70 fname = fname + u'.ipynb'
71 format = u'json'
72 name = fname.split('.')[0]
73 return fname, name, format
74
@@ -0,0 +1,48
1 """Code for converting notebooks to and from the v2 format.
2
3 Authors:
4
5 * Brian Granger
6 """
7
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2011 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18
19 from .nbbase import (
20 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output
21 )
22
23 from IPython.nbformat import v2
24
25 #-----------------------------------------------------------------------------
26 # Code
27 #-----------------------------------------------------------------------------
28
29 def convert_to_this_nbformat(nb, orig_version=2):
30 """Convert a notebook to the v2 format.
31
32 Parameters
33 ----------
34 nb : NotebookNode
35 The Python representation of the notebook to convert.
36 orig_version : int
37 The original version of the notebook to convert.
38 """
39 if orig_version == 1:
40 nb = v2.convert_to_this_nbformat(nb)
41 orig_version = 2
42 if orig_version == 2:
43 return nb
44 elif orig_version == 3:
45 return nb
46 else:
47 raise ValueError('Cannot convert a notebook from v%s to v3' % orig_version)
48
@@ -0,0 +1,191
1 """The basic dict based notebook format.
2
3 The Python representation of a notebook is a nested structure of
4 dictionary subclasses that support attribute access
5 (IPython.utils.ipstruct.Struct). The functions in this module are merely
6 helpers to build the structs in the right form.
7
8 Authors:
9
10 * Brian Granger
11 """
12
13 #-----------------------------------------------------------------------------
14 # Copyright (C) 2008-2011 The IPython Development Team
15 #
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
18 #-----------------------------------------------------------------------------
19
20 #-----------------------------------------------------------------------------
21 # Imports
22 #-----------------------------------------------------------------------------
23
24 import pprint
25 import uuid
26
27 from IPython.utils.ipstruct import Struct
28
29 #-----------------------------------------------------------------------------
30 # Code
31 #-----------------------------------------------------------------------------
32
33 class NotebookNode(Struct):
34 pass
35
36
37 def from_dict(d):
38 if isinstance(d, dict):
39 newd = NotebookNode()
40 for k,v in d.items():
41 newd[k] = from_dict(v)
42 return newd
43 elif isinstance(d, (tuple, list)):
44 return [from_dict(i) for i in d]
45 else:
46 return d
47
48
49 def new_output(output_type=None, output_text=None, output_png=None,
50 output_html=None, output_svg=None, output_latex=None, output_json=None,
51 output_javascript=None, output_jpeg=None, prompt_number=None,
52 etype=None, evalue=None, traceback=None):
53 """Create a new code cell with input and output"""
54 output = NotebookNode()
55 if output_type is not None:
56 output.output_type = unicode(output_type)
57
58 if output_type != 'pyerr':
59 if output_text is not None:
60 output.text = unicode(output_text)
61 if output_png is not None:
62 output.png = bytes(output_png)
63 if output_jpeg is not None:
64 output.jpeg = bytes(output_jpeg)
65 if output_html is not None:
66 output.html = unicode(output_html)
67 if output_svg is not None:
68 output.svg = unicode(output_svg)
69 if output_latex is not None:
70 output.latex = unicode(output_latex)
71 if output_json is not None:
72 output.json = unicode(output_json)
73 if output_javascript is not None:
74 output.javascript = unicode(output_javascript)
75
76 if output_type == u'pyout':
77 if prompt_number is not None:
78 output.prompt_number = int(prompt_number)
79
80 if output_type == u'pyerr':
81 if etype is not None:
82 output.etype = unicode(etype)
83 if evalue is not None:
84 output.evalue = unicode(evalue)
85 if traceback is not None:
86 output.traceback = [unicode(frame) for frame in list(traceback)]
87
88 return output
89
90
91 def new_code_cell(input=None, prompt_number=None, outputs=None,
92 language=u'python', collapsed=False):
93 """Create a new code cell with input and output"""
94 cell = NotebookNode()
95 cell.cell_type = u'code'
96 if language is not None:
97 cell.language = unicode(language)
98 if input is not None:
99 cell.input = unicode(input)
100 if prompt_number is not None:
101 cell.prompt_number = int(prompt_number)
102 if outputs is None:
103 cell.outputs = []
104 else:
105 cell.outputs = outputs
106 if collapsed is not None:
107 cell.collapsed = bool(collapsed)
108
109 return cell
110
111 def new_text_cell(cell_type, source=None, rendered=None):
112 """Create a new text cell."""
113 cell = NotebookNode()
114 if source is not None:
115 cell.source = unicode(source)
116 if rendered is not None:
117 cell.rendered = unicode(rendered)
118 cell.cell_type = cell_type
119 return cell
120
121
122 def new_heading_cell(source=None, rendered=None, level=1):
123 """Create a new section cell with a given integer level."""
124 cell = NotebookNode()
125 cell.cell_type = u'heading'
126 if source is not None:
127 cell.source = unicode(source)
128 if rendered is not None:
129 cell.rendered = unicode(rendered)
130 cell.level = int(level)
131 return cell
132
133
134 def new_worksheet(name=None, cells=None):
135 """Create a worksheet by name with with a list of cells."""
136 ws = NotebookNode()
137 if name is not None:
138 ws.name = unicode(name)
139 if cells is None:
140 ws.cells = []
141 else:
142 ws.cells = list(cells)
143 return ws
144
145
146 def new_notebook(metadata=None, worksheets=None):
147 """Create a notebook by name, id and a list of worksheets."""
148 nb = NotebookNode()
149 nb.nbformat = 3
150 if worksheets is None:
151 nb.worksheets = []
152 else:
153 nb.worksheets = list(worksheets)
154 if metadata is None:
155 nb.metadata = new_metadata()
156 else:
157 nb.metadata = NotebookNode(metadata)
158 return nb
159
160
161 def new_metadata(name=None, authors=None, license=None, created=None,
162 modified=None, gistid=None):
163 """Create a new metadata node."""
164 metadata = NotebookNode()
165 if name is not None:
166 metadata.name = unicode(name)
167 if authors is not None:
168 metadata.authors = list(authors)
169 if created is not None:
170 metadata.created = unicode(created)
171 if modified is not None:
172 metadata.modified = unicode(modified)
173 if license is not None:
174 metadata.license = unicode(license)
175 if gistid is not None:
176 metadata.gistid = unicode(gistid)
177 return metadata
178
179 def new_author(name=None, email=None, affiliation=None, url=None):
180 """Create a new author."""
181 author = NotebookNode()
182 if name is not None:
183 author.name = unicode(name)
184 if email is not None:
185 author.email = unicode(email)
186 if affiliation is not None:
187 author.affiliation = unicode(affiliation)
188 if url is not None:
189 author.url = unicode(url)
190 return author
191
@@ -0,0 +1,70
1 """Read and write notebooks in JSON format.
2
3 Authors:
4
5 * Brian Granger
6 """
7
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2011 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18
19 import copy
20 import json
21
22 from .nbbase import from_dict
23 from .rwbase import (
24 NotebookReader, NotebookWriter, restore_bytes, rejoin_lines, split_lines
25 )
26
27 #-----------------------------------------------------------------------------
28 # Code
29 #-----------------------------------------------------------------------------
30
31 class BytesEncoder(json.JSONEncoder):
32 """A JSON encoder that accepts b64 (and other *ascii*) bytestrings."""
33 def default(self, obj):
34 if isinstance(obj, bytes):
35 return obj.decode('ascii')
36 return json.JSONEncoder.default(self, obj)
37
38
39 class JSONReader(NotebookReader):
40
41 def reads(self, s, **kwargs):
42 nb = json.loads(s, **kwargs)
43 nb = self.to_notebook(nb, **kwargs)
44 return nb
45
46 def to_notebook(self, d, **kwargs):
47 return restore_bytes(rejoin_lines(from_dict(d)))
48
49
50 class JSONWriter(NotebookWriter):
51
52 def writes(self, nb, **kwargs):
53 kwargs['cls'] = BytesEncoder
54 kwargs['indent'] = 1
55 kwargs['sort_keys'] = True
56 kwargs['separators'] = (',',': ')
57 if kwargs.pop('split_lines', True):
58 nb = split_lines(copy.deepcopy(nb))
59 return json.dumps(nb, **kwargs)
60
61
62 _reader = JSONReader()
63 _writer = JSONWriter()
64
65 reads = _reader.reads
66 read = _reader.read
67 to_notebook = _reader.to_notebook
68 write = _writer.write
69 writes = _writer.writes
70
@@ -0,0 +1,200
1 """Read and write notebooks as regular .py files.
2
3 Authors:
4
5 * Brian Granger
6 """
7
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2011 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18
19 import re
20 from .rwbase import NotebookReader, NotebookWriter
21 from .nbbase import (
22 new_code_cell, new_text_cell, new_worksheet,
23 new_notebook, new_heading_cell
24 )
25
26 #-----------------------------------------------------------------------------
27 # Code
28 #-----------------------------------------------------------------------------
29
30 _encoding_declaration_re = re.compile(r"^#.*coding[:=]\s*([-\w.]+)")
31
32 class PyReaderError(Exception):
33 pass
34
35
36 class PyReader(NotebookReader):
37
38 def reads(self, s, **kwargs):
39 return self.to_notebook(s,**kwargs)
40
41 def to_notebook(self, s, **kwargs):
42 lines = s.splitlines()
43 cells = []
44 cell_lines = []
45 kwargs = {}
46 state = u'codecell'
47 for line in lines:
48 if line.startswith(u'# <nbformat>') or _encoding_declaration_re.match(line):
49 pass
50 elif line.startswith(u'# <codecell>'):
51 cell = self.new_cell(state, cell_lines, **kwargs)
52 if cell is not None:
53 cells.append(cell)
54 state = u'codecell'
55 cell_lines = []
56 kwargs = {}
57 elif line.startswith(u'# <htmlcell>'):
58 cell = self.new_cell(state, cell_lines, **kwargs)
59 if cell is not None:
60 cells.append(cell)
61 state = u'htmlcell'
62 cell_lines = []
63 kwargs = {}
64 elif line.startswith(u'# <markdowncell>'):
65 cell = self.new_cell(state, cell_lines, **kwargs)
66 if cell is not None:
67 cells.append(cell)
68 state = u'markdowncell'
69 cell_lines = []
70 kwargs = {}
71 elif line.startswith(u'# <plaintextcell>'):
72 cell = self.new_cell(state, cell_lines, **kwargs)
73 if cell is not None:
74 cells.append(cell)
75 state = u'plaintextcell'
76 cell_lines = []
77 kwargs = {}
78 elif line.startswith(u'# <headingcell'):
79 cell = self.new_cell(state, cell_lines, **kwargs)
80 if cell is not None:
81 cells.append(cell)
82 cell_lines = []
83 m = re.match(r'# <headingcell level=(?P<level>\d)>',line)
84 if m is not None:
85 state = u'headingcell'
86 kwargs = {}
87 kwargs['level'] = int(m.group('level'))
88 else:
89 state = u'codecell'
90 kwargs = {}
91 cell_lines = []
92 else:
93 cell_lines.append(line)
94 if cell_lines and state == u'codecell':
95 cell = self.new_cell(state, cell_lines)
96 if cell is not None:
97 cells.append(cell)
98 ws = new_worksheet(cells=cells)
99 nb = new_notebook(worksheets=[ws])
100 return nb
101
102 def new_cell(self, state, lines, **kwargs):
103 if state == u'codecell':
104 input = u'\n'.join(lines)
105 input = input.strip(u'\n')
106 if input:
107 return new_code_cell(input=input)
108 elif state == u'htmlcell':
109 text = self._remove_comments(lines)
110 if text:
111 return new_text_cell(u'html',source=text)
112 elif state == u'markdowncell':
113 text = self._remove_comments(lines)
114 if text:
115 return new_text_cell(u'markdown',source=text)
116 elif state == u'plaintextcell':
117 text = self._remove_comments(lines)
118 if text:
119 return new_text_cell(u'plaintext',source=text)
120 elif state == u'headingcell':
121 text = self._remove_comments(lines)
122 level = kwargs.get('level',1)
123 if text:
124 return new_heading_cell(source=text,level=level)
125
126 def _remove_comments(self, lines):
127 new_lines = []
128 for line in lines:
129 if line.startswith(u'#'):
130 new_lines.append(line[2:])
131 else:
132 new_lines.append(line)
133 text = u'\n'.join(new_lines)
134 text = text.strip(u'\n')
135 return text
136
137 def split_lines_into_blocks(self, lines):
138 if len(lines) == 1:
139 yield lines[0]
140 raise StopIteration()
141 import ast
142 source = '\n'.join(lines)
143 code = ast.parse(source)
144 starts = [x.lineno-1 for x in code.body]
145 for i in range(len(starts)-1):
146 yield '\n'.join(lines[starts[i]:starts[i+1]]).strip('\n')
147 yield '\n'.join(lines[starts[-1]:]).strip('\n')
148
149
150 class PyWriter(NotebookWriter):
151
152 def writes(self, nb, **kwargs):
153 lines = [u'# -*- coding: utf-8 -*-']
154 lines.extend([u'# <nbformat>2</nbformat>',''])
155 for ws in nb.worksheets:
156 for cell in ws.cells:
157 if cell.cell_type == u'code':
158 input = cell.get(u'input')
159 if input is not None:
160 lines.extend([u'# <codecell>',u''])
161 lines.extend(input.splitlines())
162 lines.append(u'')
163 elif cell.cell_type == u'html':
164 input = cell.get(u'source')
165 if input is not None:
166 lines.extend([u'# <htmlcell>',u''])
167 lines.extend([u'# ' + line for line in input.splitlines()])
168 lines.append(u'')
169 elif cell.cell_type == u'markdown':
170 input = cell.get(u'source')
171 if input is not None:
172 lines.extend([u'# <markdowncell>',u''])
173 lines.extend([u'# ' + line for line in input.splitlines()])
174 lines.append(u'')
175 elif cell.cell_type == u'plaintext':
176 input = cell.get(u'source')
177 if input is not None:
178 lines.extend([u'# <plaintextcell>',u''])
179 lines.extend([u'# ' + line for line in input.splitlines()])
180 lines.append(u'')
181 elif cell.cell_type == u'heading':
182 input = cell.get(u'source')
183 level = cell.get(u'level',1)
184 if input is not None:
185 lines.extend([u'# <headingcell level=%s>' % level,u''])
186 lines.extend([u'# ' + line for line in input.splitlines()])
187 lines.append(u'')
188 lines.append('')
189 return unicode('\n'.join(lines))
190
191
192 _reader = PyReader()
193 _writer = PyWriter()
194
195 reads = _reader.reads
196 read = _reader.read
197 to_notebook = _reader.to_notebook
198 write = _writer.write
199 writes = _writer.writes
200
@@ -0,0 +1,165
1 """Base classes and utilities for readers and writers.
2
3 Authors:
4
5 * Brian Granger
6 """
7
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2011 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18
19 from base64 import encodestring, decodestring
20 import pprint
21
22 from IPython.utils.py3compat import str_to_bytes
23
24 #-----------------------------------------------------------------------------
25 # Code
26 #-----------------------------------------------------------------------------
27
28 def restore_bytes(nb):
29 """Restore bytes of image data from unicode-only formats.
30
31 Base64 encoding is handled elsewhere. Bytes objects in the notebook are
32 always b64-encoded. We DO NOT encode/decode around file formats.
33 """
34 for ws in nb.worksheets:
35 for cell in ws.cells:
36 if cell.cell_type == 'code':
37 for output in cell.outputs:
38 if 'png' in output:
39 output.png = str_to_bytes(output.png, 'ascii')
40 if 'jpeg' in output:
41 output.jpeg = str_to_bytes(output.jpeg, 'ascii')
42 return nb
43
44 # output keys that are likely to have multiline values
45 _multiline_outputs = ['text', 'html', 'svg', 'latex', 'javascript', 'json']
46
47 def rejoin_lines(nb):
48 """rejoin multiline text into strings
49
50 For reversing effects of ``split_lines(nb)``.
51
52 This only rejoins lines that have been split, so if text objects were not split
53 they will pass through unchanged.
54
55 Used when reading JSON files that may have been passed through split_lines.
56 """
57 for ws in nb.worksheets:
58 for cell in ws.cells:
59 if cell.cell_type == 'code':
60 if 'input' in cell and isinstance(cell.input, list):
61 cell.input = u'\n'.join(cell.input)
62 for output in cell.outputs:
63 for key in _multiline_outputs:
64 item = output.get(key, None)
65 if isinstance(item, list):
66 output[key] = u'\n'.join(item)
67 else: # text, heading cell
68 for key in ['source', 'rendered']:
69 item = cell.get(key, None)
70 if isinstance(item, list):
71 cell[key] = u'\n'.join(item)
72 return nb
73
74
75 def split_lines(nb):
76 """split likely multiline text into lists of strings
77
78 For file output more friendly to line-based VCS. ``rejoin_lines(nb)`` will
79 reverse the effects of ``split_lines(nb)``.
80
81 Used when writing JSON files.
82 """
83 for ws in nb.worksheets:
84 for cell in ws.cells:
85 if cell.cell_type == 'code':
86 if 'input' in cell and isinstance(cell.input, basestring):
87 cell.input = cell.input.splitlines()
88 for output in cell.outputs:
89 for key in _multiline_outputs:
90 item = output.get(key, None)
91 if isinstance(item, basestring):
92 output[key] = item.splitlines()
93 else: # text, heading cell
94 for key in ['source', 'rendered']:
95 item = cell.get(key, None)
96 if isinstance(item, basestring):
97 cell[key] = item.splitlines()
98 return nb
99
100 # b64 encode/decode are never actually used, because all bytes objects in
101 # the notebook are already b64-encoded, and we don't need/want to double-encode
102
103 def base64_decode(nb):
104 """Restore all bytes objects in the notebook from base64-encoded strings.
105
106 Note: This is never used
107 """
108 for ws in nb.worksheets:
109 for cell in ws.cells:
110 if cell.cell_type == 'code':
111 for output in cell.outputs:
112 if 'png' in output:
113 if isinstance(output.png, unicode):
114 output.png = output.png.encode('ascii')
115 output.png = decodestring(output.png)
116 if 'jpeg' in output:
117 if isinstance(output.jpeg, unicode):
118 output.jpeg = output.jpeg.encode('ascii')
119 output.jpeg = decodestring(output.jpeg)
120 return nb
121
122
123 def base64_encode(nb):
124 """Base64 encode all bytes objects in the notebook.
125
126 These will be b64-encoded unicode strings
127
128 Note: This is never used
129 """
130 for ws in nb.worksheets:
131 for cell in ws.cells:
132 if cell.cell_type == 'code':
133 for output in cell.outputs:
134 if 'png' in output:
135 output.png = encodestring(output.png).decode('ascii')
136 if 'jpeg' in output:
137 output.jpeg = encodestring(output.jpeg).decode('ascii')
138 return nb
139
140
141 class NotebookReader(object):
142 """A class for reading notebooks."""
143
144 def reads(self, s, **kwargs):
145 """Read a notebook from a string."""
146 raise NotImplementedError("loads must be implemented in a subclass")
147
148 def read(self, fp, **kwargs):
149 """Read a notebook from a file like object"""
150 return self.read(fp.read(), **kwargs)
151
152
153 class NotebookWriter(object):
154 """A class for writing notebooks."""
155
156 def writes(self, nb, **kwargs):
157 """Write a notebook to a string."""
158 raise NotImplementedError("loads must be implemented in a subclass")
159
160 def write(self, nb, fp, **kwargs):
161 """Write a notebook to a file like object"""
162 return fp.write(self.writes(nb,**kwargs))
163
164
165
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
@@ -0,0 +1,127
1 import os
2 from base64 import encodestring
3
4 from ..nbbase import (
5 NotebookNode,
6 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
7 new_metadata, new_author, new_heading_cell
8 )
9
10 # some random base64-encoded *bytes*
11 png = encodestring(os.urandom(5))
12 jpeg = encodestring(os.urandom(6))
13
14 ws = new_worksheet(name='worksheet1')
15
16 ws.cells.append(new_text_cell(
17 u'html',
18 source='Some NumPy Examples',
19 rendered='Some NumPy Examples'
20 ))
21
22
23 ws.cells.append(new_code_cell(
24 input='import numpy',
25 prompt_number=1,
26 collapsed=False
27 ))
28
29 ws.cells.append(new_text_cell(
30 u'markdown',
31 source='A random array',
32 rendered='A random array'
33 ))
34
35 ws.cells.append(new_text_cell(
36 u'plaintext',
37 source='A random array',
38 ))
39
40 ws.cells.append(new_heading_cell(
41 u'My Heading',
42 level=2
43 ))
44
45 ws.cells.append(new_code_cell(
46 input='a = numpy.random.rand(100)',
47 prompt_number=2,
48 collapsed=True
49 ))
50
51 ws.cells.append(new_code_cell(
52 input='print a',
53 prompt_number=3,
54 collapsed=False,
55 outputs=[new_output(
56 output_type=u'pyout',
57 output_text=u'<array a>',
58 output_html=u'The HTML rep',
59 output_latex=u'$a$',
60 output_png=png,
61 output_jpeg=jpeg,
62 output_svg=u'<svg>',
63 output_json=u'json data',
64 output_javascript=u'var i=0;',
65 prompt_number=3
66 ),new_output(
67 output_type=u'display_data',
68 output_text=u'<array a>',
69 output_html=u'The HTML rep',
70 output_latex=u'$a$',
71 output_png=png,
72 output_jpeg=jpeg,
73 output_svg=u'<svg>',
74 output_json=u'json data',
75 output_javascript=u'var i=0;'
76 ),new_output(
77 output_type=u'pyerr',
78 etype=u'NameError',
79 evalue=u'NameError was here',
80 traceback=[u'frame 0', u'frame 1', u'frame 2']
81 )]
82 ))
83
84 authors = [new_author(name='Bart Simpson',email='bsimpson@fox.com',
85 affiliation=u'Fox',url=u'http://www.fox.com')]
86 md = new_metadata(name=u'My Notebook',license=u'BSD',created=u'8601_goes_here',
87 modified=u'8601_goes_here',gistid=u'21341231',authors=authors)
88
89 nb0 = new_notebook(
90 worksheets=[ws, new_worksheet(name='worksheet2')],
91 metadata=md
92 )
93
94 nb0_py = """# -*- coding: utf-8 -*-
95 # <nbformat>2</nbformat>
96
97 # <htmlcell>
98
99 # Some NumPy Examples
100
101 # <codecell>
102
103 import numpy
104
105 # <markdowncell>
106
107 # A random array
108
109 # <plaintextcell>
110
111 # A random array
112
113 # <headingcell level=2>
114
115 # My Heading
116
117 # <codecell>
118
119 a = numpy.random.rand(100)
120
121 # <codecell>
122
123 print a
124
125 """
126
127
@@ -0,0 +1,34
1 import pprint
2 from unittest import TestCase
3
4 from ..nbjson import reads, writes
5 from .nbexamples import nb0
6
7
8 class TestJSON(TestCase):
9
10 def test_roundtrip(self):
11 s = writes(nb0)
12 # print
13 # print pprint.pformat(nb0,indent=2)
14 # print
15 # print pprint.pformat(reads(s),indent=2)
16 # print
17 # print s
18 self.assertEquals(reads(s),nb0)
19
20 def test_roundtrip_nosplit(self):
21 """Ensure that multiline blobs are still readable"""
22 # ensures that notebooks written prior to splitlines change
23 # are still readable.
24 s = writes(nb0, split_lines=False)
25 self.assertEquals(reads(s),nb0)
26
27 def test_roundtrip_split(self):
28 """Ensure that splitting multiline blocks is safe"""
29 # This won't differ from test_roundtrip unless the default changes
30 s = writes(nb0, split_lines=True)
31 self.assertEquals(reads(s),nb0)
32
33
34
@@ -0,0 +1,136
1 from unittest import TestCase
2
3 from ..nbbase import (
4 NotebookNode,
5 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
6 new_author, new_metadata, new_heading_cell
7 )
8
9 class TestCell(TestCase):
10
11 def test_empty_code_cell(self):
12 cc = new_code_cell()
13 self.assertEquals(cc.cell_type,u'code')
14 self.assertEquals(u'input' not in cc, True)
15 self.assertEquals(u'prompt_number' not in cc, True)
16 self.assertEquals(cc.outputs, [])
17 self.assertEquals(cc.collapsed, False)
18
19 def test_code_cell(self):
20 cc = new_code_cell(input='a=10', prompt_number=0, collapsed=True)
21 cc.outputs = [new_output(output_type=u'pyout',
22 output_svg=u'foo',output_text=u'10',prompt_number=0)]
23 self.assertEquals(cc.input, u'a=10')
24 self.assertEquals(cc.prompt_number, 0)
25 self.assertEquals(cc.language, u'python')
26 self.assertEquals(cc.outputs[0].svg, u'foo')
27 self.assertEquals(cc.outputs[0].text, u'10')
28 self.assertEquals(cc.outputs[0].prompt_number, 0)
29 self.assertEquals(cc.collapsed, True)
30
31 def test_pyerr(self):
32 o = new_output(output_type=u'pyerr', etype=u'NameError',
33 evalue=u'Name not found', traceback=[u'frame 0', u'frame 1', u'frame 2']
34 )
35 self.assertEquals(o.output_type, u'pyerr')
36 self.assertEquals(o.etype, u'NameError')
37 self.assertEquals(o.evalue, u'Name not found')
38 self.assertEquals(o.traceback, [u'frame 0', u'frame 1', u'frame 2'])
39
40 def test_empty_html_cell(self):
41 tc = new_text_cell(u'html')
42 self.assertEquals(tc.cell_type, u'html')
43 self.assertEquals(u'source' not in tc, True)
44 self.assertEquals(u'rendered' not in tc, True)
45
46 def test_html_cell(self):
47 tc = new_text_cell(u'html', 'hi', 'hi')
48 self.assertEquals(tc.source, u'hi')
49 self.assertEquals(tc.rendered, u'hi')
50
51 def test_empty_markdown_cell(self):
52 tc = new_text_cell(u'markdown')
53 self.assertEquals(tc.cell_type, u'markdown')
54 self.assertEquals(u'source' not in tc, True)
55 self.assertEquals(u'rendered' not in tc, True)
56
57 def test_markdown_cell(self):
58 tc = new_text_cell(u'markdown', 'hi', 'hi')
59 self.assertEquals(tc.source, u'hi')
60 self.assertEquals(tc.rendered, u'hi')
61
62 def test_empty_plaintext_cell(self):
63 tc = new_text_cell(u'plaintext')
64 self.assertEquals(tc.cell_type, u'plaintext')
65 self.assertEquals(u'source' not in tc, True)
66 self.assertEquals(u'rendered' not in tc, True)
67
68 def test_plaintext_cell(self):
69 tc = new_text_cell(u'plaintext', 'hi', 'hi')
70 self.assertEquals(tc.source, u'hi')
71 self.assertEquals(tc.rendered, u'hi')
72
73 def test_empty_heading_cell(self):
74 tc = new_heading_cell()
75 self.assertEquals(tc.cell_type, u'heading')
76 self.assertEquals(u'source' not in tc, True)
77 self.assertEquals(u'rendered' not in tc, True)
78
79 def test_heading_cell(self):
80 tc = new_heading_cell(u'hi', u'hi', level=2)
81 self.assertEquals(tc.source, u'hi')
82 self.assertEquals(tc.rendered, u'hi')
83 self.assertEquals(tc.level, 2)
84
85
86 class TestWorksheet(TestCase):
87
88 def test_empty_worksheet(self):
89 ws = new_worksheet()
90 self.assertEquals(ws.cells,[])
91 self.assertEquals(u'name' not in ws, True)
92
93 def test_worksheet(self):
94 cells = [new_code_cell(), new_text_cell(u'html')]
95 ws = new_worksheet(cells=cells,name=u'foo')
96 self.assertEquals(ws.cells,cells)
97 self.assertEquals(ws.name,u'foo')
98
99 class TestNotebook(TestCase):
100
101 def test_empty_notebook(self):
102 nb = new_notebook()
103 self.assertEquals(nb.worksheets, [])
104 self.assertEquals(nb.metadata, NotebookNode())
105 self.assertEquals(nb.nbformat,2)
106
107 def test_notebook(self):
108 worksheets = [new_worksheet(),new_worksheet()]
109 metadata = new_metadata(name=u'foo')
110 nb = new_notebook(metadata=metadata,worksheets=worksheets)
111 self.assertEquals(nb.metadata.name,u'foo')
112 self.assertEquals(nb.worksheets,worksheets)
113 self.assertEquals(nb.nbformat,2)
114
115 class TestMetadata(TestCase):
116
117 def test_empty_metadata(self):
118 md = new_metadata()
119 self.assertEquals(u'name' not in md, True)
120 self.assertEquals(u'authors' not in md, True)
121 self.assertEquals(u'license' not in md, True)
122 self.assertEquals(u'saved' not in md, True)
123 self.assertEquals(u'modified' not in md, True)
124 self.assertEquals(u'gistid' not in md, True)
125
126 def test_metadata(self):
127 authors = [new_author(name='Bart Simpson',email='bsimpson@fox.com')]
128 md = new_metadata(name=u'foo',license=u'BSD',created=u'today',
129 modified=u'now',gistid=u'21341231',authors=authors)
130 self.assertEquals(md.name, u'foo')
131 self.assertEquals(md.license, u'BSD')
132 self.assertEquals(md.created, u'today')
133 self.assertEquals(md.modified, u'now')
134 self.assertEquals(md.gistid, u'21341231')
135 self.assertEquals(md.authors, authors)
136
@@ -0,0 +1,17
1 from unittest import TestCase
2
3 from ..nbbase import (
4 NotebookNode,
5 new_code_cell, new_text_cell, new_worksheet, new_notebook
6 )
7
8 from ..nbpy import reads, writes
9 from .nbexamples import nb0, nb0_py
10
11
12 class TestPy(TestCase):
13
14 def test_write(self):
15 s = writes(nb0)
16 self.assertEquals(s,nb0_py)
17
@@ -824,6 +824,8 var IPython = (function (IPython) {
824 if (data.collapsed !== undefined) {
824 if (data.collapsed !== undefined) {
825 if (data.collapsed) {
825 if (data.collapsed) {
826 this.collapse();
826 this.collapse();
827 } else {
828 this.expand();
827 };
829 };
828 };
830 };
829 };
831 };
@@ -129,6 +129,27 var IPython = (function (IPython) {
129 this.element.find('#to_markdown').click(function () {
129 this.element.find('#to_markdown').click(function () {
130 IPython.notebook.to_markdown();
130 IPython.notebook.to_markdown();
131 });
131 });
132 this.element.find('#to_plaintext').click(function () {
133 IPython.notebook.to_plaintext();
134 });
135 this.element.find('#to_heading1').click(function () {
136 IPython.notebook.to_heading(undefined, 1);
137 });
138 this.element.find('#to_heading2').click(function () {
139 IPython.notebook.to_heading(undefined, 2);
140 });
141 this.element.find('#to_heading3').click(function () {
142 IPython.notebook.to_heading(undefined, 3);
143 });
144 this.element.find('#to_heading4').click(function () {
145 IPython.notebook.to_heading(undefined, 4);
146 });
147 this.element.find('#to_heading5').click(function () {
148 IPython.notebook.to_heading(undefined, 5);
149 });
150 this.element.find('#to_heading6').click(function () {
151 IPython.notebook.to_heading(undefined, 6);
152 });
132 this.element.find('#toggle_output').click(function () {
153 this.element.find('#toggle_output').click(function () {
133 IPython.notebook.toggle_output();
154 IPython.notebook.toggle_output();
134 });
155 });
@@ -136,7 +136,42 var IPython = (function (IPython) {
136 that.control_key_active = false;
136 that.control_key_active = false;
137 return false;
137 return false;
138 } else if (event.which === 84 && that.control_key_active) {
138 } else if (event.which === 84 && that.control_key_active) {
139 // Toggle output = t
139 // To Plaintext = t
140 that.to_plaintext();
141 that.control_key_active = false;
142 return false;
143 } else if (event.which === 49 && that.control_key_active) {
144 // To Heading 1 = 1
145 that.to_heading(undefined, 1);
146 that.control_key_active = false;
147 return false;
148 } else if (event.which === 50 && that.control_key_active) {
149 // To Heading 2 = 2
150 that.to_heading(undefined, 2);
151 that.control_key_active = false;
152 return false;
153 } else if (event.which === 51 && that.control_key_active) {
154 // To Heading 3 = 3
155 that.to_heading(undefined, 3);
156 that.control_key_active = false;
157 return false;
158 } else if (event.which === 52 && that.control_key_active) {
159 // To Heading 4 = 4
160 that.to_heading(undefined, 4);
161 that.control_key_active = false;
162 return false;
163 } else if (event.which === 53 && that.control_key_active) {
164 // To Heading 5 = 5
165 that.to_heading(undefined, 5);
166 that.control_key_active = false;
167 return false;
168 } else if (event.which === 54 && that.control_key_active) {
169 // To Heading 6 = 6
170 that.to_heading(undefined, 6);
171 that.control_key_active = false;
172 return false;
173 } else if (event.which === 79 && that.control_key_active) {
174 // Toggle output = o
140 that.toggle_output();
175 that.toggle_output();
141 that.control_key_active = false;
176 that.control_key_active = false;
142 return false;
177 return false;
@@ -366,7 +401,11 var IPython = (function (IPython) {
366 };
401 };
367 var cell = this.get_cell(index)
402 var cell = this.get_cell(index)
368 cell.select();
403 cell.select();
369 IPython.toolbar.set_cell_type(cell.cell_type);
404 if (cell.cell_type === 'heading') {
405 IPython.toolbar.set_cell_type(cell.cell_type+cell.level);
406 } else {
407 IPython.toolbar.set_cell_type(cell.cell_type)
408 }
370 };
409 };
371 return this;
410 return this;
372 };
411 };
@@ -467,15 +506,19 var IPython = (function (IPython) {
467 // type = ('code','html','markdown')
506 // type = ('code','html','markdown')
468 // index = cell index or undefined to insert below selected
507 // index = cell index or undefined to insert below selected
469 index = this.index_or_selected(index);
508 index = this.index_or_selected(index);
470 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
471 var cell = null;
509 var cell = null;
510 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
472 if (type === 'code') {
511 if (type === 'code') {
473 var cell = new IPython.CodeCell(this);
512 cell = new IPython.CodeCell(this);
474 cell.set_input_prompt();
513 cell.set_input_prompt();
475 } else if (type === 'markdown') {
514 } else if (type === 'markdown') {
476 var cell = new IPython.MarkdownCell(this);
515 cell = new IPython.MarkdownCell(this);
477 } else if (type === 'html') {
516 } else if (type === 'html') {
478 var cell = new IPython.HTMLCell(this);
517 cell = new IPython.HTMLCell(this);
518 } else if (type === 'plaintext') {
519 cell = new IPython.PlaintextCell(this);
520 } else if (type === 'heading') {
521 cell = new IPython.HeadingCell(this);
479 };
522 };
480 if (cell !== null) {
523 if (cell !== null) {
481 if (this.ncells() === 0) {
524 if (this.ncells() === 0) {
@@ -489,6 +532,7 var IPython = (function (IPython) {
489 return cell;
532 return cell;
490 };
533 };
491 };
534 };
535 return cell;
492 };
536 };
493
537
494
538
@@ -496,15 +540,19 var IPython = (function (IPython) {
496 // type = ('code','html','markdown')
540 // type = ('code','html','markdown')
497 // index = cell index or undefined to insert above selected
541 // index = cell index or undefined to insert above selected
498 index = this.index_or_selected(index);
542 index = this.index_or_selected(index);
499 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
500 var cell = null;
543 var cell = null;
544 if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
501 if (type === 'code') {
545 if (type === 'code') {
502 var cell = new IPython.CodeCell(this);
546 cell = new IPython.CodeCell(this);
503 cell.set_input_prompt();
547 cell.set_input_prompt();
504 } else if (type === 'markdown') {
548 } else if (type === 'markdown') {
505 var cell = new IPython.MarkdownCell(this);
549 cell = new IPython.MarkdownCell(this);
506 } else if (type === 'html') {
550 } else if (type === 'html') {
507 var cell = new IPython.HTMLCell(this);
551 cell = new IPython.HTMLCell(this);
552 } else if (type === 'plaintext') {
553 cell = new IPython.PlaintextCell(this);
554 } else if (type === 'heading') {
555 cell = new IPython.HeadingCell(this);
508 };
556 };
509 if (cell !== null) {
557 if (cell !== null) {
510 if (this.ncells() === 0) {
558 if (this.ncells() === 0) {
@@ -518,6 +566,7 var IPython = (function (IPython) {
518 return cell;
566 return cell;
519 };
567 };
520 };
568 };
569 return cell;
521 };
570 };
522
571
523
572
@@ -534,10 +583,10 var IPython = (function (IPython) {
534 }
583 }
535 target_cell.set_text(text);
584 target_cell.set_text(text);
536 source_element.remove();
585 source_element.remove();
537 };
538 this.dirty = true;
586 this.dirty = true;
539 };
587 };
540 };
588 };
589 };
541
590
542
591
543 Notebook.prototype.to_markdown = function (index) {
592 Notebook.prototype.to_markdown = function (index) {
@@ -545,19 +594,16 var IPython = (function (IPython) {
545 if (this.is_valid_cell_index(i)) {
594 if (this.is_valid_cell_index(i)) {
546 var source_element = this.get_cell_element(i);
595 var source_element = this.get_cell_element(i);
547 var source_cell = source_element.data("cell");
596 var source_cell = source_element.data("cell");
548 var target_cell = null;
549 if (!(source_cell instanceof IPython.MarkdownCell)) {
597 if (!(source_cell instanceof IPython.MarkdownCell)) {
550 target_cell = this.insert_cell_below('markdown',i);
598 target_cell = this.insert_cell_below('markdown',i);
551 var text = source_cell.get_text();
599 var text = source_cell.get_text();
552 if (text === source_cell.placeholder) {
600 if (text === source_cell.placeholder) {
553 text = '';
601 text = '';
554 };
602 };
555 if (target_cell !== null) {
556 // The edit must come before the set_text.
603 // The edit must come before the set_text.
557 target_cell.edit();
604 target_cell.edit();
558 target_cell.set_text(text);
605 target_cell.set_text(text);
559 source_element.remove();
606 source_element.remove();
560 }
561 this.dirty = true;
607 this.dirty = true;
562 };
608 };
563 };
609 };
@@ -576,18 +622,65 var IPython = (function (IPython) {
576 if (text === source_cell.placeholder) {
622 if (text === source_cell.placeholder) {
577 text = '';
623 text = '';
578 };
624 };
579 if (target_cell !== null) {
580 // The edit must come before the set_text.
625 // The edit must come before the set_text.
581 target_cell.edit();
626 target_cell.edit();
582 target_cell.set_text(text);
627 target_cell.set_text(text);
583 source_element.remove();
628 source_element.remove();
584 }
585 this.dirty = true;
629 this.dirty = true;
586 };
630 };
587 };
631 };
588 };
632 };
589
633
590
634
635 Notebook.prototype.to_plaintext = function (index) {
636 var i = this.index_or_selected(index);
637 if (this.is_valid_cell_index(i)) {
638 var source_element = this.get_cell_element(i);
639 var source_cell = source_element.data("cell");
640 var target_cell = null;
641 if (!(source_cell instanceof IPython.PlaintextCell)) {
642 target_cell = this.insert_cell_below('plaintext',i);
643 var text = source_cell.get_text();
644 if (text === source_cell.placeholder) {
645 text = '';
646 };
647 // The edit must come before the set_text.
648 target_cell.edit();
649 target_cell.set_text(text);
650 source_element.remove();
651 this.dirty = true;
652 };
653 };
654 };
655
656
657 Notebook.prototype.to_heading = function (index, level) {
658 level = level || 1;
659 var i = this.index_or_selected(index);
660 if (this.is_valid_cell_index(i)) {
661 var source_element = this.get_cell_element(i);
662 var source_cell = source_element.data("cell");
663 var target_cell = null;
664 if (source_cell instanceof IPython.HeadingCell) {
665 source_cell.set_level(level);
666 } else {
667 target_cell = this.insert_cell_below('heading',i);
668 var text = source_cell.get_text();
669 if (text === source_cell.placeholder) {
670 text = '';
671 };
672 // The edit must come before the set_text.
673 target_cell.set_level(level);
674 target_cell.edit();
675 target_cell.set_text(text);
676 source_element.remove();
677 this.dirty = true;
678 };
679 IPython.toolbar.set_cell_type("heading"+level);
680 };
681 };
682
683
591 // Cut/Copy/Paste
684 // Cut/Copy/Paste
592
685
593 Notebook.prototype.enable_paste = function () {
686 Notebook.prototype.enable_paste = function () {
@@ -1098,7 +1191,7 var IPython = (function (IPython) {
1098 // We may want to move the name/id/nbformat logic inside toJSON?
1191 // We may want to move the name/id/nbformat logic inside toJSON?
1099 var data = this.toJSON();
1192 var data = this.toJSON();
1100 data.metadata.name = nbname;
1193 data.metadata.name = nbname;
1101 data.nbformat = 2;
1194 data.nbformat = 3;
1102 // We do the call with settings so we can set cache to false.
1195 // We do the call with settings so we can set cache to false.
1103 var settings = {
1196 var settings = {
1104 processData : false,
1197 processData : false,
@@ -34,13 +34,15 var IPython = (function (IPython) {
34 {key: 'Ctrl-m d', help: 'delete cell'},
34 {key: 'Ctrl-m d', help: 'delete cell'},
35 {key: 'Ctrl-m a', help: 'insert cell above'},
35 {key: 'Ctrl-m a', help: 'insert cell above'},
36 {key: 'Ctrl-m b', help: 'insert cell below'},
36 {key: 'Ctrl-m b', help: 'insert cell below'},
37 {key: 'Ctrl-m t', help: 'toggle output'},
37 {key: 'Ctrl-m o', help: 'toggle output'},
38 {key: 'Ctrl-m l', help: 'toggle line numbers'},
38 {key: 'Ctrl-m l', help: 'toggle line numbers'},
39 {key: 'Ctrl-m s', help: 'save notebook'},
39 {key: 'Ctrl-m s', help: 'save notebook'},
40 {key: 'Ctrl-m j', help: 'move cell down'},
40 {key: 'Ctrl-m j', help: 'move cell down'},
41 {key: 'Ctrl-m k', help: 'move cell up'},
41 {key: 'Ctrl-m k', help: 'move cell up'},
42 {key: 'Ctrl-m y', help: 'code cell'},
42 {key: 'Ctrl-m y', help: 'code cell'},
43 {key: 'Ctrl-m m', help: 'markdown cell'},
43 {key: 'Ctrl-m m', help: 'markdown cell'},
44 {key: 'Ctrl-m t', help: 'plaintext cell'},
45 {key: 'Ctrl-m 1-6', help: 'heading 1-6 cell'},
44 {key: 'Ctrl-m p', help: 'select previous'},
46 {key: 'Ctrl-m p', help: 'select previous'},
45 {key: 'Ctrl-m n', help: 'select next'},
47 {key: 'Ctrl-m n', help: 'select next'},
46 {key: 'Ctrl-m i', help: 'interrupt kernel'},
48 {key: 'Ctrl-m i', help: 'interrupt kernel'},
@@ -237,49 +237,109 var IPython = (function (IPython) {
237 };
237 };
238
238
239
239
240 // RSTCell
240 // PlaintextCell
241
241
242 var RSTCell = function (notebook) {
242 var PlaintextCell = function (notebook) {
243 this.placeholder = "Type *ReStructured Text* and LaTeX: $\\alpha^2$";
243 this.placeholder = "Type plain text and LaTeX: $\\alpha^2$";
244 this.code_mirror_mode = 'rst';
244 IPython.TextCell.apply(this, arguments);
245 IPython.TextCell.apply(this, arguments);
245 this.cell_type = 'rst';
246 this.cell_type = 'plaintext';
246 };
247 };
247
248
248
249
249 RSTCell.prototype = new TextCell();
250 PlaintextCell.prototype = new TextCell();
250
251
251
252
252 RSTCell.prototype.render = function () {
253 PlaintextCell.prototype.render = function () {
253 if (this.rendered === false) {
254 this.rendered = true;
254 var text = this.get_text();
255 this.edit();
255 if (text === "") { text = this.placeholder; }
256 };
256 var settings = {
257
257 processData : false,
258
258 cache : false,
259 PlaintextCell.prototype.select = function () {
259 type : "POST",
260 IPython.Cell.prototype.select.apply(this);
260 data : text,
261 this.code_mirror.refresh();
261 headers : {'Content-Type': 'application/x-rst'},
262 this.code_mirror.focus();
262 success : $.proxy(this.handle_render,this)
263 };
263 };
264
264 $.ajax("/rstservice/render", settings);
265
265 this.element.find('div.text_cell_input').hide();
266 PlaintextCell.prototype.at_top = function () {
266 this.element.find("div.text_cell_render").show();
267 var cursor = this.code_mirror.getCursor();
267 this.set_rendered("Rendering...");
268 if (cursor.line === 0) {
269 return true;
270 } else {
271 return false;
272 }
273 };
274
275
276 PlaintextCell.prototype.at_bottom = function () {
277 var cursor = this.code_mirror.getCursor();
278 if (cursor.line === (this.code_mirror.lineCount()-1)) {
279 return true;
280 } else {
281 return false;
268 }
282 }
269 };
283 };
270
284
271
285
272 RSTCell.prototype.handle_render = function (data, status, xhr) {
286 // HTMLCell
273 this.set_rendered(data);
287
288 var HeadingCell = function (notebook) {
289 this.placeholder = "Type Heading Here";
290 IPython.TextCell.apply(this, arguments);
291 this.cell_type = 'heading';
292 this.level = 1;
293 };
294
295
296 HeadingCell.prototype = new TextCell();
297
298
299 HeadingCell.prototype.set_level = function (level) {
300 this.level = level;
301 if (this.rendered) {
302 this.rendered = false;
303 this.render();
304 };
305 };
306
307
308 HeadingCell.prototype.get_level = function () {
309 return this.level;
310 };
311
312
313 HeadingCell.prototype.set_rendered = function (text) {
314 var r = this.element.find("div.text_cell_render");
315 r.empty();
316 r.append($('<h'+this.level+'/>').html(text));
317 };
318
319
320 HeadingCell.prototype.get_rendered = function () {
321 var r = this.element.find("div.text_cell_render");
322 return r.children().first().html();
323 };
324
325
326 HeadingCell.prototype.render = function () {
327 if (this.rendered === false) {
328 var text = this.get_text();
329 if (text === "") { text = this.placeholder; }
330 this.set_rendered(text);
274 this.typeset();
331 this.typeset();
332 this.element.find('div.text_cell_input').hide();
333 this.element.find("div.text_cell_render").show();
275 this.rendered = true;
334 this.rendered = true;
276 };
335 };
277
336 };
278
337
279 IPython.TextCell = TextCell;
338 IPython.TextCell = TextCell;
280 IPython.HTMLCell = HTMLCell;
339 IPython.HTMLCell = HTMLCell;
281 IPython.MarkdownCell = MarkdownCell;
340 IPython.MarkdownCell = MarkdownCell;
282 IPython.RSTCell = RSTCell;
341 IPython.PlaintextCell = PlaintextCell;
342 IPython.HeadingCell = HeadingCell;
283
343
284
344
285 return IPython;
345 return IPython;
@@ -108,6 +108,20 var IPython = (function (IPython) {
108 IPython.notebook.to_code();
108 IPython.notebook.to_code();
109 } else if (cell_type === 'markdown') {
109 } else if (cell_type === 'markdown') {
110 IPython.notebook.to_markdown();
110 IPython.notebook.to_markdown();
111 } else if (cell_type === 'plaintext') {
112 IPython.notebook.to_plaintext();
113 } else if (cell_type === 'heading1') {
114 IPython.notebook.to_heading(undefined, 1);
115 } else if (cell_type === 'heading2') {
116 IPython.notebook.to_heading(undefined, 2);
117 } else if (cell_type === 'heading3') {
118 IPython.notebook.to_heading(undefined, 3);
119 } else if (cell_type === 'heading4') {
120 IPython.notebook.to_heading(undefined, 4);
121 } else if (cell_type === 'heading5') {
122 IPython.notebook.to_heading(undefined, 5);
123 } else if (cell_type === 'heading6') {
124 IPython.notebook.to_heading(undefined, 6);
111 };
125 };
112 });
126 });
113
127
@@ -117,8 +117,15
117 <li id="run_cell_in_place"><a href="#">Run in Place</a></li>
117 <li id="run_cell_in_place"><a href="#">Run in Place</a></li>
118 <li id="run_all_cells"><a href="#">Run All</a></li>
118 <li id="run_all_cells"><a href="#">Run All</a></li>
119 <hr/>
119 <hr/>
120 <li id="to_code"><a href="#">Code Cell</a></li>
120 <li id="to_code"><a href="#">Code</a></li>
121 <li id="to_markdown"><a href="#">Markdown Cell</a></li>
121 <li id="to_markdown"><a href="#">Markdown </a></li>
122 <li id="to_plaintext"><a href="#">Plaintext</a></li>
123 <li id="to_heading1"><a href="#">Heading 1</a></li>
124 <li id="to_heading2"><a href="#">Heading 2</a></li>
125 <li id="to_heading3"><a href="#">Heading 3</a></li>
126 <li id="to_heading4"><a href="#">Heading 4</a></li>
127 <li id="to_heading5"><a href="#">Heading 5</a></li>
128 <li id="to_heading6"><a href="#">Heading 6</a></li>
122 <hr/>
129 <hr/>
123 <li id="toggle_output"><a href="#">Toggle Output</a></li>
130 <li id="toggle_output"><a href="#">Toggle Output</a></li>
124 <li id="clear_all_output"><a href="#">Clear All Output</a></li>
131 <li id="clear_all_output"><a href="#">Clear All Output</a></li>
@@ -173,6 +180,13
173 <select id="cell_type">
180 <select id="cell_type">
174 <option value="code">Code</option>
181 <option value="code">Code</option>
175 <option value="markdown">Markdown</option>
182 <option value="markdown">Markdown</option>
183 <option value="plaintext">Plaintext</option>
184 <option value="heading1">Heading 1</option>
185 <option value="heading2">Heading 2</option>
186 <option value="heading3">Heading 3</option>
187 <option value="heading4">Heading 4</option>
188 <option value="heading5">Heading 5</option>
189 <option value="heading6">Heading 6</option>
176 </select>
190 </select>
177 </span>
191 </span>
178
192
@@ -21,20 +21,21 import json
21 from xml.etree import ElementTree as ET
21 from xml.etree import ElementTree as ET
22 import re
22 import re
23
23
24 from IPython.nbformat import v3
24 from IPython.nbformat import v2
25 from IPython.nbformat import v2
25 from IPython.nbformat import v1
26 from IPython.nbformat import v1
26
27
27 from IPython.nbformat.v2 import (
28 from IPython.nbformat.v3 import (
28 NotebookNode,
29 NotebookNode,
29 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,
30 parse_filename, new_metadata, new_author
31 parse_filename, new_metadata, new_author, new_heading_cell
31 )
32 )
32
33
33 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
34 # Code
35 # Code
35 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
36
37
37 current_nbformat = 2
38 current_nbformat = 3
38
39
39
40
40 class NBFormatError(Exception):
41 class NBFormatError(Exception):
@@ -48,17 +49,6 def parse_json(s, **kwargs):
48 return nbformat, d
49 return nbformat, d
49
50
50
51
51 def parse_xml(s, **kwargs):
52 """Parse a string into a (nbformat, etree) tuple."""
53 root = ET.fromstring(s)
54 nbformat_e = root.find('nbformat')
55 if nbformat_e is not None:
56 nbformat = int(nbformat_e.text)
57 else:
58 raise NBFormatError('No nbformat version found')
59 return nbformat, root
60
61
62 def parse_py(s, **kwargs):
52 def parse_py(s, **kwargs):
63 """Parse a string into a (nbformat, string) tuple."""
53 """Parse a string into a (nbformat, string) tuple."""
64 pattern = r'# <nbformat>(?P<nbformat>\d+)</nbformat>'
54 pattern = r'# <nbformat>(?P<nbformat>\d+)</nbformat>'
@@ -66,7 +56,7 def parse_py(s, **kwargs):
66 if m is not None:
56 if m is not None:
67 nbformat = int(m.group('nbformat'))
57 nbformat = int(m.group('nbformat'))
68 else:
58 else:
69 nbformat = 2
59 nbformat = 3
70 return nbformat, s
60 return nbformat, s
71
61
72
62
@@ -75,26 +65,19 def reads_json(s, **kwargs):
75 nbformat, d = parse_json(s, **kwargs)
65 nbformat, d = parse_json(s, **kwargs)
76 if nbformat == 1:
66 if nbformat == 1:
77 nb = v1.to_notebook_json(d, **kwargs)
67 nb = v1.to_notebook_json(d, **kwargs)
78 nb = v2.convert_to_this_nbformat(nb, orig_version=1)
68 nb = v3.convert_to_this_nbformat(nb, orig_version=1)
79 elif nbformat == 2:
69 elif nbformat == 2:
80 nb = v2.to_notebook_json(d, **kwargs)
70 nb = v2.to_notebook_json(d, **kwargs)
71 nb = v3.convert_to_this_nbformat(nb, orig_version=2)
72 elif nbformat == 3:
73 nb = v3.to_notebook_json(d, **kwargs)
81 else:
74 else:
82 raise NBFormatError('Unsupported JSON nbformat version: %i' % nbformat)
75 raise NBFormatError('Unsupported JSON nbformat version: %i' % nbformat)
83 return nb
76 return nb
84
77
85
78
86 def writes_json(nb, **kwargs):
79 def writes_json(nb, **kwargs):
87 return v2.writes_json(nb, **kwargs)
80 return v3.writes_json(nb, **kwargs)
88
89
90 def reads_xml(s, **kwargs):
91 """Read an XML notebook from a string and return the NotebookNode object."""
92 nbformat, root = parse_xml(s, **kwargs)
93 if nbformat == 2:
94 nb = v2.to_notebook_xml(root, **kwargs)
95 else:
96 raise NBFormatError('Unsupported XML nbformat version: %i' % nbformat)
97 return nb
98
81
99
82
100 def reads_py(s, **kwargs):
83 def reads_py(s, **kwargs):
@@ -102,13 +85,15 def reads_py(s, **kwargs):
102 nbformat, s = parse_py(s, **kwargs)
85 nbformat, s = parse_py(s, **kwargs)
103 if nbformat == 2:
86 if nbformat == 2:
104 nb = v2.to_notebook_py(s, **kwargs)
87 nb = v2.to_notebook_py(s, **kwargs)
88 elif nbformat == 3:
89 nb = v3.to_notebook_py(s, **kwargs)
105 else:
90 else:
106 raise NBFormatError('Unsupported PY nbformat version: %i' % nbformat)
91 raise NBFormatError('Unsupported PY nbformat version: %i' % nbformat)
107 return nb
92 return nb
108
93
109
94
110 def writes_py(nb, **kwargs):
95 def writes_py(nb, **kwargs):
111 return v2.writes_py(nb, **kwargs)
96 return v3.writes_py(nb, **kwargs)
112
97
113
98
114 # High level API
99 # High level API
@@ -133,9 +118,7 def reads(s, format, **kwargs):
133 The notebook that was read.
118 The notebook that was read.
134 """
119 """
135 format = unicode(format)
120 format = unicode(format)
136 if format == u'xml':
121 if format == u'json' or format == u'ipynb':
137 return reads_xml(s, **kwargs)
138 elif format == u'json' or format == u'ipynb':
139 return reads_json(s, **kwargs)
122 return reads_json(s, **kwargs)
140 elif format == u'py':
123 elif format == u'py':
141 return reads_py(s, **kwargs)
124 return reads_py(s, **kwargs)
@@ -161,9 +144,7 def writes(nb, format, **kwargs):
161 The notebook string.
144 The notebook string.
162 """
145 """
163 format = unicode(format)
146 format = unicode(format)
164 if format == u'xml':
147 if format == u'json' or format == u'ipynb':
165 raise NotImplementedError('Write to XML files is not implemented.')
166 elif format == u'json' or format == u'ipynb':
167 return writes_json(nb, **kwargs)
148 return writes_json(nb, **kwargs)
168 elif format == u'py':
149 elif format == u'py':
169 return writes_py(nb, **kwargs)
150 return writes_py(nb, **kwargs)
@@ -2,7 +2,7
2 "metadata": {
2 "metadata": {
3 "name": "00_notebook_tour"
3 "name": "00_notebook_tour"
4 },
4 },
5 "nbformat": 2,
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
@@ -2,7 +2,7
2 "metadata": {
2 "metadata": {
3 "name": "01_notebook_introduction"
3 "name": "01_notebook_introduction"
4 },
4 },
5 "nbformat": 2,
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
@@ -2,7 +2,7
2 "metadata": {
2 "metadata": {
3 "name": "display_protocol"
3 "name": "display_protocol"
4 },
4 },
5 "nbformat": 2,
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
@@ -2,7 +2,7
2 "metadata": {
2 "metadata": {
3 "name": "formatting"
3 "name": "formatting"
4 },
4 },
5 "nbformat": 2,
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
@@ -2,7 +2,7
2 "metadata": {
2 "metadata": {
3 "name": "sympy"
3 "name": "sympy"
4 },
4 },
5 "nbformat": 2,
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
@@ -2,7 +2,7
2 "metadata": {
2 "metadata": {
3 "name": "sympy_quantum_computing"
3 "name": "sympy_quantum_computing"
4 },
4 },
5 "nbformat": 2,
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
@@ -2,7 +2,7
2 "metadata": {
2 "metadata": {
3 "name": "trapezoid_rule"
3 "name": "trapezoid_rule"
4 },
4 },
5 "nbformat": 2,
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
@@ -2,7 +2,7
2 "metadata": {
2 "metadata": {
3 "name": "helloworld"
3 "name": "helloworld"
4 },
4 },
5 "nbformat": 2,
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
@@ -2,7 +2,7
2 "metadata": {
2 "metadata": {
3 "name": "parallel_mpi"
3 "name": "parallel_mpi"
4 },
4 },
5 "nbformat": 2,
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
@@ -1,87 +1,116
1 {
1 {
2 "nbformat": 2,
3 "metadata": {
2 "metadata": {
4 "name": "task_1"
3 "name": "task1"
5 },
4 },
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
9 {
9 {
10 "source": "# Simple task farming example",
10 "cell_type": "markdown",
11 "cell_type": "markdown"
11 "source": [
12 "# Simple task farming example"
13 ]
12 },
14 },
13 {
15 {
14 "cell_type": "code",
16 "cell_type": "code",
17 "collapsed": true,
18 "input": [
19 "from IPython.parallel import Client"
20 ],
15 "language": "python",
21 "language": "python",
16 "outputs": [],
22 "outputs": [],
17 "collapsed": true,
23 "prompt_number": 3
18 "prompt_number": 3,
19 "input": "from IPython.parallel import Client"
20 },
24 },
21 {
25 {
22 "source": "A `Client.load_balanced_view` is used to get the object used for working with load balanced tasks.",
26 "cell_type": "markdown",
23 "cell_type": "markdown"
27 "source": [
28 "A `Client.load_balanced_view` is used to get the object used for working with load balanced tasks."
29 ]
24 },
30 },
25 {
31 {
26 "cell_type": "code",
32 "cell_type": "code",
33 "collapsed": true,
34 "input": [
35 "rc = Client()",
36 "v = rc.load_balanced_view()"
37 ],
27 "language": "python",
38 "language": "python",
28 "outputs": [],
39 "outputs": [],
29 "collapsed": true,
40 "prompt_number": 4
30 "prompt_number": 4,
31 "input": "rc = Client()\nv = rc.load_balanced_view()"
32 },
41 },
33 {
42 {
34 "source": "Set the variable `d` on all engines:",
43 "cell_type": "markdown",
35 "cell_type": "markdown"
44 "source": [
45 "Set the variable `d` on all engines:"
46 ]
36 },
47 },
37 {
48 {
38 "cell_type": "code",
49 "cell_type": "code",
50 "collapsed": true,
51 "input": [
52 "rc[:]['d'] = 30"
53 ],
39 "language": "python",
54 "language": "python",
40 "outputs": [],
55 "outputs": [],
41 "collapsed": true,
56 "prompt_number": 5
42 "prompt_number": 5,
43 "input": "rc[:]['d'] = 30"
44 },
57 },
45 {
58 {
46 "source": "Define a function that will be our task:",
59 "cell_type": "markdown",
47 "cell_type": "markdown"
60 "source": [
61 "Define a function that will be our task:"
62 ]
48 },
63 },
49 {
64 {
50 "cell_type": "code",
65 "cell_type": "code",
66 "collapsed": true,
67 "input": [
68 "def task(a):",
69 " return a, 10*d, a*10*d"
70 ],
51 "language": "python",
71 "language": "python",
52 "outputs": [],
72 "outputs": [],
53 "collapsed": true,
73 "prompt_number": 6
54 "prompt_number": 6,
55 "input": "def task(a):\n return a, 10*d, a*10*d"
56 },
74 },
57 {
75 {
58 "source": "Run the task once:",
76 "cell_type": "markdown",
59 "cell_type": "markdown"
77 "source": [
78 "Run the task once:"
79 ]
60 },
80 },
61 {
81 {
62 "cell_type": "code",
82 "cell_type": "code",
83 "collapsed": true,
84 "input": [
85 "ar = v.apply(task, 5)"
86 ],
63 "language": "python",
87 "language": "python",
64 "outputs": [],
88 "outputs": [],
65 "collapsed": true,
89 "prompt_number": 7
66 "prompt_number": 7,
67 "input": "ar = v.apply(task, 5)"
68 },
90 },
69 {
91 {
70 "source": "Print the results:",
92 "cell_type": "markdown",
71 "cell_type": "markdown"
93 "source": [
94 "Print the results:"
95 ]
72 },
96 },
73 {
97 {
74 "cell_type": "code",
98 "cell_type": "code",
99 "collapsed": false,
100 "input": [
101 "print \"a, b, c: \", ar.get()"
102 ],
75 "language": "python",
103 "language": "python",
76 "outputs": [
104 "outputs": [
77 {
105 {
78 "output_type": "stream",
106 "output_type": "stream",
79 "text": "a, b, c: [5, 300, 1500]"
107 "stream": "stdout",
108 "text": [
109 "a, b, c: [5, 300, 1500]"
110 ]
80 }
111 }
81 ],
112 ],
82 "collapsed": false,
113 "prompt_number": 8
83 "prompt_number": 8,
84 "input": "print \"a, b, c: \", ar.get()"
85 }
114 }
86 ]
115 ]
87 }
116 }
@@ -2,7 +2,7
2 "metadata": {
2 "metadata": {
3 "name": "taskmap"
3 "name": "taskmap"
4 },
4 },
5 "nbformat": 2,
5 "nbformat": 3,
6 "worksheets": [
6 "worksheets": [
7 {
7 {
8 "cells": [
8 "cells": [
General Comments 0
You need to be logged in to leave comments. Login now