Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/nbformat/v2/nbpy.py: 21%

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

110 statements  

1"""Read and write notebooks as regular .py files. 

2 

3Authors: 

4 

5* Brian Granger 

6""" 

7 

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# ----------------------------------------------------------------------------- 

14 

15# ----------------------------------------------------------------------------- 

16# Imports 

17# ----------------------------------------------------------------------------- 

18from __future__ import annotations 

19 

20import ast 

21import re 

22 

23from .nbbase import new_code_cell, new_notebook, new_text_cell, new_worksheet 

24from .rwbase import NotebookReader, NotebookWriter 

25 

26# ----------------------------------------------------------------------------- 

27# Code 

28# ----------------------------------------------------------------------------- 

29 

30_encoding_declaration_re = re.compile(r"^#.*coding[:=]\s*([-\w.]+)") 

31 

32 

33class PyReaderError(Exception): 

34 """An error raised by the PyReader.""" 

35 

36 

37class PyReader(NotebookReader): 

38 """A Python notebook reader.""" 

39 

40 def reads(self, s, **kwargs): 

41 """Convert a string to a notebook.""" 

42 return self.to_notebook(s, **kwargs) 

43 

44 def to_notebook(self, s, **kwargs): 

45 """Convert a string to a notebook.""" 

46 lines = s.splitlines() 

47 cells = [] 

48 cell_lines: list[str] = [] 

49 state = "codecell" 

50 for line in lines: 

51 if line.startswith("# <nbformat>") or _encoding_declaration_re.match(line): 

52 pass 

53 elif line.startswith("# <codecell>"): 

54 cell = self.new_cell(state, cell_lines) 

55 if cell is not None: 

56 cells.append(cell) 

57 state = "codecell" 

58 cell_lines = [] 

59 elif line.startswith("# <htmlcell>"): 

60 cell = self.new_cell(state, cell_lines) 

61 if cell is not None: 

62 cells.append(cell) 

63 state = "htmlcell" 

64 cell_lines = [] 

65 elif line.startswith("# <markdowncell>"): 

66 cell = self.new_cell(state, cell_lines) 

67 if cell is not None: 

68 cells.append(cell) 

69 state = "markdowncell" 

70 cell_lines = [] 

71 else: 

72 cell_lines.append(line) 

73 if cell_lines and state == "codecell": 

74 cell = self.new_cell(state, cell_lines) 

75 if cell is not None: 

76 cells.append(cell) 

77 ws = new_worksheet(cells=cells) 

78 return new_notebook(worksheets=[ws]) 

79 

80 def new_cell(self, state, lines): 

81 """Create a new cell.""" 

82 if state == "codecell": 

83 input_ = "\n".join(lines) 

84 input_ = input_.strip("\n") 

85 if input_: 

86 return new_code_cell(input=input_) 

87 elif state == "htmlcell": 

88 text = self._remove_comments(lines) 

89 if text: 

90 return new_text_cell("html", source=text) 

91 elif state == "markdowncell": 

92 text = self._remove_comments(lines) 

93 if text: 

94 return new_text_cell("markdown", source=text) 

95 

96 def _remove_comments(self, lines): 

97 new_lines = [] 

98 for line in lines: 

99 if line.startswith("#"): 

100 new_lines.append(line[2:]) 

101 else: 

102 new_lines.append(line) 

103 text = "\n".join(new_lines) 

104 text = text.strip("\n") 

105 return text # noqa: RET504 

106 

107 def split_lines_into_blocks(self, lines): 

108 """Split lines into code blocks.""" 

109 if len(lines) == 1: 

110 yield lines[0] 

111 raise StopIteration() 

112 

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") 

119 

120 

121class PyWriter(NotebookWriter): 

122 """A Python notebook writer.""" 

123 

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)) 

150 

151 

152_reader = PyReader() 

153_writer = PyWriter() 

154 

155reads = _reader.reads 

156read = _reader.read 

157to_notebook = _reader.to_notebook 

158write = _writer.write 

159writes = _writer.writes