Skip to content

Commit 2f837e6

Browse files
committed
fixes #1588
1 parent af56909 commit 2f837e6

3 files changed

Lines changed: 49 additions & 26 deletions

File tree

nbdev/clean.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def _clean_cell_output_id(lines):
5858
return _skip_or_sub(lines) if isinstance(lines,str) else [_skip_or_sub(o) for o in lines]
5959

6060
# %% ../nbs/api/11_clean.ipynb #b4cde615
61-
def _clean_cell_output(cell, clean_ids):
61+
def _clean_cell_output(cell, clean_ids, allowed_out_meta_keys):
6262
"Remove `cell` output execution count and optionally ids from text reprs"
6363
outputs = cell.get('outputs', [])
6464
for o in outputs:
@@ -69,15 +69,15 @@ def _clean_cell_output(cell, clean_ids):
6969
if k.startswith('text') and clean_ids: data[k] = _clean_cell_output_id(data[k])
7070
if k.startswith('image') and "svg" not in k: data[k] = data[k].rstrip()
7171
if 'text' in o and clean_ids: o['text'] = _clean_cell_output_id(o['text'])
72-
# o.get('metadata', {}).pop('tags', None)
72+
if 'metadata' in o: o['metadata'] = {k:v for k,v in o['metadata'].items() if k in allowed_out_meta_keys}
7373

7474
# %% ../nbs/api/11_clean.ipynb #2ba79c93
75-
def _clean_cell(cell, clear_all, allowed_metadata_keys, clean_ids):
75+
def _clean_cell(cell, clear_all, allowed_metadata_keys, clean_ids, allowed_out_meta_keys):
7676
"Clean `cell` by removing superfluous metadata or everything except the input if `clear_all`"
7777
if 'execution_count' in cell: cell['execution_count'] = None
7878
if 'outputs' in cell:
7979
if clear_all: cell['outputs'] = []
80-
else: _clean_cell_output(cell, clean_ids)
80+
else: _clean_cell_output(cell, clean_ids, allowed_out_meta_keys)
8181
if cell['source'] == ['']: cell['source'] = []
8282
cell['metadata'] = {} if clear_all else {
8383
k:v for k,v in cell['metadata'].items() if k in allowed_metadata_keys}
@@ -90,13 +90,16 @@ def clean_nb(
9090
allowed_metadata_keys:list=None, # Preserve the list of keys in the main notebook metadata
9191
allowed_cell_metadata_keys:list=None, # Preserve the list of keys in cell level metadata
9292
clean_ids=True, # Remove ids from plaintext reprs?
93+
allowed_out_metadata_keys:list=None, # Preserve the list of keys in output metadata
9394
):
9495
"Clean `nb` from superfluous metadata"
9596
metadata_keys = {"kernelspec", "jekyll", "jupytext", "doc", "widgets"}
9697
if allowed_metadata_keys: metadata_keys.update(allowed_metadata_keys)
9798
cell_metadata_keys = {"hide_input"}
9899
if allowed_cell_metadata_keys: cell_metadata_keys.update(allowed_cell_metadata_keys)
99-
for c in nb['cells']: _clean_cell(c, clear_all, cell_metadata_keys, clean_ids)
100+
out_meta_keys = set()
101+
if allowed_out_metadata_keys: out_meta_keys.update(allowed_out_metadata_keys)
102+
for c in nb['cells']: _clean_cell(c, clear_all, cell_metadata_keys, clean_ids, out_meta_keys)
100103
if nb.get('metadata', {}).get('kernelspec', {}).get('name', None):
101104
nb['metadata']['kernelspec']['display_name'] = nb["metadata"]["kernelspec"]["name"]
102105
nb['metadata'] = {k:v for k,v in nb['metadata'].items() if k in metadata_keys}
@@ -127,7 +130,8 @@ def _nbdev_clean(nb, path=None, clear_all=None):
127130
clear_all = clear_all or cfg.clear_all
128131
allowed_metadata_keys = cfg.get("allowed_metadata_keys") or []
129132
allowed_cell_metadata_keys = cfg.get("allowed_cell_metadata_keys") or []
130-
clean_nb(nb, clear_all, allowed_metadata_keys, allowed_cell_metadata_keys, cfg.clean_ids)
133+
allowed_out_metadata_keys = cfg.get("allowed_out_metadata_keys") or []
134+
clean_nb(nb, clear_all, allowed_metadata_keys, allowed_cell_metadata_keys, cfg.clean_ids, allowed_out_metadata_keys)
131135
if path: nbdev_trust.__wrapped__(path)
132136

133137
# %% ../nbs/api/11_clean.ipynb #6af3b9d4
@@ -209,7 +213,7 @@ def nbdev_install_hooks():
209213
os.chmod(fn, os.stat(fn).st_mode | stat.S_IEXEC)
210214

