Coverage for gpaw/utilities/nbrun.py: 17%
36 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-12 00:18 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-12 00:18 +0000
1"""Code for summerschool notebooks."""
2import json
3import sys
4from pathlib import Path
5from typing import Dict, Any, Optional
8def py2ipynb(path: Path,
9 kernel: Optional[Dict[str, str]] = None,
10 teachermode: Optional[bool] = False) -> None:
11 """Convert Python script to ipynb file.
13 Hides cells marked with "# teacher" and replaces lines marked with
14 "# student: ..."::
16 answer = 42 # student: answer = ...
18 gives::
20 answer = ...
22 """
23 cells = []
24 text = path.read_text()
25 assert text.startswith('# %%\n')
26 chunks = text[5:].split('\n\n# %%\n')
28 for chunk in chunks:
29 cell_type = 'code'
30 if chunk.startswith(('"""', 'r"""')):
31 chunk = chunk.strip('r\n')
32 chunk = chunk.strip('"')
33 cell_type = 'markdown'
35 cell: Dict[str, Any] = {
36 'cell_type': cell_type,
37 'metadata': {},
38 'source': chunk.splitlines(True)}
40 if cell_type == 'code':
41 cell['outputs'] = []
42 cell['execution_count'] = None
43 lines = cell['source']
44 for i, line in enumerate(lines):
45 if ' # student:' in line and not teachermode:
46 a, b = (x.strip() for x in line.split('# student:'))
47 lines[i] = line.split(a)[0] + b + '\n'
48 elif line.startswith('# magic: '):
49 lines[i] = line[9:]
50 elif line.lower().startswith('# teacher') and not teachermode:
51 del lines[i:]
52 break
54 cells.append(cell)
56 outpath = path.with_suffix('.ipynb')
57 if kernel is None:
58 kernel = {'display_name': 'Python 3',
59 'language': 'python',
60 'name': 'python3'}
61 outpath.write_text(
62 json.dumps(
63 {'cells': cells,
64 'metadata': {
65 'kernelspec': kernel,
66 'language_info': {
67 'codemirror_mode': {'name': 'ipython', 'version': 3},
68 'file_extension': '.py',
69 'mimetype': 'text/x-python',
70 'name': 'python',
71 'nbconvert_exporter': 'python',
72 'pygments_lexer': 'ipython3',
73 'version': '3.6.1'}},
74 'nbformat': 4,
75 'nbformat_minor': 1},
76 indent=2))
79if __name__ == '__main__':
80 py2ipynb(Path(sys.argv[1]))