010 hide solution#
gegeben:
Ein Jupyter Notebook als
.ipynb
oder als.md
-Datei.Der Dateiname enthält den Teilstring
LOESUNG
Die Notebooks enthalten Code-Zeilen, die mit dem String
#...
(ACHTUNG: keine Leerzeichen) enden
Gesucht:
Ersetze Code-Zeilen, die mit
#...
enden,duch Code-Zeilen, die – korrekt eingerückt – nur noch aus
... #
bestehenschreibe die so “maskierten” Notebooks wieder ‘raus, aber ersetze im Dateinamen den Teilstring
LOESUNG
durch den TeilstringAUTO
.
Beispiel:
Input: Zwei mal Zwei
Output: Zwei mal Zwei
Ausführung#
Da Notebooks von Jupyterbook in alphabetischer Reihenfolge ausgeführt werfen, wird dieses Notebook wegen seinem Namen 010_xxx.ipynb
sehr früh ausgeführt – und das ist gut so, das es neue Notebooks erzeugt, die dann noch im gleichen Durchlauf wiederum von Juypterbook ausgeführt werden.
Allerdings wird dieses Notebook nur dann ausgeführt, wenn es selbst geändert wurde, oder es nicht mehr im Cache verfügbar ist.
Am einfachsten uns sichersten ist es daher, dieses Notebook z.B. in einem Makefile vor der eigentlichen Ausführung von Jupyterbook auzuführen, z.B. so:
python 010_hide-solution.py
Wenn man das so machen will, muss das ipynb-Notebook mit Juyptext z.B. mit Percent-Script gepaart werden.
code#
import glob
import json
import regex as re
verbose = 1
HIDE = True
if verbose >= 1:
print("010 hide solution")
010 hide solution
transform functions#
def hide(string):
def substfn(match):
#print([ match[i] for i in range(len(match.groups()) +1) ])
result = "".join([ match[1], "...", match[4] ])
#print(result)
return result
regex = r'( *)(.*)(#\.\.\.)(.*)'
return re.sub(regex,
lambda match: "".join([ match[1], "... # ", match[4] ]),
string,
0) if ("#..." in string and HIDE) else string
def new_path_to_file(path_to_file):
return "AUTO".join(path_to_file.split('LOESUNG'))
ipynb#
files_ipynb = glob.glob("*LOESUNG*.ipynb")
if verbose >= 2:
print(f"{files_ipynb=}")
json_dict = {}
for path_to_file in files_ipynb:
file = new_path_to_file(path_to_file)
with open(path_to_file, 'r') as f:
json_dict[file] = json.load(f)
for notebook in json_dict.values():
for cell in notebook['cells']:
# print(type(cell), "\n", cell)
if cell['cell_type'] == 'code':
source = cell['source']
# print(source)
source_hide = [ hide(line) for line in cell['source'] ]
# print(source_hide)
cell['source'] = source_hide
md#
files_md = glob.glob("*LOESUNG*.md")
if verbose >= 2:
print(f"{files_md=}")
md_dict = {}
for path_to_file in files_md:
file = new_path_to_file(path_to_file)
with open(path_to_file, 'r') as f:
md_dict[file] = f.readlines()
for filename, notebook in md_dict.items():
source_hide = [ hide(line) for line in notebook ]
md_dict[new_path_to_file(filename)] = source_hide
# if verbose >= 2: print(f"{md_dict}")
write result files#
for path_to_file, notebook in json_dict.items():
with open(path_to_file, 'w') as json_file:
json.dump(notebook, json_file)
if verbose >= 1: print(f"wrote {path_to_file}")
wrote zweimalzwei_AUTO.ipynb
wrote e_r1_quizz_AUTO.ipynb
wrote f_f7_AUTO.ipynb
wrote q_r2b_AUTO.ipynb
wrote quizz_mc_typen_AUTO.ipynb
wrote zweiundvierzig_AUTO.ipynb
wrote e_r2_funktionsparameter_BMI_AUTO.ipynb
wrote f_f5_AUTO.ipynb
wrote e_r2b_AUTO.ipynb
wrote f_f4_AUTO.ipynb
wrote f_f8_2024-03-03_AUTO.ipynb
for path_to_file, notebook in md_dict.items():
with open(path_to_file, 'w') as md_file:
md_file.writelines(notebook)
if verbose >= 1: print(f"wrote {path_to_file}")
wrote e_r1_quizz_AUTO.md
wrote zweimalzwei_AUTO.md
wrote f_f3_bibliotheken-kernfunktionen_AUTO.md
wrote f_f2_AUTO.md
wrote f_f8_2024-03-03_AUTO.md
wrote f_f1_AUTO.md
wrote f_f7_AUTO.md