From 68687d2ed8a1aa6028d6a4ecb7aed856a243fbb3 2011-07-27 20:04:22 From: Brian E. Granger Date: 2011-07-27 20:04:22 Subject: [PATCH] Adding nbformat subpackage. --- diff --git a/IPython/nbformat/__init__.py b/IPython/nbformat/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/IPython/nbformat/__init__.py diff --git a/IPython/nbformat/base.py b/IPython/nbformat/base.py new file mode 100644 index 0000000..833a5ec --- /dev/null +++ b/IPython/nbformat/base.py @@ -0,0 +1,45 @@ +from base64 import encodestring, decodestring + + +def base64_decode(self, nb): + """Base64 encode all bytes objects in the notebook.""" + for ws in nb['worksheets']: + for cell in ws['cells']: + if cell['cell_type'] == 'code': + if cell.get('image/png',''): + cell['image/png'] = bytes(decodestring(cell['image/png'])) + return nb + + +def base64_encode(self, nb): + """Base64 decode all binary objects in the notebook.""" + for ws in nb['worksheets']: + for cell in ws['cells']: + if cell['cell_type'] == 'code': + if cell.get('image/png',''): + cell['image/png'] = unicode(encodestring(cell['image/png'])) + return nb + + +class NotebookReader(object): + + def reads(self, s, **kwargs): + """Read a notebook from a string.""" + raise NotImplementedError("loads must be implemented in a subclass") + + def read(self, fp, **kwargs): + """Read a notebook from a file like object""" + return self.loads(fp.read(), **kwargs) + + +class NotebookWriter(object): + + def writes(self, nb, **kwargs): + """Write a notebook to a string.""" + raise NotImplementedError("loads must be implemented in a subclass") + + def write(self, nb, fp, **kwargs): + """Write a notebook to a file like object""" + return fp.write(self.dumps(nb,**kwargs)) + + diff --git a/IPython/nbformat/nbdict.py b/IPython/nbformat/nbdict.py new file mode 100644 index 0000000..fa2900d --- /dev/null +++ b/IPython/nbformat/nbdict.py @@ -0,0 +1,76 @@ +"""The basic dict based notebook format.""" + +import uuid + + +def new_code_cell(input=None, prompt_number=None, output_text=None, output_png=None, + output_html=None, output_svg=None, output_latex=None, output_json=None, + output_javascript=None): + """Create a new code cell with input and output""" + cell = {} + cell['cell_type'] = 'code' + if input is not None: + cell['input'] = unicode(input) + if prompt_number is not None: + cell['prompt_number'] = int(prompt_number) + + output = {} + if output_text is not None: + output['text/plain'] = unicode(output_text) + if output_png is not None: + output['image/png'] = bytes(output_png) + if output_html is not None: + output['text/html'] = unicode(output_html) + if output_svg is not None: + output['image/svg+xml'] = unicode(output_svg) + if output_latex is not None: + output['text/latex'] = unicode(output_latex) + if output_json is not None: + output['application/json'] = unicode(output_json) + if output_javascript is not None: + output['application/javascript'] = unicode(output_javascript) + + cell['output'] = output + return cell + + +def new_text_cell(text=None): + """Create a new text cell.""" + cell = {} + if text is not None: + cell['text'] = unicode(text) + cell['cell_type'] = 'text' + return cell + + +def new_worksheet(name=None, cells=None): + """Create a worksheet by name with with a list of cells.""" + ws = {} + if name is not None: + ws['name'] = unicode(name) + else: + ws['name'] = u'' + if cells is None: + ws['cells'] = [] + else: + ws['cells'] = list(cells) + return ws + + +def new_notebook(name=None, id=None, worksheets=None): + """Create a notebook by name, id and a list of worksheets.""" + nb = {} + if name is not None: + nb['name'] = unicode(name) + else: + nb['name'] = u'' + if id is None: + nb['id'] = unicode(uuid.uuid4()) + else: + nb['id'] = unicode(id) + if worksheets is None: + nb['worksheets'] = [] + else: + nb['worksheets'] = list(worksheets) + return nb + diff --git a/IPython/nbformat/nbjson.py b/IPython/nbformat/nbjson.py new file mode 100644 index 0000000..00b8582 --- /dev/null +++ b/IPython/nbformat/nbjson.py @@ -0,0 +1,38 @@ +"""Read and write notebooks in JSON format.""" + +from base64 import encodestring +from .base import NotebookReader, NotebookWriter, base64_decode +import json + + +class BytesEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, bytes): + return unicode(encodestring(bytes)) + return json.JSONEncoder.default(self, obj) + + +class JSONReader(NotebookReader): + + def reads(s, **kwargs): + nb = json.loads(s, **kwargs) + nb = base64_decode(nb) + return nb + + +class JSONWriter(NotebookWriter): + + def writes(nb, **kwargs): + kwargs['cls'] = BytesEncoder + kwargs['indent'] = 4 + return json.dumps(nb, **kwargs) + + +_reader = JSONReader() +_writer = JSONWriter() + +reads = _reader.reads +read = _reader.read +write = _writer.write +writes = _writer.writes + diff --git a/IPython/nbformat/nbpy.py b/IPython/nbformat/nbpy.py new file mode 100644 index 0000000..a5328e7 --- /dev/null +++ b/IPython/nbformat/nbpy.py @@ -0,0 +1,46 @@ +"""Read and write notebooks as regular .py files.""" + +from .base import NotebookReader, NotebookWriter +from .nbdict import new_code_cell, new_worksheet, new_notebook + + +class PyReader(NotebookReader): + + def reads(s, **kwargs): + lines = s.splitlines() + cells = [] + cell_lines = [] + for line in lines: + if line.startswith('# '): + code = '\n'.join(cell_lines) + code = code.strip('\n') + if code: + cells.append(new_code_cell(input=code)) + cell_lines = [] + else: + cell_lines.append(line) + ws = new_worksheet(cells=cells) + nb = new_notebook(worksheets=[ws]) + return nb + + +class PyWriter(NotebookWriter): + + def writes(nb, **kwargs): + lines = [] + for ws in nb['worksheets']: + for cell in ws['cells']: + if cell['cell_type'] == 'code': + input = cell['input'] + lines.extend(input.splitlines()) + lines.extend(['','# ','']) + return ''.join(lines) + + +_reader = PyReader() +_writer = PyWriter() + +reads = _reader.reads +read = _reader.read +write = _writer.write +writes = _writer.writes diff --git a/IPython/nbformat/nbxml.py b/IPython/nbformat/nbxml.py new file mode 100644 index 0000000..aa22f3f --- /dev/null +++ b/IPython/nbformat/nbxml.py @@ -0,0 +1,48 @@ +"""Read and write notebook files as XML.""" + +from xml.etree import ElementTree as ET + +from .base import NotebookReader, NotebookWriter +from .nbdict import new_code_cell, new_worksheet, new_notebook + + +class XMLReader(NotebookReader): + + def reads(s, **kwargs): + pass + + +class XMLWriter(NotebookWriter): + + def writes(nb, **kwargs): + nb_e = ET.Element('notebook') + name_e = ET.SubElement(nb_e, 'name') + name_e.text = nb.get('name','') + id_e = ET.SubElement(nb_e, 'id') + id_e.text = nb.get('id','') + for ws in nb['worksheets']: + ws_e = ET.SubElement(nb_e, 'worksheet') + ws_name_e = ET.SubElement(ws_e, 'name') + ws_name_e.text = ws.get('name','') + for cell in ws['cells']: + cell_type = cell['cell_type'] + if cell_type == 'code': + output = cell['output'] + cell_e = ET.SubElement(ws_e, 'cell') + input_e = ET.SubElement(cell_e, 'input') + input_e.text = cell.get('input','') + output_e = ET.SubElement(cell_e, 'output') + text_e = ET.SubElement(output_e, 'text') + text_e.text = cell.output + elif cell_type == 'text': + pass + + + +_reader = XMLReader() +_writer = XMLWriter() + +reads = _reader.reads +read = _reader.read +write = _writer.write +writes = _writer.writes