211215
cmd = 'git config --local include.path ../.gitconfig'
212-
(repo_path/'.gitconfig').write_text(f'''# Generated by nbdev_install_hooks
216+
(repo_path/'.gitconfig').write_text(f'''# Generated by nbdev-install-hooks
213217
#
214218
# If you need to disable this instrumentation do:
215219
# git config --local --unset include.path

nbs/api/02_maker.ipynb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,7 @@
240240
]
241241
},
242242
"execution_count": null,
243-
"metadata": {
244-
"__type": "PosixPath"
245-
},
243+
"metadata": {},
246244
"output_type": "execute_result"
247245
}
248246
],

nbs/api/11_clean.ipynb

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@
164164
"outputs": [],
165165
"source": [
166166
"#| export\n",
167-
"def _clean_cell_output(cell, clean_ids):\n",
167+
"def _clean_cell_output(cell, clean_ids, allowed_out_meta_keys):\n",
168168
" \"Remove `cell` output execution count and optionally ids from text reprs\"\n",
169169
" outputs = cell.get('outputs', [])\n",
170170
" for o in outputs:\n",
@@ -175,7 +175,7 @@
175175
" if k.startswith('text') and clean_ids: data[k] = _clean_cell_output_id(data[k])\n",
176176
" if k.startswith('image') and \"svg\" not in k: data[k] = data[k].rstrip()\n",
177177
" if 'text' in o and clean_ids: o['text'] = _clean_cell_output_id(o['text'])\n",
178-
"# o.get('metadata', {}).pop('tags', None)"
178+
" if 'metadata' in o: o['metadata'] = {k:v for k,v in o['metadata'].items() if k in allowed_out_meta_keys}"
179179
]
180180
},
181181
{
@@ -186,12 +186,12 @@
186186
"outputs": [],
187187
"source": [
188188
"#| export\n",
189-
"def _clean_cell(cell, clear_all, allowed_metadata_keys, clean_ids):\n",
189+
"def _clean_cell(cell, clear_all, allowed_metadata_keys, clean_ids, allowed_out_meta_keys):\n",
190190
" \"Clean `cell` by removing superfluous metadata or everything except the input if `clear_all`\"\n",
191191
" if 'execution_count' in cell: cell['execution_count'] = None\n",
192192
" if 'outputs' in cell:\n",
193193
" if clear_all: cell['outputs'] = []\n",
194-
" else: _clean_cell_output(cell, clean_ids)\n",
194+
" else: _clean_cell_output(cell, clean_ids, allowed_out_meta_keys)\n",
195195
" if cell['source'] == ['']: cell['source'] = []\n",
196196
" cell['metadata'] = {} if clear_all else {\n",
197197
" k:v for k,v in cell['metadata'].items() if k in allowed_metadata_keys}\n",
@@ -212,13 +212,16 @@
212212
" allowed_metadata_keys:list=None, # Preserve the list of keys in the main notebook metadata\n",
213213
" allowed_cell_metadata_keys:list=None, # Preserve the list of keys in cell level metadata\n",
214214
" clean_ids=True, # Remove ids from plaintext reprs?\n",
215+
" allowed_out_metadata_keys:list=None, # Preserve the list of keys in output metadata\n",
215216
"):\n",
216217
" \"Clean `nb` from superfluous metadata\"\n",
217218
" metadata_keys = {\"kernelspec\", \"jekyll\", \"jupytext\", \"doc\", \"widgets\"}\n",
218219
" if allowed_metadata_keys: metadata_keys.update(allowed_metadata_keys)\n",
219220
" cell_metadata_keys = {\"hide_input\"}\n",
220221
" if allowed_cell_metadata_keys: cell_metadata_keys.update(allowed_cell_metadata_keys)\n",
221-
" for c in nb['cells']: _clean_cell(c, clear_all, cell_metadata_keys, clean_ids)\n",
222+
" out_meta_keys = set()\n",
223+
" if allowed_out_metadata_keys: out_meta_keys.update(allowed_out_metadata_keys)\n",
224+
" for c in nb['cells']: _clean_cell(c, clear_all, cell_metadata_keys, clean_ids, out_meta_keys)\n",
222225
" if nb.get('metadata', {}).get('kernelspec', {}).get('name', None):\n",
223226
" nb['metadata']['kernelspec']['display_name'] = nb[\"metadata\"][\"kernelspec\"][\"name\"]\n",
224227
" nb['metadata'] = {k:v for k,v in nb['metadata'].items() if k in metadata_keys}\n",
@@ -369,17 +372,17 @@
369372
{
370373
"data": {
371374
"text/plain": [
372-
"'b3c0571e'"
375+
"'88ba1c41'"
373376
]
374377
},
375-
"execution_count": null,
378+
"execution_count": 77,
376379
"metadata": {},
377380
"output_type": "execute_result"
378381
}
379382
],
380383
"source": [
381384
"test_cell = {'source': 'x=1', 'cell_type': 'code', 'metadata': {}}\n",
382-
"_clean_cell(test_cell, False, set(), True)\n",
385+
"_clean_cell(test_cell, False, set(), True, set())\n",
383386
"test_cell['id']"
384387
]
385388
},
@@ -438,7 +441,8 @@
438441
" clear_all = clear_all or cfg.clear_all\n",
439442
" allowed_metadata_keys = cfg.get(\"allowed_metadata_keys\") or []\n",
440443
" allowed_cell_metadata_keys = cfg.get(\"allowed_cell_metadata_keys\") or []\n",
441-
" clean_nb(nb, clear_all, allowed_metadata_keys, allowed_cell_metadata_keys, cfg.clean_ids)\n",
444+
" allowed_out_metadata_keys = cfg.get(\"allowed_out_metadata_keys\") or []\n",
445+
" clean_nb(nb, clear_all, allowed_metadata_keys, allowed_cell_metadata_keys, cfg.clean_ids, allowed_out_metadata_keys)\n",
442446
" if path: nbdev_trust.__wrapped__(path)"
443447
]
444448
},
@@ -474,11 +478,12 @@
474478
"By default (`fname` left to `None`), all the notebooks in `config.nbs_path` are cleaned. You can opt in to fully clean the notebook by removing every bit of metadata and the cell outputs by passing `clear_all=True`.\n",
475479
"\n",
476480
"If you want to keep some keys in the main notebook metadata you can set `allowed_metadata_keys` in `[tool.nbdev]` in `pyproject.toml`.\n",
477-
"Similarly for cell level metadata use: `allowed_cell_metadata_keys`. For example, to preserve both `k1` and `k2` at both the notebook and cell level add the following to `pyproject.toml`:\n",
481+
"Similarly for cell level metadata use `allowed_cell_metadata_keys`, and for output metadata use `allowed_out_metadata_keys`. For example, to preserve both `k1` and `k2` at both the notebook and cell level add the following to `pyproject.toml`:\n",
478482
"```toml\n",
479483
"[tool.nbdev]\n",
480484
"allowed_metadata_keys = [\"k1\", \"k2\"]\n",
481485
"allowed_cell_metadata_keys = [\"k1\", \"k2\"]\n",
486+
"allowed_out_metadata_keys = [\"k1\", \"k2\"]\n",
482487
"```"
483488
]
484489
},
@@ -620,6 +625,8 @@
620625
{
621626
"data": {
622627
"text/markdown": [
628+
"<div class=\"prose\">\n",
629+
"\n",
623630
"```python\n",
624631
"an_existing_line = True\n",
625632
"\n",
@@ -629,13 +636,24 @@
629636
" clean_jupyter(**kwargs)\n",
630637
"\n",
631638
"c.ContentsManager.pre_save_hook = nbdev_clean_jupyter\n",
632-
"```"
639+
"```\n",
640+
"\n",
641+
"</div>"
633642
],
634643
"text/plain": [
635-
"<IPython.core.display.Markdown object>"
644+
"Markdown(```python\n",
645+
"an_existing_line = True\n",
646+
"\n",
647+
"def nbdev_clean_jupyter(**kwargs):\n",
648+
" try: from nbdev.clean import clean_jupyter\n",
649+
" except ModuleNotFoundError: return\n",
650+
" clean_jupyter(**kwargs)\n",
651+
"\n",
652+
"c.ContentsManager.pre_save_hook = nbdev_clean_jupyter\n",
653+
"```)"
636654
]
637655
},
638-
"execution_count": null,
656+
"execution_count": 89,
639657
"metadata": {},
640658
"output_type": "execute_result"
641659
}
@@ -711,7 +729,7 @@
711729
" os.chmod(fn, os.stat(fn).st_mode | stat.S_IEXEC)\n",
712730
"\n",
713731
" cmd = 'git config --local include.path ../.gitconfig'\n",
714-
" (repo_path/'.gitconfig').write_text(f'''# Generated by nbdev_install_hooks\n",
732+
" (repo_path/'.gitconfig').write_text(f'''# Generated by nbdev-install-hooks\n",
715733
"#\n",
716734
"# If you need to disable this instrumentation do:\n",
717735
"# git config --local --unset include.path\n",
@@ -863,7 +881,7 @@
863881
" nbs_path = Path('nbs')\n",
864882
" nbs_path.mkdir()\n",
865883
" Path('pyproject.toml').write_text('[tool.nbdev]\\\\nnbs_path = \"nbs\"')\n",
866-
" _run('nbdev_install_hooks')\n",
884+
" _run('nbdev-install-hooks')\n",
867885
" \n",
868886
" fn = 'random.ipynb'\n",
869887
" p = nbs_path/fn\n",
@@ -917,7 +935,10 @@
917935
]
918936
}
919937
],
920-
"metadata": {},
938+
"metadata": {
939+
"solveit_dialog_mode": "concise",
940+
"solveit_ver": 2
941+
},
921942
"nbformat": 4,
922943
"nbformat_minor": 5
923944
}

0 commit comments

Comments
 (0)