Execute notebook `fname` with `metadata` for preprocessing.

def execute_nb(fname, metadata=None, save=True, show_doc_only=False):
    "Execute notebook `fname` with `metadata` for preprocessing."
    # Any module used in the notebook that isn't inside must be in the same directory as this script
    with open(fname) as f: nb = nbformat.read(f, as_version=4)
    ep_class = ExecuteShowDocPreprocessor if show_doc_only else ExecutePreprocessor
    ep = ep_class(timeout=600, kernel_name='python3')
    metadata = metadata or {}
    ep.preprocess(nb, metadata)
    if save:
        with open(fname, 'wt') as f: nbformat.write(nb, f)
        NotebookNotary().sign(nb)