chrisjsewell / ipypublish
1 3
import copy
2 3
import logging
3

4 3
import traitlets as traits
5 3
from nbconvert.preprocessors import Preprocessor
6 3
from nbformat.notebooknode import NotebookNode
7

8

9 3
def merge(a, b, path=None, overwrite=True):
10
    """merges b into a
11

12
    Examples
13
    --------
14
    >>> from pprint import pprint
15
    >>> pprint(merge({'a':{'b':1},'c':3},{'a':{'b':2}}))
16
    {'a': {'b': 2}, 'c': 3}
17

18
    """
19 3
    if path is None:
20 3
        path = []
21 3
    for key in b:
22 3
        if key in a:
23 3
            if isinstance(a[key], dict) and isinstance(b[key], dict):
24 3
                merge(a[key], b[key], path + [str(key)], overwrite)
25 3
            elif a[key] == b[key]:
26 0
                pass  # same leaf value
27 3
            elif overwrite:
28 3
                a[key] = b[key]  # overwrite leaf value
29
            else:
30 0
                raise Exception("Conflict at %s" % ".".join(path + [str(key)]))
31
        else:
32 3
            a[key] = b[key]
33 3
    return a
34

35

36 3
class SplitOutputs(Preprocessor):
37
    """ a preprocessor to split outputs into separate cells,
38
    merging the cell and output metadata, with output metadata taking priority
39

40
    """
41

42 3
    split = traits.Bool(True, help="whether to split outputs").tag(config=True)
43

44 3
    def preprocess(self, nb, resources):
45

46 3
        if not self.split:
47 0
            return nb, resources
48

49 3
        logging.info("splitting outputs into separate cells")
50

51 3
        final_cells = []
52 3
        for cell in nb.cells:
53

54 3
            if not cell.cell_type == "code":
55 3
                final_cells.append(cell)
56 3
                continue
57 3
            outputs = cell.pop("outputs")
58 3
            cell.outputs = []
59 3
            final_cells.append(cell)
60 3
            for output in outputs:
61 3
                meta = copy.deepcopy(cell.metadata)
62
                # don't need the code to output
63 3
                meta.get("ipub", NotebookNode({})).code = False
64
                # don't create a new slide for each output,
65
                # unless specified in output level metadata
66 3
                if "slide" in meta.get("ipub", NotebookNode({})):
67 3
                    if meta.ipub.slide == "new":
68 0
                        meta.ipub.slide = True
69
                    else:
70 3
                        meta.ipub.slide = meta.ipub.slide
71 3
                meta = merge(meta, output.get("metadata", {}))
72 3
                new = NotebookNode(
73
                    {
74
                        "cell_type": "code",
75
                        "source": "",
76
                        "execution_count": None,
77
                        "metadata": meta,
78
                        "outputs": [output],
79
                    }
80
                )
81 3
                final_cells.append(new)
82

83 3
        nb.cells = final_cells
84

85 3
        return nb, resources

Read our documentation on viewing source code .

Loading