Skip to content

Commit a196c2f

Browse files
authored
Merge pull request #1192 from omlnaut/master
nb_export now exports notebooks in ascending-filename-order
2 parents d7fd1e2 + 14ad26c commit a196c2f

File tree

2 files changed

+64
-15
lines changed

2 files changed

+64
-15
lines changed

nbdev/doclinks.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ def nbglob(path=None, skip_folder_re = '^[_.]', file_glob='*.ipynb', skip_file_r
110110
recursive=get_config().recursive
111111
res = globtastic(path, file_glob=file_glob, skip_folder_re=skip_folder_re,
112112
skip_file_re=skip_file_re, recursive=recursive, **kwargs)
113-
return res.map(Path) if as_path else res
113+
res = res.map(Path) if as_path else res
114+
return res
114115

115116
# %% ../nbs/api/doclinks.ipynb 21
116117
def nbglob_cli(
@@ -134,16 +135,16 @@ def nbdev_export(
134135
**kwargs):
135136
"Export notebooks in `path` to Python modules"
136137
if os.environ.get('IN_TEST',0): return
137-
files = nbglob(path=path, **kwargs)
138+
files = nbglob(path=path, as_path=True, **kwargs).sorted('name')
138139
for f in files: nb_export(f)
139140
add_init(get_config().lib_path)
140141
_build_modidx()
141142

142-
# %% ../nbs/api/doclinks.ipynb 24
143+
# %% ../nbs/api/doclinks.ipynb 26
143144
import importlib,ast
144145
from functools import lru_cache
145146

146-
# %% ../nbs/api/doclinks.ipynb 25
147+
# %% ../nbs/api/doclinks.ipynb 27
147148
def _find_mod(mod):
148149
mp,_,mr = mod.partition('/')
149150
spec = importlib.util.find_spec(mp)
@@ -166,7 +167,7 @@ def _get_exps(mod):
166167

167168
def _lineno(sym, fname): return _get_exps(fname).get(sym, None) if fname else None
168169

169-
# %% ../nbs/api/doclinks.ipynb 27
170+
# %% ../nbs/api/doclinks.ipynb 29
170171
def _qual_sym(s, settings):
171172
if not isinstance(s,tuple): return s
172173
nb,py = s
@@ -181,10 +182,10 @@ def _qual_syms(entries):
181182
if 'doc_host' not in settings: return entries
182183
return {'syms': {mod:_qual_mod(d, settings) for mod,d in entries['syms'].items()}, 'settings':settings}
183184

184-
# %% ../nbs/api/doclinks.ipynb 28
185+
# %% ../nbs/api/doclinks.ipynb 30
185186
_re_backticks = re.compile(r'`([^`\s]+)`')
186187

187-
# %% ../nbs/api/doclinks.ipynb 29
188+
# %% ../nbs/api/doclinks.ipynb 31
188189
@lru_cache(None)
189190
class NbdevLookup:
190191
"Mapping from symbol names to docs and source URLs"

nbs/api/doclinks.ipynb

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@
316316
" recursive=get_config().recursive\n",
317317
" res = globtastic(path, file_glob=file_glob, skip_folder_re=skip_folder_re,\n",
318318
" skip_file_re=skip_file_re, recursive=recursive, **kwargs)\n",
319-
" return res.map(Path) if as_path else res"
319+
" res = res.map(Path) if as_path else res\n",
320+
" return res"
320321
]
321322
},
322323
{
@@ -354,12 +355,59 @@
354355
" **kwargs):\n",
355356
" \"Export notebooks in `path` to Python modules\"\n",
356357
" if os.environ.get('IN_TEST',0): return\n",
357-
" files = nbglob(path=path, **kwargs)\n",
358+
" files = nbglob(path=path, as_path=True, **kwargs).sorted('name')\n",
358359
" for f in files: nb_export(f)\n",
359360
" add_init(get_config().lib_path)\n",
360361
" _build_modidx()"
361362
]
362363
},
364+
{
365+
"cell_type": "markdown",
366+
"metadata": {},
367+
"source": [
368+
"When exporting the notebooks, they should be exported in order of the filename to ensure deterministic build behaviour. The below test patches `nbglob` to return a non-ordered list, then checks that `nb_export` is still called on the notebooks in the right order:"
369+
]
370+
},
371+
{
372+
"cell_type": "code",
373+
"execution_count": null,
374+
"metadata": {},
375+
"outputs": [],
376+
"source": [
377+
"from copy import copy\n",
378+
"\n",
379+
"\n",
380+
"class EscapeException(Exception):\n",
381+
" pass\n",
382+
"\n",
383+
"def nb_export_mock(nb_path: str):\n",
384+
" expected = expected_order.pop()\n",
385+
" assert nb_path==expected, f'Expected {expected}, got {nb_path}'\n",
386+
" \n",
387+
" # escape from the outer function as the tests are done\n",
388+
" if not expected_order:\n",
389+
" raise EscapeException()\n",
390+
" \n",
391+
"# replace those functions by mocks, saving the original objects\n",
392+
"nbglob_save = copy(nbglob)\n",
393+
"nb_export_save = copy(nb_export)\n",
394+
"\n",
395+
"nbglob = lambda *args, **kwargs: L(['../../8.ipynb', 'api/3.ipynb', '4.ipynb']).map(Path)\n",
396+
"\n",
397+
"expected_order = reversed(L(['api/3.ipynb', '4.ipynb', '../../8.ipynb']).map(Path))\n",
398+
"#expected_order.reverse()\n",
399+
"nb_export = nb_export_mock\n",
400+
"\n",
401+
"try:\n",
402+
" nbdev_export()\n",
403+
"except EscapeException:\n",
404+
" pass # this silences the exception used to end nbdev_export early\n",
405+
"\n",
406+
"# restore original objects to make sure the notebook runs as intended\n",
407+
"nbglob = nbglob_save\n",
408+
"nb_export = nb_export_save"
409+
]
410+
},
363411
{
364412
"cell_type": "markdown",
365413
"metadata": {},
@@ -556,7 +604,7 @@
556604
"text/markdown": [
557605
"---\n",
558606
"\n",
559-
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L209){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
607+
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L211){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
560608
"\n",
561609
"### NbdevLookup.doc\n",
562610
"\n",
@@ -567,7 +615,7 @@
567615
"text/plain": [
568616
"---\n",
569617
"\n",
570-
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L209){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
618+
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L211){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
571619
"\n",
572620
"### NbdevLookup.doc\n",
573621
"\n",
@@ -650,7 +698,7 @@
650698
"text/markdown": [
651699
"---\n",
652700
"\n",
653-
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L214){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
701+
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L216){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
654702
"\n",
655703
"### NbdevLookup.code\n",
656704
"\n",
@@ -661,7 +709,7 @@
661709
"text/plain": [
662710
"---\n",
663711
"\n",
664-
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L214){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
712+
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L216){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
665713
"\n",
666714
"### NbdevLookup.code\n",
667715
"\n",
@@ -709,7 +757,7 @@
709757
"text/markdown": [
710758
"---\n",
711759
"\n",
712-
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L231){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
760+
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L233){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
713761
"\n",
714762
"### NbdevLookup.linkify\n",
715763
"\n",
@@ -718,7 +766,7 @@
718766
"text/plain": [
719767
"---\n",
720768
"\n",
721-
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L231){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
769+
"[source](https://github.com/fastai/nbdev/blob/master/nbdev/doclinks.py#L233){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n",
722770
"\n",
723771
"### NbdevLookup.linkify\n",
724772
"\n",

0 commit comments

Comments
 (0)