Skip to content

Commit

Permalink
WIP Add option to remove cell header comment lines on export, partly f…
Browse files Browse the repository at this point in the history
…ixes #965
  • Loading branch information
dmose committed Feb 11, 2023
1 parent cf5e6a5 commit 3780b52
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 10 deletions.
13 changes: 10 additions & 3 deletions nbdev/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,18 @@ def add_init(path=None):

# %% ../nbs/api/01_config.ipynb 51
def write_cells(cells, hdr, file, offset=0):
"Write `cells` to `file` along with header `hdr` starting at index `offset` (mainly for nbdev internal use)."
"""Write `cells` to `file` along with header `hdr` starting at index `offset`
(mainly for nbdev internal use). If `hdr` is not specified, neither the header
nor the cell index will be written"""
for cell in cells:
if cell.source.strip(): file.write(f'\n\n{hdr} {cell.idx_+offset}\n{cell.source}')
if cell.source.strip():
full_hdr = ''
if (hdr is not None):
full_hdr = f'{hdr} {cell.idx_+offset}\n'

file.write(f'\n\n{full_hdr}{cell.source}')

# %% ../nbs/api/01_config.ipynb 52
# %% ../nbs/api/01_config.ipynb 56
def _basic_export_nb(fname, name, dest=None):
"Basic exporter to bootstrap nbdev."
if dest is None: dest = get_config().lib_path
Expand Down
16 changes: 13 additions & 3 deletions nbdev/maker.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,18 @@ def update_var(varname, func, fn=None, code=None):
# %% ../nbs/api/02_maker.ipynb 15
class ModuleMaker:
"Helper class to create exported library from notebook source cells"
def __init__(self, dest, name, nb_path, is_new=True, parse=True):
def __init__(self, dest, name, nb_path, is_new=True, parse=True,
write_cell_hdrs=True):
dest,nb_path = Path(dest),Path(nb_path)
store_attr()
self.fname = dest/(name.replace('.','/') + ".py")
if is_new: dest.mkdir(parents=True, exist_ok=True)
else: assert self.fname.exists(), f"{self.fname} does not exist"
self.dest2nb = nb_path.relpath(self.fname.parent).as_posix()
self.hdr = f"# %% {self.dest2nb}"
if write_cell_hdrs is True:
self.hdr = f"# %% {self.dest2nb}"
else:
self.hdr = None

# %% ../nbs/api/02_maker.ipynb 18
def decor_id(d):
Expand Down Expand Up @@ -210,7 +214,7 @@ def make(self:ModuleMaker, cells, all_cells=None, lib_path=None):
write_cells(cells[last_future:], self.hdr, f)
f.write('\n')

# %% ../nbs/api/02_maker.ipynb 38
# %% ../nbs/api/02_maker.ipynb 45
@patch
def _update_all(self:ModuleMaker, all_cells, alls):
return pformat(alls + self.make_all(all_cells), width=160)
Expand All @@ -222,7 +226,13 @@ def _make_exists(self:ModuleMaker, cells, all_cells=None):
update_var('__all__', partial(self._update_all, all_cells), fn=self.fname)
with self.fname.open('a', encoding="utf-8") as f: write_cells(cells, self.hdr, f)

