Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #769 #946

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 29 additions & 12 deletions nbdev/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@
__all__ = ['absolute_import', 'nbdev_update']

# %% ../nbs/09_API/05_sync.ipynb 3
from .imports import *
from .config import *
from .maker import *
from .process import *
from .export import *
from nbdev.imports import *
from nbdev.config import *
from nbdev.maker import *
from nbdev.process import *
from nbdev.export import *

from execnb.nbio import *
from fastcore.script import *
from fastcore.xtras import *

import ast,tempfile
import ast
from importlib import import_module

# %% ../nbs/09_API/05_sync.ipynb 5
def absolute_import(name, fname, level):
Expand All @@ -35,7 +36,8 @@ def _to_absolute(code, lib_name):

def _update_lib(nbname, nb_locs, lib_name=None):
if lib_name is None: lib_name = get_config().lib_name
nbp = NBProcessor(nbname, ExportModuleProc(), rm_directives=False)
absnm = get_config().path('lib_path')/nbname
nbp = NBProcessor(fq_nm, ExportModuleProc(), rm_directives=False)
nb = nbp.nb
nbp.process()

Expand All @@ -45,17 +47,32 @@ def _update_lib(nbname, nb_locs, lib_name=None):
lines = cell.source.splitlines(True)
directives = ''.join(cell.source.splitlines(True)[:len(cell.directives_)])
cell.source = directives + _to_absolute(code, lib_name)
write_nb(nb, nbname)
write_nb(nb, absnm)

# %% ../nbs/09_API/05_sync.ipynb 10
@functools.lru_cache(maxsize=None)
def _mod_files():
mdir = get_config().path('lib_path').parent
midx = import_module(f'{get_config().lib_name}._modidx')
return L(files for mod in midx.d['syms'].values() for _,files in mod.values()).unique()

# %% ../nbs/09_API/05_sync.ipynb 12
def _get_call(s):
top,*rest = s.splitlines()
return (*top.split(),'\n'.join(rest))

@call_parse
def nbdev_update(fname:str): # A Python file name to update
"Propagate change in modules matching `fname` to notebooks that created them"
if os.environ.get('IN_TEST',0): return
def _script2notebook(fname:str):
code_cells = Path(fname).read_text().split("\n# %% ")[1:]
locs = L(_get_call(s) for s in code_cells if not s.startswith('auto '))
for nbname,nb_locs in groupby(locs, 0).items(): _update_lib(nbname, nb_locs)

@call_parse
def nbdev_update(fname:str=None): # A Python file name to update
"Propagate change in modules matching `fname` to notebooks that created them"
if fname and fname.endswith('.ipynb'): raise ValueError("`nbdev_update` operates on .py files. If you wish to convert notebooks instead, see `nbdev_export`.")
if os.environ.get('IN_TEST',0): return
fname = Path(fname or get_config().path('lib_path'))
lib_dir = get_config().path("lib_path").parent
files = globtastic(fname, file_glob='*.py').filter(lambda x: str(Path(x).absolute().relative_to(lib_dir) in _mod_files()))
files.map(_script2notebook)

47 changes: 40 additions & 7 deletions nbs/09_API/05_sync.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
"from fastcore.script import *\n",
"from fastcore.xtras import *\n",
"\n",
"import ast,tempfile"
"import ast,tempfiledd\n",
"from importlib import import_module"
]
},
{
Expand Down Expand Up @@ -120,7 +121,8 @@
"\n",
"def _update_lib(nbname, nb_locs, lib_name=None):\n",
" if lib_name is None: lib_name = get_config().lib_name\n",
" nbp = NBProcessor(nbname, ExportModuleProc(), rm_directives=False)\n",
" absnm = get_config().path('lib_path')/nbname\n",
" nbp = NBProcessor(fq_nm, ExportModuleProc(), rm_directives=False)\n",
" nb = nbp.nb\n",
" nbp.process()\n",
"\n",
Expand All @@ -130,7 +132,31 @@
" lines = cell.source.splitlines(True)\n",
" directives = ''.join(cell.source.splitlines(True)[:len(cell.directives_)])\n",
" cell.source = directives + _to_absolute(code, lib_name)\n",
" write_nb(nb, nbname)"
" write_nb(nb, absnm)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#|export\n",
"@functools.lru_cache(maxsize=None)\n",
"def _mod_files():\n",
" mdir = get_config().path('lib_path').parent\n",
" midx = import_module(f'{get_config().lib_name}._modidx')\n",
" return L(files for mod in midx.d['syms'].values() for _,files in mod.values()).unique()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#|hide\n",
"assert min(_mod_files().map(lambda x: x.endswith('.py'))) is True"
]
},
{
Expand All @@ -144,13 +170,20 @@
" top,*rest = s.splitlines()\n",
" return (*top.split(),'\\n'.join(rest))\n",
"\n",
"def _script2notebook(fname:str):\n",
" code_cells = Path(fname).read_text().split(\"\\n# %% \")[1:]\n",
" locs = L(_get_call(s) for s in code_cells if not s.startswith('auto '))\n",
" for nbname,nb_locs in groupby(locs, 0).items(): _update_lib(nbname, nb_locs)\n",
"\n",
"@call_parse\n",
"def nbdev_update(fname:str): # A Python file name to update\n",
"def nbdev_update(fname:str=None): # A Python file name to update\n",
" \"Propagate change in modules matching `fname` to notebooks that created them\"\n",
" if fname and fname.endswith('.ipynb'): raise ValueError(\"`nbdev_update` operates on .py files. If you wish to convert notebooks instead, see `nbdev_export`.\")\n",
" if os.environ.get('IN_TEST',0): return\n",
" code_cells = Path(fname).read_text().split(\"\\n# %% \")[1:]\n",
" locs = L(_get_call(s) for s in code_cells if not s.startswith('auto '))\n",
" for nbname,nb_locs in groupby(locs, 0).items(): _update_lib(nbname, nb_locs)"
" fname = Path(fname or get_config().path('lib_path'))\n",
" lib_dir = get_config().path(\"lib_path\").parent\n",
" files = globtastic(fname, file_glob='*.py').filter(lambda x: str(Path(x).absolute().relative_to(lib_dir) in _mod_files()))\n",
" files.map(_script2notebook)\n"
]
},
{
Expand Down