Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/nbformat/v2/nbpy.py: 19%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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# -----------------------------------------------------------------------------
18from __future__ import annotations
20import re
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."""
36class PyReader(NotebookReader):
37 """A Python notebook reader."""
39 def reads(self, s, **kwargs):
40 """Convert a string to a notebook."""
41 return self.to_notebook(s, **kwargs)
43 def to_notebook(self, s, **kwargs):
44 """Convert a string to a notebook."""
45 lines = s.splitlines()
46 cells = []
47 cell_lines: list[str] = []
48 state = "codecell"
49 for line in lines:
50 if line.startswith("# <nbformat>") or _encoding_declaration_re.match(line):
51 pass
52 elif line.startswith("# <codecell>"):
53 cell = self.new_cell(state, cell_lines)
54 if cell is not None:
55 cells.append(cell)
56 state = "codecell"
57 cell_lines = []
58 elif line.startswith("# <htmlcell>"):
59 cell = self.new_cell(state, cell_lines)
60 if cell is not None:
61 cells.append(cell)
62 state = "htmlcell"
63 cell_lines = []
64 elif line.startswith("# <markdowncell>"):
65 cell = self.new_cell(state, cell_lines)
66 if cell is not None:
67 cells.append(cell)
68 state = "markdowncell"
69 cell_lines = []
70 else:
71 cell_lines.append(line)
72 if cell_lines and state == "codecell":
73 cell = self.new_cell(state, cell_lines)
74 if cell is not None:
75 cells.append(cell)
76 ws = new_worksheet(cells=cells)
77 return new_notebook(worksheets=[ws])
79 def new_cell(self, state, lines):
80 """Create a new cell."""
81 if state == "codecell":
82 input_ = "\n".join(lines)
83 input_ = input_.strip("\n")
84 if input_:
85 return new_code_cell(input=input_)
86 elif state == "htmlcell":
87 text = self._remove_comments(lines)
88 if text:
89 return new_text_cell("html", source=text)
90 elif state == "markdowncell":
91 text = self._remove_comments(lines)
92 if text:
93 return new_text_cell("markdown", source=text)
95 def _remove_comments(self, lines):
96 new_lines = []
97 for line in lines:
98 if line.startswith("#"):
99 new_lines.append(line[2:])
100 else:
101 new_lines.append(line)
102 text = "\n".join(new_lines)
103 text = text.strip("\n")
104 return text # noqa: RET504
106 def split_lines_into_blocks(self, lines):
107 """Split lines into code blocks."""
108 if len(lines) == 1:
109 yield lines[0]
110 raise StopIteration()
111 import ast
113 source = "\n".join(lines)
114 code = ast.parse(source)
115 starts = [x.lineno - 1 for x in code.body]
116 for i in range(len(starts) - 1):
117 yield "\n".join(lines[starts[i] : starts[i + 1]]).strip("\n")
118 yield "\n".join(lines[starts[-1] :]).strip("\n")
121class PyWriter(NotebookWriter):
122 """A Python notebook writer."""
124 def writes(self, nb, **kwargs):
125 """Convert a notebook object to a string."""
126 lines = ["# -*- coding: utf-8 -*-"]
127 lines.extend(["# <nbformat>2</nbformat>", ""])
128 for ws in nb.worksheets:
129 for cell in ws.cells:
130 if cell.cell_type == "code":
131 input_ = cell.get("input")
132 if input_ is not None:
133 lines.extend(["# <codecell>", ""])
134 lines.extend(input_.splitlines())
135 lines.append("")
136 elif cell.cell_type == "html":
137 input_ = cell.get("source")
138 if input_ is not None:
139 lines.extend(["# <htmlcell>", ""])
140 lines.extend(["# " + line for line in input_.splitlines()])
141 lines.append("")
142 elif cell.cell_type == "markdown":
143 input_ = cell.get("source")
144 if input_ is not None:
145 lines.extend(["# <markdowncell>", ""])
146 lines.extend(["# " + line for line in input_.splitlines()])
147 lines.append("")
148 lines.append("")
149 return str("\n".join(lines))
152_reader = PyReader()
153_writer = PyWriter()
155reads = _reader.reads
156read = _reader.read
157to_notebook = _reader.to_notebook
158write = _writer.write
159writes = _writer.writes