|
| 1 | +# nbio |
| 2 | + |
| 3 | + |
| 4 | +<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! --> |
| 5 | + |
| 6 | +## Reading a notebook |
| 7 | + |
| 8 | +A notebook is just a json file. |
| 9 | + |
| 10 | +<details open class="code-fold"> |
| 11 | +<summary>Exported source</summary> |
| 12 | + |
| 13 | +``` python |
| 14 | +def _read_json(self, encoding=None, errors=None): |
| 15 | + return loads(Path(self).read_text(encoding=encoding, errors=errors)) |
| 16 | +``` |
| 17 | + |
| 18 | +</details> |
| 19 | + |
| 20 | +``` python |
| 21 | +minimal_fn = Path('../tests/minimal.ipynb') |
| 22 | +minimal_txt = AttrDict(_read_json(minimal_fn)) |
| 23 | +``` |
| 24 | + |
| 25 | +It contains two sections, the `metadata`…: |
| 26 | + |
| 27 | +``` python |
| 28 | +minimal_txt.metadata |
| 29 | +``` |
| 30 | + |
| 31 | + {'kernelspec': {'display_name': 'Python 3 (ipykernel)', |
| 32 | + 'language': 'python', |
| 33 | + 'name': 'python3'}} |
| 34 | + |
| 35 | +…and, more importantly, the `cells`: |
| 36 | + |
| 37 | +``` python |
| 38 | +minimal_txt.cells |
| 39 | +``` |
| 40 | + |
| 41 | + [{'cell_type': 'markdown', |
| 42 | + 'metadata': {}, |
| 43 | + 'source': ['## A minimal notebook']}, |
| 44 | + {'cell_type': 'code', |
| 45 | + 'execution_count': None, |
| 46 | + 'metadata': {}, |
| 47 | + 'outputs': [{'data': {'text/plain': ['2']}, |
| 48 | + 'execution_count': None, |
| 49 | + 'metadata': {}, |
| 50 | + 'output_type': 'execute_result'}], |
| 51 | + 'source': ['# Do some arithmetic\n', '1+1']}] |
| 52 | + |
| 53 | +The second cell here is a `code` cell, however it contains no outputs, |
| 54 | +because it hasn’t been executed yet. To execute a notebook, we first |
| 55 | +need to convert it into a format suitable for `nbclient` (which expects |
| 56 | +some `dict` keys to be available as attrs, and some available as regular |
| 57 | +`dict` keys). Normally, `nbformat` is used for this step, but it’s |
| 58 | +rather slow and inflexible, so we’ll write our own function based on |
| 59 | +`fastcore`’s handy `dict2obj`, which makes all keys available as both |
| 60 | +attrs *and* keys. |
| 61 | + |
| 62 | +------------------------------------------------------------------------ |
| 63 | + |
| 64 | +<a |
| 65 | +href="https://github.com/AnswerDotAI/execnb/blob/main/execnb/nbio.py#L21" |
| 66 | +target="_blank" style="float:right; font-size:smaller">source</a> |
| 67 | + |
| 68 | +### NbCell |
| 69 | + |
| 70 | +> NbCell (idx, cell) |
| 71 | +
|
| 72 | +*`dict` subclass that also provides access to keys as attrs* |
| 73 | + |
| 74 | +We use an `AttrDict` subclass which has some basic functionality for |
| 75 | +accessing notebook cells. |
| 76 | + |
| 77 | +------------------------------------------------------------------------ |
| 78 | + |
| 79 | +<a |
| 80 | +href="https://github.com/AnswerDotAI/execnb/blob/main/execnb/nbio.py#L50" |
| 81 | +target="_blank" style="float:right; font-size:smaller">source</a> |
| 82 | + |
| 83 | +### dict2nb |
| 84 | + |
| 85 | +> dict2nb (js=None, **kwargs) |
| 86 | +
|
| 87 | +*Convert dict `js` to an `AttrDict`,* |
| 88 | + |
| 89 | +We can now convert our JSON into this `nbclient`-compatible format, |
| 90 | +which pretty prints the source code of cells in notebooks. |
| 91 | + |
| 92 | +``` python |
| 93 | +minimal = dict2nb(minimal_txt) |
| 94 | +cell = minimal.cells[1] |
| 95 | +cell |
| 96 | +``` |
| 97 | + |
| 98 | +``` json |
| 99 | +{ 'cell_type': 'code', |
| 100 | + 'execution_count': None, |
| 101 | + 'idx_': 1, |
| 102 | + 'metadata': {}, |
| 103 | + 'outputs': [ { 'data': {'text/plain': ['2']}, |
| 104 | + 'execution_count': None, |
| 105 | + 'metadata': {}, |
| 106 | + 'output_type': 'execute_result'}], |
| 107 | + 'source': '# Do some arithmetic\n1+1'} |
| 108 | +``` |
| 109 | + |
| 110 | +The abstract syntax tree of source code cells is available in the |
| 111 | +`parsed_` property: |
| 112 | + |
| 113 | +``` python |
| 114 | +cell.parsed_(), cell.parsed_()[0].value.op |
| 115 | +``` |
| 116 | + |
| 117 | + ([<ast.Expr>], <ast.Add>) |
| 118 | + |
| 119 | +------------------------------------------------------------------------ |
| 120 | + |
| 121 | +<a |
| 122 | +href="https://github.com/AnswerDotAI/execnb/blob/main/execnb/nbio.py#L57" |
| 123 | +target="_blank" style="float:right; font-size:smaller">source</a> |
| 124 | + |
| 125 | +### read_nb |
| 126 | + |
| 127 | +> read_nb (path) |
| 128 | +
|
| 129 | +*Return notebook at `path`* |
| 130 | + |
| 131 | +This reads the JSON for the file at `path` and converts it with |
| 132 | +[`dict2nb`](https://AnswerDotAI.github.io/execnb/nbio.html#dict2nb). For |
| 133 | +instance: |
| 134 | + |
| 135 | +``` python |
| 136 | +minimal = read_nb(minimal_fn) |
| 137 | +str(minimal.cells[0]) |
| 138 | +``` |
| 139 | + |
| 140 | + "{'cell_type': 'markdown', 'metadata': {}, 'source': '## A minimal notebook', 'idx_': 0}" |
| 141 | + |
| 142 | +The file name read is stored in `path_`: |
| 143 | + |
| 144 | +``` python |
| 145 | +minimal.path_ |
| 146 | +``` |
| 147 | + |
| 148 | + '../tests/minimal.ipynb' |
| 149 | + |
| 150 | +## Creating a notebook |
| 151 | + |
| 152 | +------------------------------------------------------------------------ |
| 153 | + |
| 154 | +<a |
| 155 | +href="https://github.com/AnswerDotAI/execnb/blob/main/execnb/nbio.py#L64" |
| 156 | +target="_blank" style="float:right; font-size:smaller">source</a> |
| 157 | + |
| 158 | +### new_nb |
| 159 | + |
| 160 | +> new_nb (cells=None, meta=None, nbformat=4, nbformat_minor=5) |
| 161 | +
|
| 162 | +*Returns an empty new notebook* |
| 163 | + |
| 164 | +Use this function when creating a new notebook. Useful for when you |
| 165 | +don’t want to create a notebook on disk first and then read it. |
| 166 | + |
| 167 | +------------------------------------------------------------------------ |
| 168 | + |
| 169 | +<a |
| 170 | +href="https://github.com/AnswerDotAI/execnb/blob/main/execnb/nbio.py#L69" |
| 171 | +target="_blank" style="float:right; font-size:smaller">source</a> |
| 172 | + |
| 173 | +### mk_cell |
| 174 | + |
| 175 | +> mk_cell (text, cell_type='code', **kwargs) |
| 176 | +
|
| 177 | +*Create an |
| 178 | +[`NbCell`](https://AnswerDotAI.github.io/execnb/nbio.html#nbcell) |
| 179 | +containing `text`* |
| 180 | + |
| 181 | +<table> |
| 182 | +<thead> |
| 183 | +<tr> |
| 184 | +<th></th> |
| 185 | +<th><strong>Type</strong></th> |
| 186 | +<th><strong>Default</strong></th> |
| 187 | +<th><strong>Details</strong></th> |
| 188 | +</tr> |
| 189 | +</thead> |
| 190 | +<tbody> |
| 191 | +<tr> |
| 192 | +<td>text</td> |
| 193 | +<td></td> |
| 194 | +<td></td> |
| 195 | +<td><code>source</code> attr in cell</td> |
| 196 | +</tr> |
| 197 | +<tr> |
| 198 | +<td>cell_type</td> |
| 199 | +<td>str</td> |
| 200 | +<td>code</td> |
| 201 | +<td><code>cell_type</code> attr in cell</td> |
| 202 | +</tr> |
| 203 | +<tr> |
| 204 | +<td>kwargs</td> |
| 205 | +<td>VAR_KEYWORD</td> |
| 206 | +<td></td> |
| 207 | +<td></td> |
| 208 | +</tr> |
| 209 | +</tbody> |
| 210 | +</table> |
| 211 | + |
| 212 | +``` python |
| 213 | +mk_cell('print(1)', execution_count=0) |
| 214 | +``` |
| 215 | + |
| 216 | +``` json |
| 217 | +{ 'cell_type': 'code', |
| 218 | + 'directives_': {}, |
| 219 | + 'execution_count': 0, |
| 220 | + 'idx_': 0, |
| 221 | + 'metadata': {}, |
| 222 | + 'source': 'print(1)'} |
| 223 | +``` |
| 224 | + |
| 225 | +## Writing a notebook |
| 226 | + |
| 227 | +------------------------------------------------------------------------ |
| 228 | + |
| 229 | +<a |
| 230 | +href="https://github.com/AnswerDotAI/execnb/blob/main/execnb/nbio.py#L81" |
| 231 | +target="_blank" style="float:right; font-size:smaller">source</a> |
| 232 | + |
| 233 | +### nb2dict |
| 234 | + |
| 235 | +> nb2dict (d, k=None) |
| 236 | +
|
| 237 | +*Convert parsed notebook to `dict`* |
| 238 | + |
| 239 | +This returns the exact same dict as is read from the notebook JSON. |
| 240 | + |
| 241 | +``` python |
| 242 | +minimal_fn = Path('../tests/minimal.ipynb') |
| 243 | +minimal = read_nb(minimal_fn) |
| 244 | + |
| 245 | +minimal_dict = _read_json(minimal_fn) |
| 246 | +assert minimal_dict==nb2dict(minimal) |
| 247 | +``` |
| 248 | + |
| 249 | +------------------------------------------------------------------------ |
| 250 | + |
| 251 | +<a |
| 252 | +href="https://github.com/AnswerDotAI/execnb/blob/main/execnb/nbio.py#L89" |
| 253 | +target="_blank" style="float:right; font-size:smaller">source</a> |
| 254 | + |
| 255 | +### nb2str |
| 256 | + |
| 257 | +> nb2str (nb) |
| 258 | +
|
| 259 | +*Convert `nb` to a `str`* |
| 260 | + |
| 261 | +To save a notebook we first need to convert it to a `str`: |
| 262 | + |
| 263 | +``` python |
| 264 | +print(nb2str(minimal)[:45]) |
| 265 | +``` |
| 266 | + |
| 267 | + { |
| 268 | + "cells": [ |
| 269 | + { |
| 270 | + "cell_type": "markdown", |
| 271 | + |
| 272 | +------------------------------------------------------------------------ |
| 273 | + |
| 274 | +<a |
| 275 | +href="https://github.com/AnswerDotAI/execnb/blob/main/execnb/nbio.py#L95" |
| 276 | +target="_blank" style="float:right; font-size:smaller">source</a> |
| 277 | + |
| 278 | +### write_nb |
| 279 | + |
| 280 | +> write_nb (nb, path) |
| 281 | +
|
| 282 | +*Write `nb` to `path`* |
| 283 | + |
| 284 | +This returns the exact same string as saved by Jupyter. |
| 285 | + |
| 286 | +``` python |
| 287 | +tmp = Path('tmp.ipynb') |
| 288 | +try: |
| 289 | + minimal_txt = minimal_fn.read_text() |
| 290 | + write_nb(minimal, tmp) |
| 291 | + assert minimal_txt==tmp.read_text() |
| 292 | +finally: tmp.unlink() |
| 293 | +``` |
| 294 | + |
| 295 | +Here’s how to put all the pieces of `execnb.nbio` together: |
| 296 | + |
| 297 | +``` python |
| 298 | +nb = new_nb([mk_cell('print(1)')]) |
| 299 | +path = Path('test.ipynb') |
| 300 | +write_nb(nb, path) |
| 301 | +nb2 = read_nb(path) |
| 302 | +print(nb2.cells) |
| 303 | +path.unlink() |
| 304 | +``` |
| 305 | + |
| 306 | + [{'cell_type': 'code', 'metadata': {}, 'source': 'print(1)', 'idx_': 0}] |
0 commit comments