Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/nbformat/v2/nbpy.py: 20%
111 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
1"""Read and write notebooks as regular .py files.
3Authors:
5* Brian Granger
6"""
8# -----------------------------------------------------------------------------
9# Copyright (C) 2008-2011 The IPython Development Team
10#
11# Distributed under the terms of the BSD License. The full license is in
12# the file LICENSE, distributed as part of this software.
13# -----------------------------------------------------------------------------
15# -----------------------------------------------------------------------------
16# Imports
17# -----------------------------------------------------------------------------
19import re
20from typing import List
22from .nbbase import new_code_cell, new_notebook, new_text_cell, new_worksheet
23from .rwbase import NotebookReader, NotebookWriter
25# -----------------------------------------------------------------------------
26# Code
27# -----------------------------------------------------------------------------
29_encoding_declaration_re = re.compile(r"^#.*coding[:=]\s*([-\w.]+)")
32class PyReaderError(Exception):
33 """An error raised by the PyReader."""
35 pass
38class PyReader(NotebookReader):
39 """A Python notebook reader."""
41 def reads(self, s, **kwargs):
42 """Convert a string to a notebook."""
43 return self.to_notebook(s, **kwargs)
45 def to_notebook(self, s, **kwargs): # noqa
46 """Convert a string to a notebook."""
47 lines = s.splitlines()
48 cells = []
49 cell_lines: List[str] = []
50 state = "codecell"
51 for line in lines:
52 if line.startswith("# <nbformat>") or _encoding_declaration_re.match(line):
53 pass
54 elif line.startswith("# <codecell>"):
55 cell = self.new_cell(state, cell_lines)
56 if cell is not None:
57 cells.append(cell)
58 state = "codecell"
59 cell_lines = []
60 elif line.startswith("# <htmlcell>"):
61 cell = self.new_cell(state, cell_lines)
62 if cell is not None:
63 cells.append(cell)
64 state = "htmlcell"
65 cell_lines = []
66 elif line.startswith("# <markdowncell>"):
67 cell = self.new_cell(state, cell_lines)
68 if cell is not None:
69 cells.append(cell)
70 state = "markdowncell"
71 cell_lines = []
72 else:
73 cell_lines.append(line)
74 if cell_lines and state == "codecell":
75 cell = self.new_cell(state, cell_lines)
76 if cell is not None:
77 cells.append(cell)
78 ws = new_worksheet(cells=cells)
79 nb = new_notebook(worksheets=[ws])
80 return nb
82 def new_cell(self, state, lines):
83 """Create a new cell."""
84 if state == "codecell":
85 input_ = "\n".join(lines)
86 input_ = input_.strip("\n")
87 if input_:
88 return new_code_cell(input=input_)
89 elif state == "htmlcell":
90 text = self._remove_comments(lines)
91 if text:
92 return new_text_cell("html", source=text)
93 elif state == "markdowncell":
94 text = self._remove_comments(lines)
95 if text:
96 return new_text_cell("markdown", source=text)
98 def _remove_comments(self, lines):
99 new_lines = []
100 for line in lines:
101 if line.startswith("#"):
102 new_lines.append(line[2:])
103 else:
104 new_lines.append(line)
105 text = "\n".join(new_lines)
106 text = text.strip("\n")
107 return text
109 def split_lines_into_blocks(self, lines):
110 """Split lines into code blocks."""
111 if len(lines) == 1:
112 yield lines[0]
113 raise StopIteration()
114 import ast
116 source = "\n".join(lines)
117 code = ast.parse(source)
118 starts = [x.lineno - 1 for x in code.body]
119 for i in range(len(starts) - 1):
120 yield "\n".join(lines[starts[i] : starts[i + 1]]).strip("\n")
121 yield "\n".join(lines[starts[-1] :]).strip("\n")
124class PyWriter(NotebookWriter):
125 """A Python notebook writer."""
127 def writes(self, nb, **kwargs):
128 """Convert a notebook object to a string."""
129 lines = ["# -*- coding: utf-8 -*-"]
130 lines.extend(["# <nbformat>2</nbformat>", ""])
131 for ws in nb.worksheets:
132 for cell in ws.cells:
133 if cell.cell_type == "code":
134 input_ = cell.get("input")
135 if input_ is not None:
136 lines.extend(["# <codecell>", ""])
137 lines.extend(input_.splitlines())
138 lines.append("")
139 elif cell.cell_type == "html":
140 input_ = cell.get("source")
141 if input_ is not None:
142 lines.extend(["# <htmlcell>", ""])
143 lines.extend(["# " + line for line in input_.splitlines()])
144 lines.append("")
145 elif cell.cell_type == "markdown":
146 input_ = cell.get("source")
147 if input_ is not None:
148 lines.extend(["# <markdowncell>", ""])
149 lines.extend(["# " + line for line in input_.splitlines()])
150 lines.append("")
151 lines.append("")
152 return str("\n".join(lines))
155_reader = PyReader()
156_writer = PyWriter()
158reads = _reader.reads
159read = _reader.read
160to_notebook = _reader.to_notebook
161write = _writer.write
162writes = _writer.writes