nbpy.py
82 lines
| 2.6 KiB
| text/x-python
|
PythonLexer
Brian E. Granger
|
r4392 | """Read and write notebooks as regular .py files.""" | ||
Brian E. Granger
|
r4401 | from .rwbase import NotebookReader, NotebookWriter | ||
from .nbbase import new_code_cell, new_worksheet, new_notebook | ||||
Brian E. Granger
|
r4392 | |||
Brian E. Granger
|
r4493 | class PyReaderError(Exception): | ||
pass | ||||
Brian E. Granger
|
r4392 | class PyReader(NotebookReader): | ||
Brian E. Granger
|
r4401 | def reads(self, s, **kwargs): | ||
Brian E. Granger
|
r4406 | return self.to_notebook(s,**kwargs) | ||
def to_notebook(self, s, **kwargs): | ||||
Brian E. Granger
|
r4392 | lines = s.splitlines() | ||
cells = [] | ||||
cell_lines = [] | ||||
Brian E. Granger
|
r4493 | code_cell = False | ||
Brian E. Granger
|
r4392 | for line in lines: | ||
Brian E. Granger
|
r4401 | if line.startswith(u'# <codecell>'): | ||
Brian E. Granger
|
r4493 | if code_cell: | ||
raise PyReaderError('Unexpected <codecell>') | ||||
if cell_lines: | ||||
for block in self.split_lines_into_blocks(cell_lines): | ||||
cells.append(new_code_cell(input=block)) | ||||
Brian E. Granger
|
r4406 | cell_lines = [] | ||
Brian E. Granger
|
r4493 | code_cell = True | ||
Brian E. Granger
|
r4406 | if line.startswith(u'# </codecell>'): | ||
Brian E. Granger
|
r4493 | if not code_cell: | ||
raise PyReaderError('Unexpected </codecell>') | ||||
Brian E. Granger
|
r4401 | code = u'\n'.join(cell_lines) | ||
code = code.strip(u'\n') | ||||
Brian E. Granger
|
r4392 | if code: | ||
cells.append(new_code_cell(input=code)) | ||||
Brian E. Granger
|
r4493 | code_cell = False | ||
Brian E. Granger
|
r4392 | else: | ||
cell_lines.append(line) | ||||
Brian E. Granger
|
r4493 | # For lines we were not able to process, | ||
for block in self.split_lines_into_blocks(cell_lines): | ||||
cells.append(new_code_cell(input=block)) | ||||
Brian E. Granger
|
r4392 | ws = new_worksheet(cells=cells) | ||
nb = new_notebook(worksheets=[ws]) | ||||
return nb | ||||
Brian E. Granger
|
r4493 | def split_lines_into_blocks(self, lines): | ||
import ast | ||||
source = '\n'.join(lines) | ||||
code = ast.parse(source) | ||||
starts = [x.lineno-1 for x in code.body] | ||||
for i in range(len(starts)-1): | ||||
yield '\n'.join(lines[starts[i]:starts[i+1]]).strip('\n') | ||||
yield '\n'.join(lines[starts[-1]:]).strip('\n') | ||||
Brian E. Granger
|
r4392 | |||
class PyWriter(NotebookWriter): | ||||
Brian E. Granger
|
r4401 | def writes(self, nb, **kwargs): | ||
Brian E. Granger
|
r4392 | lines = [] | ||
Brian E. Granger
|
r4406 | lines.extend(['# <nbformat>2</nbformat>','']) | ||
Brian E. Granger
|
r4401 | for ws in nb.worksheets: | ||
for cell in ws.cells: | ||||
if cell.cell_type == 'code': | ||||
Brian E. Granger
|
r4484 | input = cell.get('input') | ||
if input is not None: | ||||
lines.extend([u'# <codecell>',u'']) | ||||
lines.extend(input.splitlines()) | ||||
lines.extend([u'',u'# </codecell>']) | ||||
Brian E. Granger
|
r4406 | lines.append('') | ||
Brian E. Granger
|
r4401 | return unicode('\n'.join(lines)) | ||
Brian E. Granger
|
r4392 | |||
_reader = PyReader() | ||||
_writer = PyWriter() | ||||
reads = _reader.reads | ||||
read = _reader.read | ||||
Brian E. Granger
|
r4406 | to_notebook = _reader.to_notebook | ||
Brian E. Granger
|
r4392 | write = _writer.write | ||
writes = _writer.writes | ||||
Brian E. Granger
|
r4406 | |||