learntaproot/generate_jupyter.py

142 lines
5.8 KiB
Python

import nbformat
import re
import sys
sessions = ['']
FIRST_CELL = '''############## PLEASE RUN THIS CELL FIRST! ###################
# import everything and define a test runner function
from importlib import reload
from helper import run
'''
UNITTEST_TEMPLATE_1 = '''### Exercise {exercise_number}
{instructions}
#### Make [this test](/edit/{path}/{module}.py) pass: `{module}.py:{test_suite}:{test}`'''
UNITTEST_TEMPLATE_2 = '''# Exercise {exercise_number}
reload({module})
run({module}.{test_suite}('{test}'))'''
EXERCISE_TEMPLATE_1 = '''### Exercise {exercise_number}
{instructions}'''
EXERCISE_TEMPLATE_2 = '''# Exercise {exercise_number}
{code}'''
for session in sessions:
notebook = nbformat.v4.new_notebook()
notebook_complete = nbformat.v4.new_notebook()
cells = notebook['cells']
cells_complete = notebook_complete['cells']
path = 'session{}'.format(session)
with open('{}/complete/answers.py'.format(path), 'r') as f:
current = ''
cell_type = None
exercise_number = 1
for l in f:
line = l.strip()
if line in ('#markdown', '#code', '#exercise', '#unittest'):
cell_type = line[1:]
elif line == '#end{}'.format(cell_type):
if cell_type == 'markdown':
markdown_cell = nbformat.v4.new_markdown_cell(current)
markdown_cell.metadata['slideshow'] = dict(slide_type='slide')
cells.append(markdown_cell)
cells_complete.append(markdown_cell)
elif cell_type == 'code':
# only take >>> or ... lines
lines = []
for line in current.split('\n'):
if line.startswith('>>> ') or line.startswith('... '):
line = re.sub(r'\\\\x', r'\\x', line)
lines.append(line[4:])
if lines[0].startswith('import '):
code = FIRST_CELL + '\n'.join(lines)
slide_type = 'skip'
else:
code = '\n'.join(lines)
slide_type = 'slide'
code_cell = nbformat.v4.new_code_cell(code)
code_cell.metadata['slideshow'] = dict(slide_type=slide_type)
cells.append(code_cell)
cells_complete.append(code_cell)
elif cell_type == 'exercise':
instructions, code = current.split('---')
markdown = EXERCISE_TEMPLATE_1.format(
exercise_number=exercise_number,
instructions=instructions,
)
markdown_cell = nbformat.v4.new_markdown_cell(markdown)
markdown_cell.metadata['slideshow'] = dict(slide_type='slide')
cells.append(markdown_cell)
cells_complete.append(markdown_cell)
lines = []
lines_complete = []
for line in code.split('\n'):
if line.startswith('>>> ') or line.startswith('... '):
line = re.sub(r'\\\\x', r'\\x', line)
start_alt = line.find(' #/')
if start_alt == -1:
lines.append(line[4:])
lines_complete.append(line[4:])
else:
lines.append(line[start_alt+4:])
lines_complete.append(line[4:start_alt])
code_1 = EXERCISE_TEMPLATE_2.format(
code='\n'.join(lines),
exercise_number=exercise_number,
)
code_cell_1 = nbformat.v4.new_code_cell(code_1)
cells.append(code_cell_1)
code_2 = EXERCISE_TEMPLATE_2.format(
code='\n'.join(lines_complete),
exercise_number=exercise_number,
)
code_cell_2 = nbformat.v4.new_code_cell(code_2)
cells_complete.append(code_cell_2)
exercise_number += 1
elif cell_type == 'unittest':
module, test_suite, test, instructions = current.split(':', 3)
markdown = UNITTEST_TEMPLATE_1.format(
exercise_number=exercise_number,
instructions=instructions,
module=module,
path=path,
test=test,
test_suite=test_suite,
)
markdown_cell = nbformat.v4.new_markdown_cell(markdown)
markdown_cell.metadata['slideshow'] = dict(slide_type='slide')
cells.append(markdown_cell)
cells_complete.append(markdown_cell)
code = UNITTEST_TEMPLATE_2.format(
exercise_number=exercise_number,
module=module,
path=path,
test=test,
test_suite=test_suite,
)
code_cell = nbformat.v4.new_code_cell(code)
cells.append(code_cell)
cells_complete.append(code_cell)
exercise_number += 1
current = ''
cell_type = None
elif cell_type:
if cell_type == 'markdown':
current += l
else:
current += line + '\n'
nbformat.write(notebook, '{}/session{}.ipynb'.format(path, session))
nbformat.write(notebook_complete, '{}/complete/session{}.ipynb'.format(path, session))