##// END OF EJS Templates
Adding rst and heading cells to the notebook format.
Brian Granger -
Show More
@@ -1,179 +1,189 b''
1 1 """The basic dict based notebook format.
2 2
3 3 The Python representation of a notebook is a nested structure of
4 4 dictionary subclasses that support attribute access
5 5 (IPython.utils.ipstruct.Struct). The functions in this module are merely
6 6 helpers to build the structs in the right form.
7 7
8 8 Authors:
9 9
10 10 * Brian Granger
11 11 """
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Copyright (C) 2008-2011 The IPython Development Team
15 15 #
16 16 # Distributed under the terms of the BSD License. The full license is in
17 17 # the file COPYING, distributed as part of this software.
18 18 #-----------------------------------------------------------------------------
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Imports
22 22 #-----------------------------------------------------------------------------
23 23
24 24 import pprint
25 25 import uuid
26 26
27 27 from IPython.utils.ipstruct import Struct
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Code
31 31 #-----------------------------------------------------------------------------
32 32
33 33 class NotebookNode(Struct):
34 34 pass
35 35
36 36
37 37 def from_dict(d):
38 38 if isinstance(d, dict):
39 39 newd = NotebookNode()
40 40 for k,v in d.items():
41 41 newd[k] = from_dict(v)
42 42 return newd
43 43 elif isinstance(d, (tuple, list)):
44 44 return [from_dict(i) for i in d]
45 45 else:
46 46 return d
47 47
48 48
49 49 def new_output(output_type=None, output_text=None, output_png=None,
50 50 output_html=None, output_svg=None, output_latex=None, output_json=None,
51 51 output_javascript=None, output_jpeg=None, prompt_number=None,
52 52 etype=None, evalue=None, traceback=None):
53 53 """Create a new code cell with input and output"""
54 54 output = NotebookNode()
55 55 if output_type is not None:
56 56 output.output_type = unicode(output_type)
57 57
58 58 if output_type != 'pyerr':
59 59 if output_text is not None:
60 60 output.text = unicode(output_text)
61 61 if output_png is not None:
62 62 output.png = bytes(output_png)
63 63 if output_jpeg is not None:
64 64 output.jpeg = bytes(output_jpeg)
65 65 if output_html is not None:
66 66 output.html = unicode(output_html)
67 67 if output_svg is not None:
68 68 output.svg = unicode(output_svg)
69 69 if output_latex is not None:
70 70 output.latex = unicode(output_latex)
71 71 if output_json is not None:
72 72 output.json = unicode(output_json)
73 73 if output_javascript is not None:
74 74 output.javascript = unicode(output_javascript)
75 75
76 76 if output_type == u'pyout':
77 77 if prompt_number is not None:
78 78 output.prompt_number = int(prompt_number)
79 79
80 80 if output_type == u'pyerr':
81 81 if etype is not None:
82 82 output.etype = unicode(etype)
83 83 if evalue is not None:
84 84 output.evalue = unicode(evalue)
85 85 if traceback is not None:
86 86 output.traceback = [unicode(frame) for frame in list(traceback)]
87 87
88 88 return output
89 89
90 90
91 91 def new_code_cell(input=None, prompt_number=None, outputs=None,
92 92 language=u'python', collapsed=False):
93 93 """Create a new code cell with input and output"""
94 94 cell = NotebookNode()
95 95 cell.cell_type = u'code'
96 96 if language is not None:
97 97 cell.language = unicode(language)
98 98 if input is not None:
99 99 cell.input = unicode(input)
100 100 if prompt_number is not None:
101 101 cell.prompt_number = int(prompt_number)
102 102 if outputs is None:
103 103 cell.outputs = []
104 104 else:
105 105 cell.outputs = outputs
106 106 if collapsed is not None:
107 107 cell.collapsed = bool(collapsed)
108 108
109 109 return cell
110 110
111 111 def new_text_cell(cell_type, source=None, rendered=None):
112 112 """Create a new text cell."""
113 113 cell = NotebookNode()
114 114 if source is not None:
115 115 cell.source = unicode(source)
116 116 if rendered is not None:
117 117 cell.rendered = unicode(rendered)
118 118 cell.cell_type = cell_type
119 119 return cell
120 120
121 121
122 def new_heading_cell(source=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 cell.level = int(level)
129 return cell
130
131
122 132 def new_worksheet(name=None, cells=None):
123 133 """Create a worksheet by name with with a list of cells."""
124 134 ws = NotebookNode()
125 135 if name is not None:
126 136 ws.name = unicode(name)
127 137 if cells is None:
128 138 ws.cells = []
129 139 else:
130 140 ws.cells = list(cells)
131 141 return ws
132 142
133 143
134 144 def new_notebook(metadata=None, worksheets=None):
135 145 """Create a notebook by name, id and a list of worksheets."""
136 146 nb = NotebookNode()
137 147 nb.nbformat = 2
138 148 if worksheets is None:
139 149 nb.worksheets = []
140 150 else:
141 151 nb.worksheets = list(worksheets)
142 152 if metadata is None:
143 153 nb.metadata = new_metadata()
144 154 else:
145 155 nb.metadata = NotebookNode(metadata)
146 156 return nb
147 157
148 158
149 159 def new_metadata(name=None, authors=None, license=None, created=None,
150 160 modified=None, gistid=None):
151 161 """Create a new metadata node."""
152 162 metadata = NotebookNode()
153 163 if name is not None:
154 164 metadata.name = unicode(name)
155 165 if authors is not None:
156 166 metadata.authors = list(authors)
157 167 if created is not None:
158 168 metadata.created = unicode(created)
159 169 if modified is not None:
160 170 metadata.modified = unicode(modified)
161 171 if license is not None:
162 172 metadata.license = unicode(license)
163 173 if gistid is not None:
164 174 metadata.gistid = unicode(gistid)
165 175 return metadata
166 176
167 177 def new_author(name=None, email=None, affiliation=None, url=None):
168 178 """Create a new author."""
169 179 author = NotebookNode()
170 180 if name is not None:
171 181 author.name = unicode(name)
172 182 if email is not None:
173 183 author.email = unicode(email)
174 184 if affiliation is not None:
175 185 author.affiliation = unicode(affiliation)
176 186 if url is not None:
177 187 author.url = unicode(url)
178 188 return author
179 189
@@ -1,150 +1,200 b''
1 1 """Read and write notebooks as regular .py files.
2 2
3 3 Authors:
4 4
5 5 * Brian Granger
6 6 """
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2008-2011 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 import re
20 20 from .rwbase import NotebookReader, NotebookWriter
21 from .nbbase import new_code_cell, new_text_cell, new_worksheet, new_notebook
21 from .nbbase import (
22 new_code_cell, new_text_cell, new_worksheet,
23 new_notebook, new_heading_cell
24 )
22 25
23 26 #-----------------------------------------------------------------------------
24 27 # Code
25 28 #-----------------------------------------------------------------------------
26 29
27 30 _encoding_declaration_re = re.compile(r"^#.*coding[:=]\s*([-\w.]+)")
28 31
29 32 class PyReaderError(Exception):
30 33 pass
31 34
32 35
33 36 class PyReader(NotebookReader):
34 37
35 38 def reads(self, s, **kwargs):
36 39 return self.to_notebook(s,**kwargs)
37 40
38 41 def to_notebook(self, s, **kwargs):
39 42 lines = s.splitlines()
40 43 cells = []
41 44 cell_lines = []
45 kwargs = {}
42 46 state = u'codecell'
43 47 for line in lines:
44 48 if line.startswith(u'# <nbformat>') or _encoding_declaration_re.match(line):
45 49 pass
46 50 elif line.startswith(u'# <codecell>'):
47 cell = self.new_cell(state, cell_lines)
51 cell = self.new_cell(state, cell_lines, **kwargs)
48 52 if cell is not None:
49 53 cells.append(cell)
50 54 state = u'codecell'
51 55 cell_lines = []
56 kwargs = {}
52 57 elif line.startswith(u'# <htmlcell>'):
53 cell = self.new_cell(state, cell_lines)
58 cell = self.new_cell(state, cell_lines, **kwargs)
54 59 if cell is not None:
55 60 cells.append(cell)
56 61 state = u'htmlcell'
57 62 cell_lines = []
63 kwargs = {}
58 64 elif line.startswith(u'# <markdowncell>'):
59 cell = self.new_cell(state, cell_lines)
65 cell = self.new_cell(state, cell_lines, **kwargs)
60 66 if cell is not None:
61 67 cells.append(cell)
62 68 state = u'markdowncell'
63 69 cell_lines = []
70 kwargs = {}
71 elif line.startswith(u'# <rstcell>'):
72 cell = self.new_cell(state, cell_lines, **kwargs)
73 if cell is not None:
74 cells.append(cell)
75 state = u'rstcell'
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 = []
64 92 else:
65 93 cell_lines.append(line)
66 94 if cell_lines and state == u'codecell':
67 95 cell = self.new_cell(state, cell_lines)
68 96 if cell is not None:
69 97 cells.append(cell)
70 98 ws = new_worksheet(cells=cells)
71 99 nb = new_notebook(worksheets=[ws])
72 100 return nb
73 101
74 def new_cell(self, state, lines):
102 def new_cell(self, state, lines, **kwargs):
75 103 if state == u'codecell':
76 104 input = u'\n'.join(lines)
77 105 input = input.strip(u'\n')
78 106 if input:
79 107 return new_code_cell(input=input)
80 108 elif state == u'htmlcell':
81 109 text = self._remove_comments(lines)
82 110 if text:
83 111 return new_text_cell(u'html',source=text)
84 112 elif state == u'markdowncell':
85 113 text = self._remove_comments(lines)
86 114 if text:
87 115 return new_text_cell(u'markdown',source=text)
116 elif state == u'rstcell':
117 text = self._remove_comments(lines)
118 if text:
119 return new_text_cell(u'rst',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)
88 125
89 126 def _remove_comments(self, lines):
90 127 new_lines = []
91 128 for line in lines:
92 129 if line.startswith(u'#'):
93 130 new_lines.append(line[2:])
94 131 else:
95 132 new_lines.append(line)
96 133 text = u'\n'.join(new_lines)
97 134 text = text.strip(u'\n')
98 135 return text
99 136
100 137 def split_lines_into_blocks(self, lines):
101 138 if len(lines) == 1:
102 139 yield lines[0]
103 140 raise StopIteration()
104 141 import ast
105 142 source = '\n'.join(lines)
106 143 code = ast.parse(source)
107 144 starts = [x.lineno-1 for x in code.body]
108 145 for i in range(len(starts)-1):
109 146 yield '\n'.join(lines[starts[i]:starts[i+1]]).strip('\n')
110 147 yield '\n'.join(lines[starts[-1]:]).strip('\n')
111 148
112 149
113 150 class PyWriter(NotebookWriter):
114 151
115 152 def writes(self, nb, **kwargs):
116 153 lines = [u'# -*- coding: utf-8 -*-']
117 154 lines.extend([u'# <nbformat>2</nbformat>',''])
118 155 for ws in nb.worksheets:
119 156 for cell in ws.cells:
120 157 if cell.cell_type == u'code':
121 158 input = cell.get(u'input')
122 159 if input is not None:
123 160 lines.extend([u'# <codecell>',u''])
124 161 lines.extend(input.splitlines())
125 162 lines.append(u'')
126 163 elif cell.cell_type == u'html':
127 164 input = cell.get(u'source')
128 165 if input is not None:
129 166 lines.extend([u'# <htmlcell>',u''])
130 167 lines.extend([u'# ' + line for line in input.splitlines()])
131 168 lines.append(u'')
132 169 elif cell.cell_type == u'markdown':
133 170 input = cell.get(u'source')
134 171 if input is not None:
135 172 lines.extend([u'# <markdowncell>',u''])
136 173 lines.extend([u'# ' + line for line in input.splitlines()])
137 174 lines.append(u'')
175 elif cell.cell_type == u'rst':
176 input = cell.get(u'source')
177 if input is not None:
178 lines.extend([u'# <rstcell>',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'')
138 188 lines.append('')
139 189 return unicode('\n'.join(lines))
140 190
141 191
142 192 _reader = PyReader()
143 193 _writer = PyWriter()
144 194
145 195 reads = _reader.reads
146 196 read = _reader.read
147 197 to_notebook = _reader.to_notebook
148 198 write = _writer.write
149 199 writes = _writer.writes
150 200
@@ -1,165 +1,169 b''
1 1 """Base classes and utilities for readers and writers.
2 2
3 3 Authors:
4 4
5 5 * Brian Granger
6 6 """
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2008-2011 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 from base64 import encodestring, decodestring
20 20 import pprint
21 21
22 22 from IPython.utils.py3compat import str_to_bytes
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Code
26 26 #-----------------------------------------------------------------------------
27 27
28 28 def restore_bytes(nb):
29 29 """Restore bytes of image data from unicode-only formats.
30 30
31 31 Base64 encoding is handled elsewhere. Bytes objects in the notebook are
32 32 always b64-encoded. We DO NOT encode/decode around file formats.
33 33 """
34 34 for ws in nb.worksheets:
35 35 for cell in ws.cells:
36 36 if cell.cell_type == 'code':
37 37 for output in cell.outputs:
38 38 if 'png' in output:
39 39 output.png = str_to_bytes(output.png, 'ascii')
40 40 if 'jpeg' in output:
41 41 output.jpeg = str_to_bytes(output.jpeg, 'ascii')
42 42 return nb
43 43
44 44 # output keys that are likely to have multiline values
45 45 _multiline_outputs = ['text', 'html', 'svg', 'latex', 'javascript', 'json']
46 46
47 47 def rejoin_lines(nb):
48 48 """rejoin multiline text into strings
49 49
50 50 For reversing effects of ``split_lines(nb)``.
51 51
52 52 This only rejoins lines that have been split, so if text objects were not split
53 53 they will pass through unchanged.
54 54
55 55 Used when reading JSON files that may have been passed through split_lines.
56 56 """
57 57 for ws in nb.worksheets:
58 58 for cell in ws.cells:
59 59 if cell.cell_type == 'code':
60 60 if 'input' in cell and isinstance(cell.input, list):
61 61 cell.input = u'\n'.join(cell.input)
62 62 for output in cell.outputs:
63 63 for key in _multiline_outputs:
64 64 item = output.get(key, None)
65 65 if isinstance(item, list):
66 66 output[key] = u'\n'.join(item)
67 elif cell.cell_type == 'heading':
68 pass
67 69 else: # text cell
68 70 for key in ['source', 'rendered']:
69 71 item = cell.get(key, None)
70 72 if isinstance(item, list):
71 73 cell[key] = u'\n'.join(item)
72 74 return nb
73 75
74 76
75 77 def split_lines(nb):
76 78 """split likely multiline text into lists of strings
77 79
78 80 For file output more friendly to line-based VCS. ``rejoin_lines(nb)`` will
79 81 reverse the effects of ``split_lines(nb)``.
80 82
81 83 Used when writing JSON files.
82 84 """
83 85 for ws in nb.worksheets:
84 86 for cell in ws.cells:
85 87 if cell.cell_type == 'code':
86 88 if 'input' in cell and isinstance(cell.input, basestring):
87 89 cell.input = cell.input.splitlines()
88 90 for output in cell.outputs:
89 91 for key in _multiline_outputs:
90 92 item = output.get(key, None)
91 93 if isinstance(item, basestring):
92 94 output[key] = item.splitlines()
95 elif cell.cell_type == 'heading':
96 pass
93 97 else: # text cell
94 98 for key in ['source', 'rendered']:
95 99 item = cell.get(key, None)
96 100 if isinstance(item, basestring):
97 101 cell[key] = item.splitlines()
98 102 return nb
99 103
100 104 # b64 encode/decode are never actually used, because all bytes objects in
101 105 # the notebook are already b64-encoded, and we don't need/want to double-encode
102 106
103 107 def base64_decode(nb):
104 108 """Restore all bytes objects in the notebook from base64-encoded strings.
105 109
106 110 Note: This is never used
107 111 """
108 112 for ws in nb.worksheets:
109 113 for cell in ws.cells:
110 114 if cell.cell_type == 'code':
111 115 for output in cell.outputs:
112 116 if 'png' in output:
113 117 if isinstance(output.png, unicode):
114 118 output.png = output.png.encode('ascii')
115 119 output.png = decodestring(output.png)
116 120 if 'jpeg' in output:
117 121 if isinstance(output.jpeg, unicode):
118 122 output.jpeg = output.jpeg.encode('ascii')
119 123 output.jpeg = decodestring(output.jpeg)
120 124 return nb
121 125
122 126
123 127 def base64_encode(nb):
124 128 """Base64 encode all bytes objects in the notebook.
125 129
126 130 These will be b64-encoded unicode strings
127 131
128 132 Note: This is never used
129 133 """
130 134 for ws in nb.worksheets:
131 135 for cell in ws.cells:
132 136 if cell.cell_type == 'code':
133 137 for output in cell.outputs:
134 138 if 'png' in output:
135 139 output.png = encodestring(output.png).decode('ascii')
136 140 if 'jpeg' in output:
137 141 output.jpeg = encodestring(output.jpeg).decode('ascii')
138 142 return nb
139 143
140 144
141 145 class NotebookReader(object):
142 146 """A class for reading notebooks."""
143 147
144 148 def reads(self, s, **kwargs):
145 149 """Read a notebook from a string."""
146 150 raise NotImplementedError("loads must be implemented in a subclass")
147 151
148 152 def read(self, fp, **kwargs):
149 153 """Read a notebook from a file like object"""
150 154 return self.read(fp.read(), **kwargs)
151 155
152 156
153 157 class NotebookWriter(object):
154 158 """A class for writing notebooks."""
155 159
156 160 def writes(self, nb, **kwargs):
157 161 """Write a notebook to a string."""
158 162 raise NotImplementedError("loads must be implemented in a subclass")
159 163
160 164 def write(self, nb, fp, **kwargs):
161 165 """Write a notebook to a file like object"""
162 166 return fp.write(self.writes(nb,**kwargs))
163 167
164 168
165 169
@@ -1,109 +1,127 b''
1 1 import os
2 2 from base64 import encodestring
3 3
4 4 from ..nbbase import (
5 5 NotebookNode,
6 6 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
7 new_metadata, new_author
7 new_metadata, new_author, new_heading_cell
8 8 )
9 9
10 10 # some random base64-encoded *bytes*
11 11 png = encodestring(os.urandom(5))
12 12 jpeg = encodestring(os.urandom(6))
13 13
14 14 ws = new_worksheet(name='worksheet1')
15 15
16 16 ws.cells.append(new_text_cell(
17 17 u'html',
18 18 source='Some NumPy Examples',
19 19 rendered='Some NumPy Examples'
20 20 ))
21 21
22 22
23 23 ws.cells.append(new_code_cell(
24 24 input='import numpy',
25 25 prompt_number=1,
26 26 collapsed=False
27 27 ))
28 28
29 29 ws.cells.append(new_text_cell(
30 30 u'markdown',
31 31 source='A random array',
32 32 rendered='A random array'
33 33 ))
34 34
35 ws.cells.append(new_text_cell(
36 u'rst',
37 source='A random array',
38 ))
39
40 ws.cells.append(new_heading_cell(
41 u'My Heading',
42 level=2
43 ))
44
35 45 ws.cells.append(new_code_cell(
36 46 input='a = numpy.random.rand(100)',
37 47 prompt_number=2,
38 48 collapsed=True
39 49 ))
40 50
41 51 ws.cells.append(new_code_cell(
42 52 input='print a',
43 53 prompt_number=3,
44 54 collapsed=False,
45 55 outputs=[new_output(
46 56 output_type=u'pyout',
47 57 output_text=u'<array a>',
48 58 output_html=u'The HTML rep',
49 59 output_latex=u'$a$',
50 60 output_png=png,
51 61 output_jpeg=jpeg,
52 62 output_svg=u'<svg>',
53 63 output_json=u'json data',
54 64 output_javascript=u'var i=0;',
55 65 prompt_number=3
56 66 ),new_output(
57 67 output_type=u'display_data',
58 68 output_text=u'<array a>',
59 69 output_html=u'The HTML rep',
60 70 output_latex=u'$a$',
61 71 output_png=png,
62 72 output_jpeg=jpeg,
63 73 output_svg=u'<svg>',
64 74 output_json=u'json data',
65 75 output_javascript=u'var i=0;'
66 76 ),new_output(
67 77 output_type=u'pyerr',
68 78 etype=u'NameError',
69 79 evalue=u'NameError was here',
70 80 traceback=[u'frame 0', u'frame 1', u'frame 2']
71 81 )]
72 82 ))
73 83
74 84 authors = [new_author(name='Bart Simpson',email='bsimpson@fox.com',
75 85 affiliation=u'Fox',url=u'http://www.fox.com')]
76 86 md = new_metadata(name=u'My Notebook',license=u'BSD',created=u'8601_goes_here',
77 87 modified=u'8601_goes_here',gistid=u'21341231',authors=authors)
78 88
79 89 nb0 = new_notebook(
80 90 worksheets=[ws, new_worksheet(name='worksheet2')],
81 91 metadata=md
82 92 )
83 93
84 94 nb0_py = """# -*- coding: utf-8 -*-
85 95 # <nbformat>2</nbformat>
86 96
87 97 # <htmlcell>
88 98
89 99 # Some NumPy Examples
90 100
91 101 # <codecell>
92 102
93 103 import numpy
94 104
95 105 # <markdowncell>
96 106
97 107 # A random array
98 108
109 # <rstcell>
110
111 # A random array
112
113 # <headingcell level=2>
114
115 # My Heading
116
99 117 # <codecell>
100 118
101 119 a = numpy.random.rand(100)
102 120
103 121 # <codecell>
104 122
105 123 print a
106 124
107 125 """
108 126
109 127
@@ -1,34 +1,34 b''
1 1 import pprint
2 2 from unittest import TestCase
3 3
4 4 from ..nbjson import reads, writes
5 5 from .nbexamples import nb0
6 6
7 7
8 8 class TestJSON(TestCase):
9 9
10 10 def test_roundtrip(self):
11 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
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 18 self.assertEquals(reads(s),nb0)
19 19
20 20 def test_roundtrip_nosplit(self):
21 21 """Ensure that multiline blobs are still readable"""
22 22 # ensures that notebooks written prior to splitlines change
23 23 # are still readable.
24 24 s = writes(nb0, split_lines=False)
25 25 self.assertEquals(reads(s),nb0)
26 26
27 27 def test_roundtrip_split(self):
28 28 """Ensure that splitting multiline blocks is safe"""
29 29 # This won't differ from test_roundtrip unless the default changes
30 30 s = writes(nb0, split_lines=True)
31 31 self.assertEquals(reads(s),nb0)
32 32
33 33
34 34
@@ -1,113 +1,134 b''
1 1 from unittest import TestCase
2 2
3 3 from ..nbbase import (
4 4 NotebookNode,
5 5 new_code_cell, new_text_cell, new_worksheet, new_notebook, new_output,
6 new_author, new_metadata
6 new_author, new_metadata, new_heading_cell
7 7 )
8 8
9 9 class TestCell(TestCase):
10 10
11 11 def test_empty_code_cell(self):
12 12 cc = new_code_cell()
13 13 self.assertEquals(cc.cell_type,u'code')
14 14 self.assertEquals(u'input' not in cc, True)
15 15 self.assertEquals(u'prompt_number' not in cc, True)
16 16 self.assertEquals(cc.outputs, [])
17 17 self.assertEquals(cc.collapsed, False)
18 18
19 19 def test_code_cell(self):
20 20 cc = new_code_cell(input='a=10', prompt_number=0, collapsed=True)
21 21 cc.outputs = [new_output(output_type=u'pyout',
22 22 output_svg=u'foo',output_text=u'10',prompt_number=0)]
23 23 self.assertEquals(cc.input, u'a=10')
24 24 self.assertEquals(cc.prompt_number, 0)
25 25 self.assertEquals(cc.language, u'python')
26 26 self.assertEquals(cc.outputs[0].svg, u'foo')
27 27 self.assertEquals(cc.outputs[0].text, u'10')
28 28 self.assertEquals(cc.outputs[0].prompt_number, 0)
29 29 self.assertEquals(cc.collapsed, True)
30 30
31 31 def test_pyerr(self):
32 32 o = new_output(output_type=u'pyerr', etype=u'NameError',
33 33 evalue=u'Name not found', traceback=[u'frame 0', u'frame 1', u'frame 2']
34 34 )
35 35 self.assertEquals(o.output_type, u'pyerr')
36 36 self.assertEquals(o.etype, u'NameError')
37 37 self.assertEquals(o.evalue, u'Name not found')
38 38 self.assertEquals(o.traceback, [u'frame 0', u'frame 1', u'frame 2'])
39 39
40 40 def test_empty_html_cell(self):
41 41 tc = new_text_cell(u'html')
42 42 self.assertEquals(tc.cell_type, u'html')
43 43 self.assertEquals(u'source' not in tc, True)
44 44 self.assertEquals(u'rendered' not in tc, True)
45 45
46 46 def test_html_cell(self):
47 47 tc = new_text_cell(u'html', 'hi', 'hi')
48 48 self.assertEquals(tc.source, u'hi')
49 49 self.assertEquals(tc.rendered, u'hi')
50 50
51 51 def test_empty_markdown_cell(self):
52 52 tc = new_text_cell(u'markdown')
53 53 self.assertEquals(tc.cell_type, u'markdown')
54 54 self.assertEquals(u'source' not in tc, True)
55 55 self.assertEquals(u'rendered' not in tc, True)
56 56
57 57 def test_markdown_cell(self):
58 58 tc = new_text_cell(u'markdown', 'hi', 'hi')
59 59 self.assertEquals(tc.source, u'hi')
60 60 self.assertEquals(tc.rendered, u'hi')
61 61
62 def test_empty_rst_cell(self):
63 tc = new_text_cell(u'rst')
64 self.assertEquals(tc.cell_type, u'rst')
65 self.assertEquals(u'source' not in tc, True)
66 self.assertEquals(u'rendered' not in tc, True)
67
68 def test_rst_cell(self):
69 tc = new_text_cell(u'rst', '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
78 def test_heading_cell(self):
79 tc = new_heading_cell(u'My Heading', level=2)
80 self.assertEquals(tc.source, u'My Heading')
81 self.assertEquals(tc.level, 2)
82
62 83
63 84 class TestWorksheet(TestCase):
64 85
65 86 def test_empty_worksheet(self):
66 87 ws = new_worksheet()
67 88 self.assertEquals(ws.cells,[])
68 89 self.assertEquals(u'name' not in ws, True)
69 90
70 91 def test_worksheet(self):
71 92 cells = [new_code_cell(), new_text_cell(u'html')]
72 93 ws = new_worksheet(cells=cells,name=u'foo')
73 94 self.assertEquals(ws.cells,cells)
74 95 self.assertEquals(ws.name,u'foo')
75 96
76 97 class TestNotebook(TestCase):
77 98
78 99 def test_empty_notebook(self):
79 100 nb = new_notebook()
80 101 self.assertEquals(nb.worksheets, [])
81 102 self.assertEquals(nb.metadata, NotebookNode())
82 103 self.assertEquals(nb.nbformat,2)
83 104
84 105 def test_notebook(self):
85 106 worksheets = [new_worksheet(),new_worksheet()]
86 107 metadata = new_metadata(name=u'foo')
87 108 nb = new_notebook(metadata=metadata,worksheets=worksheets)
88 109 self.assertEquals(nb.metadata.name,u'foo')
89 110 self.assertEquals(nb.worksheets,worksheets)
90 111 self.assertEquals(nb.nbformat,2)
91 112
92 113 class TestMetadata(TestCase):
93 114
94 115 def test_empty_metadata(self):
95 116 md = new_metadata()
96 117 self.assertEquals(u'name' not in md, True)
97 118 self.assertEquals(u'authors' not in md, True)
98 119 self.assertEquals(u'license' not in md, True)
99 120 self.assertEquals(u'saved' not in md, True)
100 121 self.assertEquals(u'modified' not in md, True)
101 122 self.assertEquals(u'gistid' not in md, True)
102 123
103 124 def test_metadata(self):
104 125 authors = [new_author(name='Bart Simpson',email='bsimpson@fox.com')]
105 126 md = new_metadata(name=u'foo',license=u'BSD',created=u'today',
106 127 modified=u'now',gistid=u'21341231',authors=authors)
107 128 self.assertEquals(md.name, u'foo')
108 129 self.assertEquals(md.license, u'BSD')
109 130 self.assertEquals(md.created, u'today')
110 131 self.assertEquals(md.modified, u'now')
111 132 self.assertEquals(md.gistid, u'21341231')
112 133 self.assertEquals(md.authors, authors)
113 134
General Comments 0
You need to be logged in to leave comments. Login now