##// END OF EJS Templates
Initial draft of more formal notebook format....
Brian E. Granger -
Show More
1 NO CONTENT: new file 100644
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 """The basic dict based notebook format."""
1 """The basic dict based notebook format."""
2
2
3 import pprint
3 import uuid
4 import uuid
4
5
6 from IPython.utils.ipstruct import Struct
7
8
9 class NotebookNode(Struct):
10 pass
11
5
12
6 def new_code_cell(input=None, prompt_number=None, output_text=None, output_png=None,
13 def new_code_cell(input=None, prompt_number=None, output_text=None, output_png=None,
7 output_html=None, output_svg=None, output_latex=None, output_json=None,
14 output_html=None, output_svg=None, output_latex=None, output_json=None,
8 output_javascript=None):
15 output_javascript=None):
9 """Create a new code cell with input and output"""
16 """Create a new code cell with input and output"""
10 cell = {}
17 cell = NotebookNode()
11 cell['cell_type'] = 'code'
18 cell.cell_type = 'code'
12 if input is not None:
19 if input is not None:
13 cell['input'] = unicode(input)
20 cell.input = unicode(input)
14 if prompt_number is not None:
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 if output_text is not None:
25 if output_text is not None:
19 output['text/plain'] = unicode(output_text)
26 output.text = unicode(output_text)
20 if output_png is not None:
27 if output_png is not None:
21 output['image/png'] = bytes(output_png)
28 output.png = bytes(output_png)
22 if output_html is not None:
29 if output_html is not None:
23 output['text/html'] = unicode(output_html)
30 output.html = unicode(output_html)
24 if output_svg is not None:
31 if output_svg is not None:
25 output['image/svg+xml'] = unicode(output_svg)
32 output.svg = unicode(output_svg)
26 if output_latex is not None:
33 if output_latex is not None:
27 output['text/latex'] = unicode(output_latex)
34 output.latex = unicode(output_latex)
28 if output_json is not None:
35 if output_json is not None:
29 output['application/json'] = unicode(output_json)
36 output.json = unicode(output_json)
30 if output_javascript is not None:
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 return cell
41 return cell
35
42
36
43
37 def new_text_cell(text=None):
44 def new_text_cell(text=None):
38 """Create a new text cell."""
45 """Create a new text cell."""
39 cell = {}
46 cell = NotebookNode()
40 if text is not None:
47 if text is not None:
41 cell['text'] = unicode(text)
48 cell.text = unicode(text)
42 cell['cell_type'] = 'text'
49 cell.cell_type = 'text'
43 return cell
50 return cell
44
51
45
52
46 def new_worksheet(name=None, cells=None):
53 def new_worksheet(name=None, cells=None):
47 """Create a worksheet by name with with a list of cells."""
54 """Create a worksheet by name with with a list of cells."""
48 ws = {}
55 ws = NotebookNode()
49 if name is not None:
56 if name is not None:
50 ws['name'] = unicode(name)
57 ws.name = unicode(name)
51 else:
52 ws['name'] = u''
53 if cells is None:
58 if cells is None:
54 ws['cells'] = []
59 ws.cells = []
55 else:
60 else:
56 ws['cells'] = list(cells)
61 ws.cells = list(cells)
57 return ws
62 return ws
58
63
59
64
60 def new_notebook(name=None, id=None, worksheets=None):
65 def new_notebook(name=None, id=None, worksheets=None):
61 """Create a notebook by name, id and a list of worksheets."""
66 """Create a notebook by name, id and a list of worksheets."""
62 nb = {}
67 nb = NotebookNode()
63 if name is not None:
68 if name is not None:
64 nb['name'] = unicode(name)
69 nb.name = unicode(name)
65 else:
66 nb['name'] = u''
67 if id is None:
70 if id is None:
68 nb['id'] = unicode(uuid.uuid4())
71 nb.id = unicode(uuid.uuid4())
69 else:
72 else:
70 nb['id'] = unicode(id)
73 nb.id = unicode(id)
71 if worksheets is None:
74 if worksheets is None:
72 nb['worksheets'] = []
75 nb.worksheets = []
73 else:
76 else:
74 nb['worksheets'] = list(worksheets)
77 nb.worksheets = list(worksheets)
75 return nb
78 return nb
76
79
@@ -1,38 +1,38 b''
1 """Read and write notebooks in JSON format."""
1 """Read and write notebooks in JSON format."""
2
2
3 from base64 import encodestring
3 from base64 import encodestring
4 from .base import NotebookReader, NotebookWriter, base64_decode
4 from .rwbase import NotebookReader, NotebookWriter, base64_decode
5 import json
5 import json
6
6
7
7
8 class BytesEncoder(json.JSONEncoder):
8 class BytesEncoder(json.JSONEncoder):
9 def default(self, obj):
9 def default(self, obj):
10 if isinstance(obj, bytes):
10 if isinstance(obj, bytes):
11 return unicode(encodestring(bytes))
11 return unicode(encodestring(bytes))
12 return json.JSONEncoder.default(self, obj)
12 return json.JSONEncoder.default(self, obj)
13
13
14
14
15 class JSONReader(NotebookReader):
15 class JSONReader(NotebookReader):
16
16
17 def reads(s, **kwargs):
17 def reads(self, s, **kwargs):
18 nb = json.loads(s, **kwargs)
18 nb = json.loads(s, **kwargs)
19 nb = base64_decode(nb)
19 nb = base64_decode(nb)
20 return nb
20 return nb
21
21
22
22
23 class JSONWriter(NotebookWriter):
23 class JSONWriter(NotebookWriter):
24
24
25 def writes(nb, **kwargs):
25 def writes(self, nb, **kwargs):
26 kwargs['cls'] = BytesEncoder
26 kwargs['cls'] = BytesEncoder
27 kwargs['indent'] = 4
27 kwargs['indent'] = 4
28 return json.dumps(nb, **kwargs)
28 return json.dumps(nb, **kwargs)
29
29
30
30
31 _reader = JSONReader()
31 _reader = JSONReader()
32 _writer = JSONWriter()
32 _writer = JSONWriter()
33
33
34 reads = _reader.reads
34 reads = _reader.reads
35 read = _reader.read
35 read = _reader.read
36 write = _writer.write
36 write = _writer.write
37 writes = _writer.writes
37 writes = _writer.writes
38
38
@@ -1,46 +1,47 b''
1 """Read and write notebooks as regular .py files."""
1 """Read and write notebooks as regular .py files."""
2
2
3 from .base import NotebookReader, NotebookWriter
3 from .rwbase import NotebookReader, NotebookWriter
4 from .nbdict import new_code_cell, new_worksheet, new_notebook
4 from .nbbase import new_code_cell, new_worksheet, new_notebook
5
5
6
6
7 class PyReader(NotebookReader):
7 class PyReader(NotebookReader):
8
8
9 def reads(s, **kwargs):
9 def reads(self, s, **kwargs):
10 lines = s.splitlines()
10 lines = s.splitlines()
11 cells = []
11 cells = []
12 cell_lines = []
12 cell_lines = []
13 for line in lines:
13 for line in lines:
14 if line.startswith('# <codecell>'):
14 if line.startswith(u'# <codecell>'):
15 code = '\n'.join(cell_lines)
15 code = u'\n'.join(cell_lines)
16 code = code.strip('\n')
16 code = code.strip(u'\n')
17 if code:
17 if code:
18 cells.append(new_code_cell(input=code))
18 cells.append(new_code_cell(input=code))
19 cell_lines = []
19 cell_lines = []
20 else:
20 else:
21 cell_lines.append(line)
21 cell_lines.append(line)
22 ws = new_worksheet(cells=cells)
22 ws = new_worksheet(cells=cells)
23 nb = new_notebook(worksheets=[ws])
23 nb = new_notebook(worksheets=[ws])
24 return nb
24 return nb
25
25
26
26
27 class PyWriter(NotebookWriter):
27 class PyWriter(NotebookWriter):
28
28
29 def writes(nb, **kwargs):
29 def writes(self, nb, **kwargs):
30 lines = []
30 lines = []
31 for ws in nb['worksheets']:
31 for ws in nb.worksheets:
32 for cell in ws['cells']:
32 for cell in ws.cells:
33 if cell['cell_type'] == 'code':
33 if cell.cell_type == 'code':
34 input = cell['input']
34 input = cell.input
35 lines.extend([u'# <codecell>',u''])
35 lines.extend(input.splitlines())
36 lines.extend(input.splitlines())
36 lines.extend(['','# <codecell>',''])
37 lines.append(u'')
37 return ''.join(lines)
38 return unicode('\n'.join(lines))
38
39
39
40
40 _reader = PyReader()
41 _reader = PyReader()
41 _writer = PyWriter()
42 _writer = PyWriter()
42
43
43 reads = _reader.reads
44 reads = _reader.reads
44 read = _reader.read
45 read = _reader.read
45 write = _writer.write
46 write = _writer.write
46 writes = _writer.writes
47 writes = _writer.writes
@@ -1,48 +1,141 b''
1 """Read and write notebook files as XML."""
1 """Read and write notebook files as XML."""
2
2
3 from xml.etree import ElementTree as ET
3 from xml.etree import ElementTree as ET
4
4
5 from .base import NotebookReader, NotebookWriter
5 from .rwbase import NotebookReader, NotebookWriter
6 from .nbdict import new_code_cell, new_worksheet, new_notebook
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 class XMLReader(NotebookReader):
33 class XMLReader(NotebookReader):
10
34
11 def reads(s, **kwargs):
35 def reads(self, s, **kwargs):
12 pass
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 class XMLWriter(NotebookWriter):
73 class XMLWriter(NotebookWriter):
16
74
17 def writes(nb, **kwargs):
75 def writes(self, nb, **kwargs):
18 nb_e = ET.Element('notebook')
76 nb_e = ET.Element('notebook')
19 name_e = ET.SubElement(nb_e, 'name')
77 if 'name' in nb:
20 name_e.text = nb.get('name','')
78 name_e = ET.SubElement(nb_e, 'name')
21 id_e = ET.SubElement(nb_e, 'id')
79 name_e.text = nb.name
22 id_e.text = nb.get('id','')
80 if 'id' in nb:
23 for ws in nb['worksheets']:
81 id_e = ET.SubElement(nb_e, 'id')
82 id_e.text = nb.id
83 for ws in nb.worksheets:
24 ws_e = ET.SubElement(nb_e, 'worksheet')
84 ws_e = ET.SubElement(nb_e, 'worksheet')
25 ws_name_e = ET.SubElement(ws_e, 'name')
85 if 'name' in ws:
26 ws_name_e.text = ws.get('name','')
86 ws_name_e = ET.SubElement(ws_e, 'name')
27 for cell in ws['cells']:
87 ws_name_e.text = ws.name
28 cell_type = cell['cell_type']
88 for cell in ws.cells:
89 cell_type = cell.cell_type
29 if cell_type == 'code':
90 if cell_type == 'code':
30 output = cell['output']
91 output = cell.output
31 cell_e = ET.SubElement(ws_e, 'cell')
92 cell_e = ET.SubElement(ws_e, 'codecell')
32 input_e = ET.SubElement(cell_e, 'input')
33 input_e.text = cell.get('input','')
34 output_e = ET.SubElement(cell_e, 'output')
93 output_e = ET.SubElement(cell_e, 'output')
35 text_e = ET.SubElement(output_e, 'text')
36 text_e.text = cell.output
37 elif cell_type == 'text':
38 pass
39
40
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
41
101
102 if 'text' in output:
103 text_e = ET.SubElement(output_e, 'text')
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
123 elif cell_type == 'text':
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
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
133
134
42 _reader = XMLReader()
135 _reader = XMLReader()
43 _writer = XMLWriter()
136 _writer = XMLWriter()
44
137
45 reads = _reader.reads
138 reads = _reader.reads
46 read = _reader.read
139 read = _reader.read
47 write = _writer.write
140 write = _writer.write
48 writes = _writer.writes
141 writes = _writer.writes
@@ -1,45 +1,46 b''
1 from base64 import encodestring, decodestring
1 from base64 import encodestring, decodestring
2
2
3
3
4 def base64_decode(self, nb):
4 def base64_decode(nb):
5 """Base64 encode all bytes objects in the notebook."""
5 """Base64 encode all bytes objects in the notebook."""
6 for ws in nb['worksheets']:
6 for ws in nb['worksheets']:
7 for cell in ws['cells']:
7 for cell in ws['cells']:
8 if cell['cell_type'] == 'code':
8 if cell['cell_type'] == 'code':
9 if cell.get('image/png',''):
9 if cell.get('image/png',''):
10 cell['image/png'] = bytes(decodestring(cell['image/png']))
10 cell['image/png'] = bytes(decodestring(cell['image/png']))
11 return nb
11 return nb
12
12
13
13
14 def base64_encode(self, nb):
14 def base64_encode(nb):
15 """Base64 decode all binary objects in the notebook."""
15 """Base64 decode all binary objects in the notebook."""
16 for ws in nb['worksheets']:
16 for ws in nb['worksheets']:
17 for cell in ws['cells']:
17 for cell in ws['cells']:
18 if cell['cell_type'] == 'code':
18 if cell['cell_type'] == 'code':
19 if cell.get('image/png',''):
19 if cell.get('image/png',''):
20 cell['image/png'] = unicode(encodestring(cell['image/png']))
20 cell['image/png'] = unicode(encodestring(cell['image/png']))
21 return nb
21 return nb
22
22
23
23
24 class NotebookReader(object):
24 class NotebookReader(object):
25
25
26 def reads(self, s, **kwargs):
26 def reads(self, s, **kwargs):
27 """Read a notebook from a string."""
27 """Read a notebook from a string."""
28 raise NotImplementedError("loads must be implemented in a subclass")
28 raise NotImplementedError("loads must be implemented in a subclass")
29
29
30 def read(self, fp, **kwargs):
30 def read(self, fp, **kwargs):
31 """Read a notebook from a file like object"""
31 """Read a notebook from a file like object"""
32 return self.loads(fp.read(), **kwargs)
32 return self.loads(fp.read(), **kwargs)
33
33
34
34
35 class NotebookWriter(object):
35 class NotebookWriter(object):
36
36
37 def writes(self, nb, **kwargs):
37 def writes(self, nb, **kwargs):
38 """Write a notebook to a string."""
38 """Write a notebook to a string."""
39 raise NotImplementedError("loads must be implemented in a subclass")
39 raise NotImplementedError("loads must be implemented in a subclass")
40
40
41 def write(self, nb, fp, **kwargs):
41 def write(self, nb, fp, **kwargs):
42 """Write a notebook to a file like object"""
42 """Write a notebook to a file like object"""
43 return fp.write(self.dumps(nb,**kwargs))
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