Source code for ipypublish.convert.nbmerge

#!/usr/bin/env python
# Note, updated version of
# https://github.com/ipython/ipython-in-depth/blob/master/tools/nbmerge.py
"""
usage:

python nbmerge.py directory_name > merged.ipynb
"""
from __future__ import print_function

import logging
import os
import re
import sys

import nbformat
from six import string_types

from ipypublish.utils import pathlib, handle_error

logger = logging.getLogger("nbmerge")


[docs]def alphanumeric_sort(l): """sort key.name alphanumerically Parameters ---------- l: list[str] """ def convert(text): return int(text) if text.isdigit() else text.lower() def alphanum_key(key): return [convert(c) for c in re.split("([0-9]+)", key.name)] return sorted(l, key=alphanum_key)
[docs]def merge_notebooks(ipynb_path, ignore_prefix="_", to_str=False, as_version=4): """ merge one or more ipynb's, if more than one, then the meta data is taken from the first Parameters ---------- ipynb_path: str or pathlib.Path ignore_prefix : str ignore filename starting with this prefix to_str: bool return as a string, else return nbformat object as_version: int notebook format vesion Returns ------ finalnb: jupyter.notebook meta_path : pathlib.Path path to notebook containing meta file """ meta_path = "" if isinstance(ipynb_path, string_types): ipynb_path = pathlib.Path(ipynb_path) if not ipynb_path.exists(): handle_error( "the notebook path does not exist: {}".format(ipynb_path), IOError, logger ) final_nb = None if ipynb_path.is_dir(): logger.info("Merging all notebooks in directory") for ipath in alphanumeric_sort(ipynb_path.glob("*.ipynb")): if os.path.basename(ipath.name).startswith(ignore_prefix): continue with ipath.open("r", encoding="utf-8") as f: if ( sys.version_info.major == 3 and sys.version_info.minor < 6 and "win" not in sys.platform ): data = f.read() if hasattr(data, "decode"): data = data.decode("utf-8") nb = nbformat.reads(data, as_version=as_version) else: nb = nbformat.read(f, as_version=as_version) if final_nb is None: meta_path = ipath final_nb = nb else: final_nb.cells.extend(nb.cells) else: logger.info("Reading notebook") with ipynb_path.open("r", encoding="utf-8") as f: if ( sys.version_info.major == 3 and sys.version_info.minor < 6 and "win" not in sys.platform ): data = f.read() if hasattr(data, "decode"): data = data.decode("utf-8") final_nb = nbformat.reads(data, as_version=as_version) else: final_nb = nbformat.read(f, as_version=as_version) meta_path = ipynb_path if not hasattr(final_nb.metadata, "name"): final_nb.metadata.name = "" final_nb.metadata.name += "_merged" if to_str: if sys.version_info > (3, 0): return nbformat.writes(final_nb) else: return nbformat.writes(final_nb).encode("utf-8") if final_nb is None: handle_error( "no acceptable notebooks found for path: {}".format(ipynb_path.name), IOError, logger, ) return final_nb, meta_path