<<<<<<< HEAD
# %% ../nbs/api/02_maker.ipynb 44
||||||| parent of 414c5f7 (WIP Add option to remove cell header comment lines on export, partly fixes #965)
# %% ../nbs/api/maker.ipynb 44
=======
# %% ../nbs/api/maker.ipynb 51
>>>>>>> 414c5f7 (WIP Add option to remove cell header comment lines on export, partly fixes #965)
def _basic_export_nb2(fname, name, dest=None):
"A basic exporter to bootstrap nbdev using `ModuleMaker`"
if dest is None: dest = get_config().lib_path
Expand Down
56 changes: 54 additions & 2 deletions nbs/api/01_config.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"source": [
"#|hide\n",
"from fastcore.test import *\n",
"from nbdev.maker import make_code_cells\n",
"import tempfile"
]
},
Expand Down Expand Up @@ -725,9 +726,60 @@
"source": [
"#|export\n",
"def write_cells(cells, hdr, file, offset=0):\n",
" \"Write `cells` to `file` along with header `hdr` starting at index `offset` (mainly for nbdev internal use).\"\n",
" \"\"\"Write `cells` to `file` along with header `hdr` starting at index `offset`\n",
" (mainly for nbdev internal use). If `hdr` is not specified, neither the header\n",
" nor the cell index will be written\"\"\"\n",
" for cell in cells:\n",
" if cell.source.strip(): file.write(f'\\n\\n{hdr} {cell.idx_+offset}\\n{cell.source}')"
" if cell.source.strip():\n",
" full_hdr = ''\n",
" if (hdr is not None):\n",
" full_hdr = f'{hdr} {cell.idx_+offset}\\n'\n",
" \n",
" file.write(f'\\n\\n{full_hdr}{cell.source}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If `hdr` has a real value, include it along with the offset index:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#|hide\n",
"with tempfile.TemporaryFile(mode='w+t') as f:\n",
" c = make_code_cells(\"a = 'b'\\n_doc_ = 'hi'\")\n",
" write_cells(c, \"#\", f)\n",
"\n",
" f.seek(0)\n",
" test_eq(f.read(), \"\\n\\n# 0\\na = 'b'\\n_doc_ = 'hi'\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If `hdr` doesn't have a real value, omit the line entirely:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#|hide\n",
"with tempfile.TemporaryFile(mode='w+t') as f:\n",
" c = make_code_cells(\"a = 'b'\\n_doc_ = 'hi'\")\n",
" write_cells(c, None, f)\n",
"\n",
" f.seek(0)\n",
" test_eq(f.read(), \"\\n\\na = 'b'\\n_doc_ = 'hi'\")"
]
},
{
Expand Down
112 changes: 110 additions & 2 deletions nbs/api/02_maker.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,18 @@
"#|export\n",
"class ModuleMaker:\n",
" \"Helper class to create exported library from notebook source cells\"\n",
" def __init__(self, dest, name, nb_path, is_new=True, parse=True):\n",
" def __init__(self, dest, name, nb_path, is_new=True, parse=True, \n",
" write_cell_hdrs=True):\n",
" dest,nb_path = Path(dest),Path(nb_path)\n",
" store_attr()\n",
" self.fname = dest/(name.replace('.','/') + \".py\")\n",
" if is_new: dest.mkdir(parents=True, exist_ok=True)\n",
" else: assert self.fname.exists(), f\"{self.fname} does not exist\"\n",
" self.dest2nb = nb_path.relpath(self.fname.parent).as_posix()\n",
" self.hdr = f\"# %% {self.dest2nb}\""
" if write_cell_hdrs is True:\n",
" self.hdr = f\"# %% {self.dest2nb}\"\n",
" else:\n",
" self.hdr = None"
]
},
{
Expand Down Expand Up @@ -645,6 +649,110 @@
"show_src(Path('tmp/test/testing_noall.py').read_text())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Check that the default header is written correctly:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"file_lines = Path('tmp/test/testing_noall.py').read_text().splitlines()\n",
"\n",
"comment_lines = (line for line in file_lines if line.startswith(\"# %% \"))\n",
"\n",
"for index, line in enumerate(comment_lines):\n",
" test_eq(line, f'# %% ../../01_export.ipynb {index}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Test making a module with `write_cell_hdrs`= `False`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Path('tmp/test/testing_noall.py')"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"am = ModuleMaker(dest='tmp', name='test.testing_noall', nb_path=Path.cwd()/'01_export.ipynb',\n",
" is_new=True, parse=False, write_cell_hdrs=False)\n",
"am.fname"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"```python\n",
"# AUTOGENERATED! DO NOT EDIT! File to edit: ../../01_export.ipynb.\n",
"\n",
"from __future__ import print_function\n",
"\n",
"#|export\n",
"def a(): ...\n",
"\n",
"#|export\n",
"class A:\n",
"\n",
"```"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cells = make_code_cells(\"from __future__ import print_function\", \"#|export\\ndef a(): ...\", \"#|export\\nclass A:\")\n",
"am.make(cells)\n",
"show_src(Path('tmp/test/testing_noall.py').read_text())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Check that cell headers are omitted when `write_cell_hdrs` is `False`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"file_lines = Path('tmp/test/testing_noall.py').read_text().splitlines()\n",
"comment_lines = list(line for line in file_lines if line.startswith(\"# %% \"))\n",
"test_eq(len(comment_lines), 0)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down

0 comments on commit 3780b52

Please sign in to comment.