##// END OF EJS Templates
Initial draft of more formal notebook format....
Brian E. Granger -
Show More
1 NO CONTENT: new file 100644
@@ -0,0 +1,52 b''
1 from IPython.nbformat.nbbase import (
2 NotebookNode,
3 new_code_cell, new_text_cell, new_worksheet, new_notebook
4 )
5
6
7
8 ws = new_worksheet(name='worksheet1')
9
10 ws.cells.append(new_text_cell(
11 text='Some NumPy Examples'
12 ))
13
14
15 ws.cells.append(new_code_cell(
16 input='import numpy'
17 ))
18
19 ws.cells.append(new_code_cell(
20 input='a = numpy.random.rand(100)'
21 ))
22
23 ws.cells.append(new_code_cell(
24 input='print a',
25 output_text='<array a>',
26 output_html='The HTML rep',
27 output_latex='$a$',
28 output_png=b'data',
29 output_svg='<svg>',
30 output_json='json data',
31 output_javascript='var i=0;'
32 ))
33
34 nb0 = new_notebook(
35 name='nb0',
36 worksheets=[ws, new_worksheet(name='worksheet2')]
37 )
38
39 nb0_py = """# <codecell>
40
41 import numpy
42
43 # <codecell>
44
45 a = numpy.random.rand(100)
46
47 # <codecell>
48
49 print a
50 """
51
52
@@ -0,0 +1,14 b''
1 from unittest import TestCase
2
3 from IPython.nbformat.nbjson import reads, writes
4 from IPython.nbformat.tests.nbexamples import nb0
5
6
7 class TestJSON(TestCase):
8
9 def test_roundtrip(self):
10 s = writes(nb0)
11 self.assertEquals(reads(s),nb0)
12
13
14
@@ -0,0 +1,60 b''
1 from unittest import TestCase
2
3 from IPython.nbformat.nbbase import (
4 NotebookNode,
5 new_code_cell, new_text_cell, new_worksheet, new_notebook
6 )
7
8 class TestCell(TestCase):
9
10 def test_empty_code_cell(self):
11 cc = new_code_cell()
12 self.assertEquals(cc.cell_type,'code')
13 self.assertEquals('input' not in cc, True)
14 self.assertEquals('prompt_number' not in cc, True)
15 self.assertEquals(cc.output, NotebookNode())
16
17 def test_code_cell(self):
18 cc = new_code_cell(input='a=10', prompt_number=0, output_svg='foo', output_text='10')
19 self.assertEquals(cc.input, u'a=10')
20 self.assertEquals(cc.prompt_number, 0)
21 self.assertEquals(cc.output.svg, u'foo')
22 self.assertEquals(cc.output.text, u'10')
23
24 def test_empty_text_cell(self):
25 tc = new_text_cell()
26 self.assertEquals(tc.cell_type, 'text')
27 self.assertEquals('text' not in tc, True)
28
29 def test_text_cell(self):
30 tc = new_text_cell('hi')
31 self.assertEquals(tc.text, u'hi')
32
33
34 class TestWorksheet(TestCase):
35
36 def test_empty_worksheet(self):
37 ws = new_worksheet()
38 self.assertEquals(ws.cells,[])
39 self.assertEquals('name' not in ws, True)
40
41 def test_worksheet(self):
42 cells = [new_code_cell(), new_text_cell()]
43 ws = new_worksheet(cells=cells,name='foo')
44 self.assertEquals(ws.cells,cells)
45 self.assertEquals(ws.name,u'foo')
46
47 class TestNotebook(TestCase):
48
49 def test_empty_notebook(self):
50 nb = new_notebook()
51 self.assertEquals('id' in nb, True)
52 self.assertEquals(nb.worksheets, [])
53 self.assertEquals('name' not in nb, True)
54
55 def test_notebooke(self):
56 worksheets = [new_worksheet(),new_worksheet()]
57 nb = new_notebook(name='foo',worksheets=worksheets)
58 self.assertEquals(nb.name,u'foo')
59 self.assertEquals(nb.worksheets,worksheets)
60
@@ -0,0 +1,18 b''
1 from unittest import TestCase
2
3 from IPython.nbformat.nbbase import (
4 NotebookNode,
5 new_code_cell, new_text_cell, new_worksheet, new_notebook
6 )
7
8 from IPython.nbformat.nbpy import reads, writes
9 from IPython.nbformat.tests.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
18
@@ -0,0 +1,12 b''
1 from unittest import TestCase
2
3 from IPython.nbformat.nbxml import reads, writes
4 from IPython.nbformat.tests.nbexamples import nb0
5
6
7 class TestXML(TestCase):
8
9 def test_roundtrip(self):
10 s = writes(nb0)
11 self.assertEquals(reads(s),nb0)
12
@@ -1,76 +1,79 b''
1 1 """The basic dict based notebook format."""
2 2
3 import pprint
3 4 import uuid
4 5
6 from IPython.utils.ipstruct import Struct
7
8
9 class NotebookNode(Struct):
10 pass
11
5 12
6 13 def new_code_cell(input=None, prompt_number=None, output_text=None, output_png=None,
7 14 output_html=None, output_svg=None, output_latex=None, output_json=None,
8 15 output_javascript=None):
9 16 """Create a new code cell with input and output"""
10 cell = {}
11 cell['cell_type'] = 'code'
17 cell = NotebookNode()
18 cell.cell_type = 'code'
12 19 if input is not None:
13 cell['input'] = unicode(input)
20 cell.input = unicode(input)
14 21 if prompt_number is not None:
15 cell['prompt_number'] = int(prompt_number)
22 cell.prompt_number = int(prompt_number)
16 23
17 output = {}
24 output = NotebookNode()
18 25 if output_text is not None:
19 output['text/plain'] = unicode(output_text)
26 output.text = unicode(output_text)
20 27 if output_png is not None:
21 output['image/png'] = bytes(output_png)
28 output.png = bytes(output_png)
22 29 if output_html is not None:
23 output['text/html'] = unicode(output_html)
30 output.html = unicode(output_html)
24 31 if output_svg is not None:
25 output['image/svg+xml'] = unicode(output_svg)
32 output.svg = unicode(output_svg)
26 33 if output_latex is not None:
27 output['text/latex'] = unicode(output_latex)
34 output.latex = unicode(output_latex)
28 35 if output_json is not None:
29 output['application/json'] = unicode(output_json)
36 output.json = unicode(output_json)
30 37 if output_javascript is not None:
31 output['application/javascript'] = unicode(output_javascript)
38 output.javascript = unicode(output_javascript)
32 39
33 cell['output'] = output
40 cell.output = output
34 41 return cell
35 42
36 43
37 44 def new_text_cell(text=None):
38 45 """Create a new text cell."""
39 cell = {}
46 cell = NotebookNode()
40 47 if text is not None:
41 cell['text'] = unicode(text)
42 cell['cell_type'] = 'text'
48 cell.text = unicode(text)
49 cell.cell_type = 'text'
43 50 return cell
44 51
45 52
46 53 def new_worksheet(name=None, cells=None):
47 54 """Create a worksheet by name with with a list of cells."""
48 ws = {}
55 ws = NotebookNode()
49 56 if name is not None:
50 ws['name'] = unicode(name)
51 else:
52 ws['name'] = u''
57 ws.name = unicode(name)
53 58 if cells is None:
54 ws['cells'] = []
59 ws.cells = []
55 60 else:
56 ws['cells'] = list(cells)
61 ws.cells = list(cells)
57 62 return ws
58 63
59 64
60 65 def new_notebook(name=None, id=None, worksheets=None):
61 66 """Create a notebook by name, id and a list of worksheets."""
62 nb = {}
67 nb = NotebookNode()
63 68 if name is not None:
64 nb['name'] = unicode(name)
65 else:
66 nb['name'] = u''
69 nb.name = unicode(name)
67 70 if id is None:
68 nb['id'] = unicode(uuid.uuid4())
71 nb.id = unicode(uuid.uuid4())
69 72 else:
70 nb['id'] = unicode(id)
73 nb.id = unicode(id)
71 74 if worksheets is None:
72 nb['worksheets'] = []
75 nb.worksheets = []
73 76 else:
74 nb['worksheets'] = list(worksheets)
77 nb.worksheets = list(worksheets)
75 78 return nb
76 79
@@ -1,7 +1,7 b''
1 1 """Read and write notebooks in JSON format."""
2 2
3 3 from base64 import encodestring
4 from .base import NotebookReader, NotebookWriter, base64_decode
4 from .rwbase import NotebookReader, NotebookWriter, base64_decode
5 5 import json
6 6
7 7
@@ -14,7 +14,7 b' class BytesEncoder(json.JSONEncoder):'
14 14
15 15 class JSONReader(NotebookReader):
16 16
17 def reads(s, **kwargs):
17 def reads(self, s, **kwargs):
18 18 nb = json.loads(s, **kwargs)
19 19 nb = base64_decode(nb)
20 20 return nb
@@ -22,7 +22,7 b' class JSONReader(NotebookReader):'
22 22
23 23 class JSONWriter(NotebookWriter):
24 24
25 def writes(nb, **kwargs):
25 def writes(self, nb, **kwargs):
26 26 kwargs['cls'] = BytesEncoder
27 27 kwargs['indent'] = 4
28 28 return json.dumps(nb, **kwargs)
@@ -1,19 +1,19 b''
1 1 """Read and write notebooks as regular .py files."""
2 2
3 from .base import NotebookReader, NotebookWriter
4 from .nbdict import new_code_cell, new_worksheet, new_notebook
3 from .rwbase import NotebookReader, NotebookWriter
4 from .nbbase import new_code_cell, new_worksheet, new_notebook
5 5
6 6
7 7 class PyReader(NotebookReader):
8 8
9 def reads(s, **kwargs):
9 def reads(self, s, **kwargs):
10 10 lines = s.splitlines()
11 11 cells = []
12 12 cell_lines = []
13 13 for line in lines:
14 if line.startswith('# <codecell>'):
15 code = '\n'.join(cell_lines)
16 code = code.strip('\n')
14 if line.startswith(u'# <codecell>'):
15 code = u'\n'.join(cell_lines)
16 code = code.strip(u'\n')
17 17 if code:
18 18 cells.append(new_code_cell(input=code))
19 19 cell_lines = []
@@ -26,15 +26,16 b' class PyReader(NotebookReader):'
26 26
27 27 class PyWriter(NotebookWriter):
28 28
29 def writes(nb, **kwargs):
29 def writes(self, nb, **kwargs):
30 30 lines = []
31 for ws in nb['worksheets']:
32 for cell in ws['cells']:
33 if cell['cell_type'] == 'code':
34 input = cell['input']
31 for ws in nb.worksheets:
32 for cell in ws.cells:
33 if cell.cell_type == 'code':
34 input = cell.input
35 lines.extend([u'# <codecell>',u''])
35 36 lines.extend(input.splitlines())
36 lines.extend(['','# <codecell>',''])
37 return ''.join(lines)
37 lines.append(u'')
38 return unicode('\n'.join(lines))
38 39
39 40
40 41 _reader = PyReader()
@@ -2,41 +2,134 b''
2 2
3 3 from xml.etree import ElementTree as ET
4 4
5 from .base import NotebookReader, NotebookWriter
6 from .nbdict import new_code_cell, new_worksheet, new_notebook
5 from .rwbase import NotebookReader, NotebookWriter
6 from .nbbase import new_code_cell, new_text_cell, new_worksheet, new_notebook
7
8
9 def indent(elem, level=0):
10 i = "\n" + level*" "
11 if len(elem):
12 if not elem.text or not elem.text.strip():
13 elem.text = i + " "
14 if not elem.tail or not elem.tail.strip():
15 elem.tail = i
16 for elem in elem:
17 indent(elem, level+1)
18 if not elem.tail or not elem.tail.strip():
19 elem.tail = i
20 else:
21 if level and (not elem.tail or not elem.tail.strip()):
22 elem.tail = i
23
24
25 def _get_text(e, tag):
26 sub_e = e.find(tag)
27 if sub_e is None:
28 return None
29 else:
30 return sub_e.text
7 31
8 32
9 33 class XMLReader(NotebookReader):
10 34
11 def reads(s, **kwargs):
12 pass
35 def reads(self, s, **kwargs):
36 root = ET.fromstring(s)
37
38 nbname = _get_text(root,'name')
39 nbid = _get_text(root,'id')
40
41 worksheets = []
42 for ws_e in root.getiterator('worksheet'):
43 wsname = _get_text(ws_e,'name')
44 cells = []
45 for cell_e in ws_e.getiterator():
46 if cell_e.tag == 'codecell':
47 input = _get_text(cell_e,'input')
48 output_e = cell_e.find('output')
49 if output_e is not None:
50 output_text = _get_text(output_e,'text')
51 output_png = _get_text(output_e,'png')
52 output_svg = _get_text(output_e,'svg')
53 output_html = _get_text(output_e,'html')
54 output_latex = _get_text(output_e,'latex')
55 output_json = _get_text(output_e,'json')
56 output_javascript = _get_text(output_e,'javascript')
57 cc = new_code_cell(input=input,output_png=output_png,
58 output_text=output_text,output_svg=output_svg,
59 output_html=output_html,output_latex=output_latex,
60 output_json=output_json,output_javascript=output_javascript
61 )
62 cells.append(cc)
63 if cell_e.tag == 'textcell':
64 text = _get_text(cell_e,'text')
65 cells.append(new_text_cell(text=text))
66 ws = new_worksheet(name=wsname,cells=cells)
67 worksheets.append(ws)
68
69 nb = new_notebook(name=nbname,id=nbid,worksheets=worksheets)
70 return nb
13 71
14 72
15 73 class XMLWriter(NotebookWriter):
16 74
17 def writes(nb, **kwargs):
75 def writes(self, nb, **kwargs):
18 76 nb_e = ET.Element('notebook')
77 if 'name' in nb:
19 78 name_e = ET.SubElement(nb_e, 'name')
20 name_e.text = nb.get('name','')
79 name_e.text = nb.name
80 if 'id' in nb:
21 81 id_e = ET.SubElement(nb_e, 'id')
22 id_e.text = nb.get('id','')
23 for ws in nb['worksheets']:
82 id_e.text = nb.id
83 for ws in nb.worksheets:
24 84 ws_e = ET.SubElement(nb_e, 'worksheet')
85 if 'name' in ws:
25 86 ws_name_e = ET.SubElement(ws_e, 'name')
26 ws_name_e.text = ws.get('name','')
27 for cell in ws['cells']:
28 cell_type = cell['cell_type']
87 ws_name_e.text = ws.name
88 for cell in ws.cells:
89 cell_type = cell.cell_type
29 90 if cell_type == 'code':
30 output = cell['output']
31 cell_e = ET.SubElement(ws_e, 'cell')
32 input_e = ET.SubElement(cell_e, 'input')
33 input_e.text = cell.get('input','')
91 output = cell.output
92 cell_e = ET.SubElement(ws_e, 'codecell')
34 93 output_e = ET.SubElement(cell_e, 'output')
94
95 if 'input' in cell:
96 input_e = ET.SubElement(cell_e, 'input')
97 input_e.text = cell.input
98 if 'prompt_number' in cell:
99 prompt_number_e = ET.SubElement(cell_e, 'prompt_number')
100 input_e.text = cell.prompt_number
101
102 if 'text' in output:
35 103 text_e = ET.SubElement(output_e, 'text')
36 text_e.text = cell.output
104 text_e.text = output.text
105 if 'png' in output:
106 png_e = ET.SubElement(output_e, 'png')
107 png_e.text = output.png
108 if 'html' in output:
109 html_e = ET.SubElement(output_e, 'html')
110 html_e.text = output.html
111 if 'svg' in output:
112 svg_e = ET.SubElement(output_e, 'svg')
113 svg_e.text = output.svg
114 if 'latex' in output:
115 latex_e = ET.SubElement(output_e, 'latex')
116 latex_e.text = output.latex
117 if 'json' in output:
118 json_e = ET.SubElement(output_e, 'json')
119 json_e.text = output.json
120 if 'javascript' in output:
121 javascript_e = ET.SubElement(output_e, 'javascript')
122 javascript_e.text = output.javascript
37 123 elif cell_type == 'text':
38 pass
124 cell_e = ET.SubElement(ws_e, 'textcell')
125 if 'text' in cell:
126 cell_text_e = ET.SubElement(cell_e, 'text')
127 cell_text_e.text = cell.text
39 128
129 indent(nb_e)
130 txt = ET.tostring(nb_e, encoding="utf-8")
131 txt = '<?xml version="1.0" encoding="utf-8"?>\n' + txt
132 return txt
40 133
41 134
42 135 _reader = XMLReader()
@@ -1,7 +1,7 b''
1 1 from base64 import encodestring, decodestring
2 2
3 3
4 def base64_decode(self, nb):
4 def base64_decode(nb):
5 5 """Base64 encode all bytes objects in the notebook."""
6 6 for ws in nb['worksheets']:
7 7 for cell in ws['cells']:
@@ -11,7 +11,7 b' def base64_decode(self, nb):'
11 11 return nb
12 12
13 13
14 def base64_encode(self, nb):
14 def base64_encode(nb):
15 15 """Base64 decode all binary objects in the notebook."""
16 16 for ws in nb['worksheets']:
17 17 for cell in ws['cells']:
@@ -43,3 +43,4 b' class NotebookWriter(object):'
43 43 return fp.write(self.dumps(nb,**kwargs))
44 44
45 45
46
General Comments 0
You need to be logged in to leave comments. Login now