Source code for ipypublish.main

#!/usr/bin/env python
# import base64
import io
import logging
import os
import re
import shutil
import time

# python 3 to 2 compatibility
try:
    basestring
except NameError:
    basestring = str
try:
    import pathlib
except ImportError:
    import pathlib2 as pathlib

import ipypublish
from ipypublish.scripts import export_plugins
from ipypublish.scripts.nbmerge import merge_notebooks
from ipypublish.scripts.nbexport import export_notebook
from ipypublish.scripts.pdfexport import export_pdf


[docs]def publish(ipynb_path, outformat='latex_ipypublish_main', outpath=None, dump_files=False, ignore_prefix='_', clear_files=False, create_pdf=False, pdf_in_temp=False, pdf_debug=False): """ convert one or more Jupyter notebooks to a published format paths can be string of an existing file or folder, or a pathlib.Path like object all files linked in the documents are placed into a single folder Parameters ---------- ipynb_path notebook file or directory outformat: str output format to use outpath : path_like path to output converted files dump_files: bool whether to write files from nbconvert (containing images, etc) to outpath ignore_prefix: str ignore ipynb files with this prefix clear_files : str whether to clear existing external files in outpath folder create_pdf: bool whether to convert to pdf (if converting to latex) pdf_in_temp: bool whether to run pdf conversion in a temporary folder pdf_debug: bool if True, run latexmk in interactive mode Returns -------- outpath: str path to output file """ if isinstance(ipynb_path, basestring): ipynb_path = pathlib.Path(ipynb_path) ipynb_name = os.path.splitext(ipynb_path.name)[0] files_folder = ipynb_name + '_files' outdir = os.path.join(os.getcwd(), 'converted') if outpath is None else outpath if not os.path.exists(outdir): os.mkdir(outdir) logging.info('started ipypublish v{0} at {1}'.format(ipypublish.__version__, time.strftime("%c"))) logging.info('logging to: {}'.format(os.path.join(outdir, ipynb_name + '.nbpub.log'))) logging.info('running for ipynb(s) at: {0}'.format(ipynb_path)) logging.info('with conversion: {0}'.format(outformat)) final_nb, meta_path = merge_notebooks(ipynb_path, ignore_prefix=ignore_prefix) logging.debug('notebooks meta path: {}'.format(meta_path)) logging.info('getting output format from exporter plugin') plugins = export_plugins.get() if outformat not in plugins: logging.error("the exporter plugin '{}' does not exist".format(outformat) + ", acceptable names: {}".format(list(plugins.keys()))) raise ValueError("the exporter plugin '{}' does not exist".format(outformat) + ", acceptable names: {}".format(list(plugins.keys()))) oplugin = plugins[outformat] # ensure file paths point towards the right folder oplugin['config'][ 'ExtractOutputPreprocessor.output_filename_template' ] = files_folder + '/{unique_key}_{cell_index}_{index}{extension}' oplugin['config']['LatexDocLinks.metapath'] = str(meta_path) oplugin['config']['LatexDocLinks.filesfolder'] = str(files_folder) oplugin['config']['LatexDocHTML.metapath'] = str(meta_path) oplugin['config']['LatexDocHTML.filesfolder'] = str(files_folder) logging.debug('{}'.format(oplugin['config'])) # for debugging: # tpath = os.path.join(outdir, ipynb_name+'.template.tpl') # with open(tpath, "w") as fh: # fh.write(str(oplugin['template'])) (body, resources), exe = export_notebook(final_nb, oplugin['oformat'], oplugin['config'], oplugin['template']) # reduce multiple blank lines to single body = re.sub(r'\n\s*\n', '\n\n', body) # make sure references refer to correct slides if 'refslide' in resources: for k, (col, row) in resources['refslide'].items(): body = body.replace('{{id_home_prefix}}{0}'.format(k), '#/{0}/{1}{2}'.format(col, row, k)) # filter internal files by those that are referenced in the document body if resources['outputs']: for path in list(resources['outputs'].keys()): if path not in body: resources['outputs'].pop(path) internal_files = resources['outputs'] else: internal_files = {} # output main file outpath = os.path.join(outdir, ipynb_name + exe) logging.info('outputting converted file to: {}'.format(outpath)) with io.open(outpath, "w", encoding='utf8') as fh: fh.write(body) # output external files if dump_files or create_pdf: outfilespath = os.path.join(outdir, files_folder) logging.info('dumping external files to: {}'.format(outfilespath)) if os.path.exists(outfilespath): if clear_files: shutil.rmtree(outfilespath) else: os.mkdir(outfilespath) for internal_path, fcontents in internal_files.items(): with open(os.path.join(outdir, internal_path), "wb") as fh: fh.write(fcontents) for external_path in resources['external_file_paths']: shutil.copyfile(external_path, os.path.join(outfilespath, os.path.basename(external_path))) if create_pdf and oplugin['oformat'].lower() == 'latex': logging.info('running pdf conversion') if not export_pdf(outpath, outdir=outdir, files_path=outfilespath, convert_in_temp=pdf_in_temp, html_viewer=True, debug_mode=pdf_debug): logging.error('pdf export returned false, try running with pdf_debug=True') raise RuntimeError('the pdf export failed, try running with pdf_debug=True') logging.info('process finished successfully') return outpath