diff --git a/Slides/cell_manager.py b/Slides/cell_manager.py index 0f89244..f8bbf37 100644 --- a/Slides/cell_manager.py +++ b/Slides/cell_manager.py @@ -1,127 +1,133 @@ #!/bin/env python3 import os import subprocess import shutil import nbformat ################################################################ class NotFoundNotebooks(Exception): "Could not find the notebooks to treat" ################################################################ def mergeNotebooks(notebook_files, add_cell_number=False, - select_functor=None, + select_functor=None, modify_functor=None, out_filename='talk'): "Merges several notebooks in a single one" def _select_functor(_i, _cell): return True if select_functor is None: select_functor = _select_functor + def _modify_functor(_i, _cell): + return _cell + + if modify_functor is None: + modify_functor = _modify_functor + print("Merging notebooks {0}".format(notebook_files)) notebooks = [nbformat.read(f, as_version=4) for f in notebook_files] if len(notebooks) == 0: raise NotFoundNotebooks cells = notebooks[0]['cells'] for n in notebooks[1:]: cells += n['cells'] new_cells = [] for cell_number, c in enumerate(cells): if not select_functor(cell_number, c): continue # print(c) - new_cells.append(c) + new_cells.append(modify_functor(cell_number, c)) if add_cell_number: new_cell = nbformat.notebooknode.NotebookNode() new_cell['cell_type'] = 'markdown' new_cell['source'] = 'Cell number {0}'.format(cell_number) new_cell['metadata'] = {} new_cells.append(new_cell) # print(new_cells) notebooks[0]['cells'] = new_cells nbformat.write(notebooks[0], out_filename) ################################################################ def launchSlideServer(filename, options="", font_size="25px"): " Launch the HTTP server for reveal slides " dir_name = os.path.dirname(__file__) slides_config_file = os.path.join(dir_name, 'slides_config.py') # reveal_path = os.path.join(dir_name, '..', 'js', 'reveal.js') # cmd = ('jupyter nbconvert --to=Slides.myslides.SlidesExporter # --config {1} --post serve ' # '--ServePostProcessor.open_in_browser=False' # ' --reveal-prefix={0} {2} talk.ipynb').format( # reveal_path, slides_config_file, options) cmd = ('jupyter nbconvert --to=Slides.myslides.SlidesExporter ' f'--config {slides_config_file} ' f'--post serve --SlidesExporter.font_size={font_size} ' f'--ServePostProcessor.open_in_browser=False {filename}') print(cmd) subprocess.call(cmd, shell=True) ################################################################ def generateHTML(filename, options="", font_size="25px"): " Launch the HTTP server for reveal slides " dir_name = os.path.dirname(__file__) slides_config_file = os.path.join(dir_name, 'slides_config.py') # reveal_path = os.path.join(dir_name, 'js', './reveal.js') # cmd = ('jupyter nbconvert --to=Slides.myslides.SlidesExporter # --config {1}' # ' --reveal-prefix={0} {2} talk.ipynb').format( # reveal_path, slides_config_file, options) cmd = ('jupyter nbconvert --to=Slides.myslides.SlidesExporter ' f'--config {slides_config_file} --SlidesExporter.pdf_format="true" ' f'--SlidesExporter.font_size={font_size}' f' {options} {filename}') print(cmd) subprocess.call(cmd, shell=True) ################################################################ def generateBeamer(filename, options="", font_size="25px"): " Launch the HTTP server for reveal slides " dir_name = os.path.dirname(__file__) slides_config_file = os.path.join(dir_name, 'beamer_config.py') # reveal_path = os.path.join(dir_name, 'js', './reveal.js') cmd = (f'jupyter nbconvert --to=Slides.beamer.BeamerExporter ' f'--config {slides_config_file} ' f'--BeamerExporter.font_size={font_size}' f' {options} {filename}') print(cmd) subprocess.call(cmd, shell=True) ################################################################ def executeNotebook(filename): " Request the execution of all cells " print('execute notebook: ', filename) dir_name = os.path.dirname(__file__) slides_config_file = os.path.join(dir_name, 'slides_execute_config.py') subprocess.call('jupyter nbconvert --to=notebook --output tmp.ipynb' ' --config {0} {1}'.format( slides_config_file, filename), shell=True) shutil.move('tmp.ipynb', filename) subprocess.call('jupyter trust {0}'.format(filename), shell=True) ################################################################ diff --git a/scripts/slides b/scripts/slides index a0595a2..cc51581 100755 --- a/scripts/slides +++ b/scripts/slides @@ -1,154 +1,171 @@ #!/usr/bin/python3 """ This executable permits to generate an advanced presentation from a Jupyter notebook. The capabilities are: - a server of reveal content - a pptx (under developement) - a beamer tex file (TODO) """ ################################################################ import argparse import os import re import Slides.count_slides as count_slides import Slides.cell_manager as cell_manager ################################################################ def getNotebookFilenames(slides_file): """ When a directory is provided to the executable, a file named 'slides' is searched for with the expected list of ipython notebooks. The list of notebooks to consider is then returned. """ if not os.path.isfile(slides_file): raise Exception("Cannot find slides file") f = open(slides_file) slides = [_l.strip() for _l in f.readlines() if _l != ""] return slides ################################################################ def main(): parser = argparse.ArgumentParser(description='Slide launcher') parser.add_argument( "--execute", action='store_true', help=('Requests to execute all the notebooks launching ' 'the slides server')) parser.add_argument("--no_count", action='store_false', help="Requests not to count slides generated") parser.add_argument("notebooks", nargs='*', help="The notebooks to associate in a presentation") parser.add_argument( "--internet", action='store_true', help="Weather the http server should serve on the internet") parser.add_argument("--html", action='store_true', help="only produce a html file") parser.add_argument("--beamer", action='store_true', help="produce a beamer/latex file and the pdf") parser.add_argument("--add_cell_number", action='store_true', help="add the cell number before each cell") parser.add_argument("--select_cells", type=int, nargs='*', help="Provides a list of cells to select") parser.add_argument("--font_size", type=str, default='25px', help="Provides the font size of the presentation") parser.add_argument("-o", "--out_filename", type=str, default="talk.ipynb", help=("Gives the name of notebook to generate when" " transforming or merging input notebooks")) parser.add_argument("-f", "--filter_correction", action="store_true", - help=("Asks to produce a copy of the note book with " + help=("Asks to produce a copy of the notebook with " " the correction removed")) + parser.add_argument("-p", "--prepare_correction", action="store_true", + help=("Asks to produce a copy of the note book with " + " only the correction tags removed")) arguments = parser.parse_args() if len(arguments.notebooks) == 1: if os.path.isdir(arguments.notebooks[0]): slides_path = arguments.notebooks[0] slides_file = os.path.join(slides_path, 'slides') arguments.notebooks = getNotebookFilenames(slides_file) else: _file = arguments.notebooks[0] ext = os.path.splitext(_file)[1] if ext == '.sld': arguments.notebooks = getNotebookFilenames(_file) if arguments.execute: for n in arguments.notebooks: cell_manager.executeNotebook(n) - def _no_sel(_i, _cell): return True - select_functor = _no_sel + select_functor = None if arguments.select_cells: select_cells = set(arguments.select_cells) def _sel_by_index(i, _cell): return i in select_cells select_functor = _sel_by_index if arguments.filter_correction: - _original_sel = select_functor - - def _sel_correction(i, cell): - if _original_sel(i, cell) is False: - return False + # _original_sel = select_functor + def _sel_correction(__unused__i, cell): + # if _original_sel(i, cell) is False: + # return False if ("solution" in cell.metadata and cell.metadata.solution is True): return False if re.search("SolutionToRemove", cell.source): return False - print(cell.source) + # print(cell.source) return True select_functor = _sel_correction + modify_functor = None + if arguments.prepare_correction: + def _remove_solution_tags(__unused__i, cell): + print(cell) + if cell.cell_type == 'markdown': + cell.source = cell.source.replace( + "SolutionToRemove", "").strip() + if cell.cell_type == 'code': + cell.source = cell.source.replace( + "# SolutionToRemove", "").strip() + print(cell) + return cell + + modify_functor = _remove_solution_tags + try: cell_manager.mergeNotebooks(arguments.notebooks, add_cell_number=arguments.add_cell_number, select_functor=select_functor, + modify_functor=modify_functor, out_filename=arguments.out_filename) except cell_manager.NotFoundNotebooks: print('Could not find the notebooks to treat: check path provided') return if not arguments.no_count: nb_slides = count_slides.countSlides([arguments.out_filename]) print("*" * 20) print("You generated a talk with {0} slides".format(nb_slides)) print("*" * 20) - if arguments.filter_correction: + if arguments.filter_correction or arguments.prepare_correction: return if arguments.html: cell_manager.generateHTML( arguments.out_filename, font_size=arguments.font_size) elif arguments.beamer: cell_manager.generateBeamer( arguments.out_filename, font_size=arguments.font_size) elif arguments.internet: cell_manager.launchSlideServer(arguments.out_filename, options="--ServePostProcessor.ip='*'", font_size=arguments.font_size) else: cell_manager.launchSlideServer( arguments.out_filename, font_size=arguments.font_size) ################################################################ if __name__ == "__main__": main()