nbdev 2.4.8__py3-none-any.whl → 2.4.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nbdev/__init__.py +1 -1
- nbdev/_modidx.py +1 -7
- nbdev/clean.py +22 -19
- nbdev/cli.py +15 -16
- nbdev/config.py +29 -28
- nbdev/diff.py +9 -9
- nbdev/doclinks.py +29 -31
- nbdev/export.py +7 -7
- nbdev/frontmatter.py +4 -4
- nbdev/maker.py +22 -22
- nbdev/merge.py +10 -10
- nbdev/migrate.py +18 -18
- nbdev/process.py +15 -15
- nbdev/processors.py +26 -26
- nbdev/qmd.py +9 -9
- nbdev/quarto.py +27 -27
- nbdev/release.py +29 -29
- nbdev/serve.py +5 -5
- nbdev/showdoc.py +9 -55
- nbdev/sync.py +14 -11
- nbdev/test.py +5 -5
- {nbdev-2.4.8.dist-info → nbdev-2.4.11.dist-info}/METADATA +3 -2
- nbdev-2.4.11.dist-info/RECORD +30 -0
- nbdev-2.4.8.dist-info/RECORD +0 -30
- {nbdev-2.4.8.dist-info → nbdev-2.4.11.dist-info}/WHEEL +0 -0
- {nbdev-2.4.8.dist-info → nbdev-2.4.11.dist-info}/entry_points.txt +0 -0
- {nbdev-2.4.8.dist-info → nbdev-2.4.11.dist-info}/licenses/LICENSE +0 -0
- {nbdev-2.4.8.dist-info → nbdev-2.4.11.dist-info}/top_level.txt +0 -0
nbdev/doclinks.py
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/05_doclinks.ipynb.
|
|
4
4
|
|
|
5
|
-
# %% auto 0
|
|
5
|
+
# %% auto #0
|
|
6
6
|
__all__ = ['typs', 'bset', 'patch_name', 'nbglob', 'nbglob_cli', 'nbdev_export', 'create_index', 'NbdevLookup']
|
|
7
7
|
|
|
8
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
8
|
+
# %% ../nbs/api/05_doclinks.ipynb #6476cba7
|
|
9
9
|
from .config import *
|
|
10
10
|
from .maker import *
|
|
11
11
|
from .export import *
|
|
@@ -29,7 +29,7 @@ from types import ModuleType
|
|
|
29
29
|
|
|
30
30
|
from importlib.metadata import entry_points
|
|
31
31
|
|
|
32
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
32
|
+
# %% ../nbs/api/05_doclinks.ipynb #a53fc2bb
|
|
33
33
|
def _sym_nm(klas, sym): return f'{unparse(klas).strip()}.{sym.name}'
|
|
34
34
|
|
|
35
35
|
def _binop_leafs(bo, o):
|
|
@@ -50,32 +50,30 @@ def patch_name(o):
|
|
|
50
50
|
else: return o.name
|
|
51
51
|
return _sym_nm(a,o)
|
|
52
52
|
|
|
53
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
53
|
+
# %% ../nbs/api/05_doclinks.ipynb #7552f6c8
|
|
54
54
|
def _iter_py_cells(p):
|
|
55
55
|
"Yield cells from an exported Python file."
|
|
56
56
|
p = Path(p)
|
|
57
57
|
cells = p.read_text(encoding='utf-8').split("\n# %% ")
|
|
58
|
-
has_cell_number = get_config().cell_number
|
|
59
58
|
for cell in cells[1:]:
|
|
60
59
|
top,code = cell.split('\n', 1)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
nb_path = None if nb=='auto' else (p.parent/nb).resolve() # NB paths are stored relative to .py file
|
|
60
|
+
parts = top.split()
|
|
61
|
+
# Format: "path/to/nb.ipynb #cell_id"
|
|
62
|
+
if len(parts) >= 2 and parts[-1].startswith('#'):
|
|
63
|
+
cell_id = parts[-1][1:] # Remove the '#' prefix
|
|
64
|
+
nb = ' '.join(parts[:-1])
|
|
65
|
+
else:
|
|
66
|
+
raise ValueError(f"Cell ID required but not found in '{p}' at:\n```\n# %% {top}\n```\n"
|
|
67
|
+
"Run `nbdev_export` to regenerate .py files with cell IDs.")
|
|
68
|
+
if nb=='auto': continue # Skip auto-generated __all__ cell
|
|
69
|
+
nb_path = (p.parent/nb).resolve() # NB paths are stored relative to .py file
|
|
72
70
|
if code.endswith('\n'): code=code[:-1]
|
|
73
|
-
yield AttrDict(nb=nb,
|
|
71
|
+
yield AttrDict(nb=nb, cell_id=cell_id, code=code, nb_path=nb_path, py_path=p.resolve())
|
|
74
72
|
|
|
75
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
73
|
+
# %% ../nbs/api/05_doclinks.ipynb #d1c22276
|
|
76
74
|
def _nbpath2html(p): return p.with_name(re.sub(r'^\d+[a-zA-Z0-9]*_', '', p.name.lower())).with_suffix('.html')
|
|
77
75
|
|
|
78
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
76
|
+
# %% ../nbs/api/05_doclinks.ipynb #f57b8709
|
|
79
77
|
def _get_modidx(py_path, code_root, nbs_path):
|
|
80
78
|
"Get module symbol index for a Python source file"
|
|
81
79
|
cfg = get_config()
|
|
@@ -97,7 +95,7 @@ def _get_modidx(py_path, code_root, nbs_path):
|
|
|
97
95
|
if isinstance(t2, _def_types): _stor(f'{tree.name}.{t2.name}')
|
|
98
96
|
return {mod_name: d}
|
|
99
97
|
|
|
100
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
98
|
+
# %% ../nbs/api/05_doclinks.ipynb #587df0d4
|
|
101
99
|
def _build_modidx(dest=None, nbs_path=None, skip_exists=False):
|
|
102
100
|
"Create _modidx.py"
|
|
103
101
|
if dest is None: dest = get_config().lib_path
|
|
@@ -117,7 +115,7 @@ def _build_modidx(dest=None, nbs_path=None, skip_exists=False):
|
|
|
117
115
|
except ValueError: pass
|
|
118
116
|
idxfile.write_text("# Autogenerated by nbdev\n\nd = "+pformat(res, width=140, indent=2, compact=True)+'\n')
|
|
119
117
|
|
|
120
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
118
|
+
# %% ../nbs/api/05_doclinks.ipynb #0b3e1605
|
|
121
119
|
@delegates(globtastic)
|
|
122
120
|
def nbglob(path=None, skip_folder_re = '^[_.]', file_glob='*.ipynb', skip_file_re='^[_.]', key='nbs_path', as_path=False, **kwargs):
|
|
123
121
|
"Find all files in a directory matching an extension given a config key."
|
|
@@ -127,7 +125,7 @@ def nbglob(path=None, skip_folder_re = '^[_.]', file_glob='*.ipynb', skip_file_r
|
|
|
127
125
|
skip_file_re=skip_file_re, recursive=recursive, **kwargs)
|
|
128
126
|
return res.map(Path) if as_path else res
|
|
129
127
|
|
|
130
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
128
|
+
# %% ../nbs/api/05_doclinks.ipynb #f0922957
|
|
131
129
|
def nbglob_cli(
|
|
132
130
|
path:str=None, # Path to notebooks
|
|
133
131
|
symlinks:bool=False, # Follow symlinks?
|
|
@@ -141,7 +139,7 @@ def nbglob_cli(
|
|
|
141
139
|
return nbglob(path, symlinks=symlinks, file_glob=file_glob, file_re=file_re, folder_re=folder_re,
|
|
142
140
|
skip_file_glob=skip_file_glob, skip_file_re=skip_file_re, skip_folder_re=skip_folder_re)
|
|
143
141
|
|
|
144
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
142
|
+
# %% ../nbs/api/05_doclinks.ipynb #5e6fbe08
|
|
145
143
|
@call_parse
|
|
146
144
|
@delegates(nbglob_cli)
|
|
147
145
|
def nbdev_export(
|
|
@@ -159,11 +157,11 @@ def nbdev_export(
|
|
|
159
157
|
add_init(get_config().lib_path)
|
|
160
158
|
_build_modidx()
|
|
161
159
|
|
|
162
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
160
|
+
# %% ../nbs/api/05_doclinks.ipynb #3134c22b
|
|
163
161
|
typs = 'module','class','method','function'
|
|
164
162
|
bset = set(dir(builtins))
|
|
165
163
|
|
|
166
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
164
|
+
# %% ../nbs/api/05_doclinks.ipynb #f5fceca8
|
|
167
165
|
def create_index(url, pre=None):
|
|
168
166
|
"Create a documentation index from a sphinx inventory file at `url`, with optional prefix `pre`"
|
|
169
167
|
try: from sphinx.util.inventory import InventoryFile
|
|
@@ -181,11 +179,11 @@ def create_index(url, pre=None):
|
|
|
181
179
|
if modparts: syms['.'.join(modparts)][k] = v
|
|
182
180
|
return syms
|
|
183
181
|
|
|
184
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
182
|
+
# %% ../nbs/api/05_doclinks.ipynb #98a6ee7a
|
|
185
183
|
import importlib,ast
|
|
186
184
|
from functools import lru_cache
|
|
187
185
|
|
|
188
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
186
|
+
# %% ../nbs/api/05_doclinks.ipynb #c30ec2fe
|
|
189
187
|
def _find_mod(mod):
|
|
190
188
|
mp,_,mr = mod.partition('/')
|
|
191
189
|
spec = importlib.util.find_spec(mp)
|
|
@@ -209,7 +207,7 @@ def _get_exps(mod):
|
|
|
209
207
|
|
|
210
208
|
def _lineno(sym, fname): return _get_exps(fname).get(sym, None) if fname else None
|
|
211
209
|
|
|
212
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
210
|
+
# %% ../nbs/api/05_doclinks.ipynb #c1b8c9fa
|
|
213
211
|
def _qual_sym(s, settings):
|
|
214
212
|
"Get qualified nb, py, and github paths for a symbol s"
|
|
215
213
|
if not isinstance(s,tuple): return s
|
|
@@ -225,10 +223,10 @@ def _qual_syms(entries):
|
|
|
225
223
|
if 'doc_host' not in settings: return entries
|
|
226
224
|
return {'syms': {mod:_qual_mod(d, settings) for mod,d in entries['syms'].items()}, 'settings':settings}
|
|
227
225
|
|
|
228
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
226
|
+
# %% ../nbs/api/05_doclinks.ipynb #53505fa4
|
|
229
227
|
_re_backticks = re.compile(r'`([^`\s]+?)(?:\(\))?`')
|
|
230
228
|
|
|
231
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
229
|
+
# %% ../nbs/api/05_doclinks.ipynb #3a24b883
|
|
232
230
|
@lru_cache(None)
|
|
233
231
|
def _build_lookup_table(strip_libs=None, incl_libs=None, skip_mods=None):
|
|
234
232
|
cfg = get_config()
|
|
@@ -260,7 +258,7 @@ def _build_lookup_table(strip_libs=None, incl_libs=None, skip_mods=None):
|
|
|
260
258
|
py_syms = merge(stripped, py_syms)
|
|
261
259
|
return entries,py_syms
|
|
262
260
|
|
|
263
|
-
# %% ../nbs/api/05_doclinks.ipynb
|
|
261
|
+
# %% ../nbs/api/05_doclinks.ipynb #3257b6bf
|
|
264
262
|
class NbdevLookup:
|
|
265
263
|
"Mapping from symbol names to docs and source URLs"
|
|
266
264
|
def __init__(self, strip_libs=None, incl_libs=None, skip_mods=None, ns=None):
|
nbdev/export.py
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/04_export.ipynb.
|
|
4
4
|
|
|
5
|
-
# %% auto 0
|
|
5
|
+
# %% auto #0
|
|
6
6
|
__all__ = ['ExportModuleProc', 'black_format', 'scrub_magics', 'optional_procs', 'nb_export']
|
|
7
7
|
|
|
8
|
-
# %% ../nbs/api/04_export.ipynb
|
|
8
|
+
# %% ../nbs/api/04_export.ipynb #3b932371
|
|
9
9
|
from .config import *
|
|
10
10
|
from .maker import *
|
|
11
11
|
from .imports import *
|
|
@@ -18,7 +18,7 @@ from fastcore.meta import *
|
|
|
18
18
|
|
|
19
19
|
from collections import defaultdict
|
|
20
20
|
|
|
21
|
-
# %% ../nbs/api/04_export.ipynb
|
|
21
|
+
# %% ../nbs/api/04_export.ipynb #a62f3967
|
|
22
22
|
class ExportModuleProc:
|
|
23
23
|
"A processor which exports code to a module"
|
|
24
24
|
def begin(self): self.modules,self.in_all = defaultdict(L),defaultdict(L)
|
|
@@ -33,7 +33,7 @@ class ExportModuleProc:
|
|
|
33
33
|
if cell.cell_type=='markdown' and src.startswith('# '): self.modules['#'].append(cell)
|
|
34
34
|
_exports_=_export_
|
|
35
35
|
|
|
36
|
-
# %% ../nbs/api/04_export.ipynb
|
|
36
|
+
# %% ../nbs/api/04_export.ipynb #6f524839
|
|
37
37
|
def black_format(cell, # Cell to format
|
|
38
38
|
force=False): # Turn black formatting on regardless of settings.ini
|
|
39
39
|
"Processor to format code with `black`"
|
|
@@ -47,7 +47,7 @@ def black_format(cell, # Cell to format
|
|
|
47
47
|
try: cell.source = _format_str(cell.source).strip()
|
|
48
48
|
except: pass
|
|
49
49
|
|
|
50
|
-
# %% ../nbs/api/04_export.ipynb
|
|
50
|
+
# %% ../nbs/api/04_export.ipynb #aed6a875
|
|
51
51
|
# includes the newline, because calling .strip() would affect all cells.
|
|
52
52
|
_magics_pattern = re.compile(r'^\s*(%%|%).*\n?', re.MULTILINE)
|
|
53
53
|
|
|
@@ -59,14 +59,14 @@ def scrub_magics(cell): # Cell to format
|
|
|
59
59
|
try: cell.source = _magics_pattern.sub('', cell.source)
|
|
60
60
|
except: pass
|
|
61
61
|
|
|
62
|
-
# %% ../nbs/api/04_export.ipynb
|
|
62
|
+
# %% ../nbs/api/04_export.ipynb #d4a5fd8c
|
|
63
63
|
import nbdev.export
|
|
64
64
|
def optional_procs():
|
|
65
65
|
"An explicit list of processors that could be used by `nb_export`"
|
|
66
66
|
return L([p for p in nbdev.export.__all__
|
|
67
67
|
if p not in ["nb_export", "nb_export_cli", "ExportModuleProc", "optional_procs"]])
|
|
68
68
|
|
|
69
|
-
# %% ../nbs/api/04_export.ipynb
|
|
69
|
+
# %% ../nbs/api/04_export.ipynb #76717e36
|
|
70
70
|
def nb_export(nbname:str, # Filename of notebook
|
|
71
71
|
lib_path:str=None, # Path to destination library. If not in a nbdev project, defaults to current directory.
|
|
72
72
|
procs=None, # Processors to use
|
nbdev/frontmatter.py
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/09_frontmatter.ipynb.
|
|
4
4
|
|
|
5
|
-
# %% auto 0
|
|
5
|
+
# %% auto #0
|
|
6
6
|
__all__ = ['FrontmatterProc']
|
|
7
7
|
|
|
8
|
-
# %% ../nbs/api/09_frontmatter.ipynb
|
|
8
|
+
# %% ../nbs/api/09_frontmatter.ipynb #2398f5ef-06d3-4890-8a54-7cf4f81f3894
|
|
9
9
|
from .imports import *
|
|
10
10
|
from .process import *
|
|
11
11
|
from .doclinks import _nbpath2html
|
|
@@ -14,7 +14,7 @@ from execnb.nbio import *
|
|
|
14
14
|
from fastcore.imports import *
|
|
15
15
|
import yaml
|
|
16
16
|
|
|
17
|
-
# %% ../nbs/api/09_frontmatter.ipynb
|
|
17
|
+
# %% ../nbs/api/09_frontmatter.ipynb #6d13ecdb
|
|
18
18
|
_RE_FM_BASE=r'''^---\s*
|
|
19
19
|
(.*?\S+.*?)
|
|
20
20
|
---\s*'''
|
|
@@ -42,7 +42,7 @@ def _md2dict(s:str):
|
|
|
42
42
|
except Exception as e: warn(f'Failed to create YAML dict for:\n{r}\n\n{e}\n')
|
|
43
43
|
return res
|
|
44
44
|
|
|
45
|
-
# %% ../nbs/api/09_frontmatter.ipynb
|
|
45
|
+
# %% ../nbs/api/09_frontmatter.ipynb #1b5d9d32
|
|
46
46
|
def _dict2fm(d): return f'---\n{yaml.dump(d)}\n---\n\n'
|
|
47
47
|
def _insertfm(nb, fm): nb.cells.insert(0, mk_cell(_dict2fm(fm), 'raw'))
|
|
48
48
|
|
nbdev/maker.py
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/02_maker.ipynb.
|
|
4
4
|
|
|
5
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
5
|
+
# %% ../nbs/api/02_maker.ipynb #aac32462
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
-
# %% auto 0
|
|
8
|
+
# %% auto #0
|
|
9
9
|
__all__ = ['find_var', 'read_var', 'update_var', 'ModuleMaker', 'decor_id', 'make_code_cells', 'relative_import', 'update_import']
|
|
10
10
|
|
|
11
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
11
|
+
# %% ../nbs/api/02_maker.ipynb #ae4d461b
|
|
12
12
|
from .config import *
|
|
13
13
|
from .imports import *
|
|
14
14
|
|
|
@@ -23,7 +23,7 @@ from collections import defaultdict
|
|
|
23
23
|
from pprint import pformat
|
|
24
24
|
from textwrap import TextWrapper
|
|
25
25
|
|
|
26
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
26
|
+
# %% ../nbs/api/02_maker.ipynb #c2d38766
|
|
27
27
|
def find_var(lines, varname):
|
|
28
28
|
"Find the line numbers where `varname` is defined in `lines`"
|
|
29
29
|
start = first(i for i,o in enumerate(lines) if o.startswith(varname))
|
|
@@ -33,7 +33,7 @@ def find_var(lines, varname):
|
|
|
33
33
|
end = first(i for i,o in enumerate(lines[start+1:]) if o[:1] not in empty)
|
|
34
34
|
return start,len(lines) if end is None else (end+start+1)
|
|
35
35
|
|
|
36
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
36
|
+
# %% ../nbs/api/02_maker.ipynb #b231d55b
|
|
37
37
|
def read_var(code, varname):
|
|
38
38
|
"Eval and return the value of `varname` defined in `code`"
|
|
39
39
|
lines = code.splitlines()
|
|
@@ -44,7 +44,7 @@ def read_var(code, varname):
|
|
|
44
44
|
try: return eval('\n'.join(res))
|
|
45
45
|
except SyntaxError: raise Exception('\n'.join(res)) from None
|
|
46
46
|
|
|
47
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
47
|
+
# %% ../nbs/api/02_maker.ipynb #be8307b0
|
|
48
48
|
def update_var(varname, func, fn=None, code=None):
|
|
49
49
|
"Update the definition of `varname` in file `fn`, by calling `func` with the current definition"
|
|
50
50
|
if fn:
|
|
@@ -60,7 +60,7 @@ def update_var(varname, func, fn=None, code=None):
|
|
|
60
60
|
if fn: fn.write_text(code)
|
|
61
61
|
else: return code
|
|
62
62
|
|
|
63
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
63
|
+
# %% ../nbs/api/02_maker.ipynb #a676a7ea
|
|
64
64
|
class ModuleMaker:
|
|
65
65
|
"Helper class to create exported library from notebook source cells"
|
|
66
66
|
def __init__(self, dest, name, nb_path, is_new=True, parse=True, solo_nb=False):
|
|
@@ -72,12 +72,12 @@ class ModuleMaker:
|
|
|
72
72
|
self.dest2nb = nb_path.relpath(self.fname.parent).as_posix()
|
|
73
73
|
self.hdr = f"# %% {self.dest2nb}"
|
|
74
74
|
|
|
75
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
75
|
+
# %% ../nbs/api/02_maker.ipynb #e87fd7a3
|
|
76
76
|
def decor_id(d):
|
|
77
77
|
"`id` attr of decorator, regardless of whether called as function or bare"
|
|
78
78
|
return d.id if hasattr(d, 'id') else nested_attr(d, 'func.id', '')
|
|
79
79
|
|
|
80
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
80
|
+
# %% ../nbs/api/02_maker.ipynb #31c81084
|
|
81
81
|
_def_types = ast.FunctionDef,ast.AsyncFunctionDef,ast.ClassDef
|
|
82
82
|
_assign_types = ast.AnnAssign, ast.Assign, ast.AugAssign
|
|
83
83
|
|
|
@@ -88,7 +88,7 @@ def _all_targets(a): return L(getattr(a,'elts',a))
|
|
|
88
88
|
def _filt_dec(x): return decor_id(x).startswith('patch')
|
|
89
89
|
def _wants(o): return isinstance(o,_def_types) and not any(L(o.decorator_list).filter(_filt_dec))
|
|
90
90
|
|
|
91
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
91
|
+
# %% ../nbs/api/02_maker.ipynb #59156e51
|
|
92
92
|
def _targets(o): return [o.target] if isinstance(o, (ast.AugAssign,ast.AnnAssign)) else o.targets
|
|
93
93
|
|
|
94
94
|
@patch
|
|
@@ -107,10 +107,10 @@ def make_all(self:ModuleMaker, cells):
|
|
|
107
107
|
exports = (assign_targs.attrgot('id')+syms).filter(lambda o: o and o[0]!='_')
|
|
108
108
|
return (exports+all_vals).unique()
|
|
109
109
|
|
|
110
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
110
|
+
# %% ../nbs/api/02_maker.ipynb #ea782f32
|
|
111
111
|
def make_code_cells(*ss): return dict2nb({'cells':L(ss).map(mk_cell)}).cells
|
|
112
112
|
|
|
113
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
113
|
+
# %% ../nbs/api/02_maker.ipynb #a2546836
|
|
114
114
|
def relative_import(name, fname, level=0):
|
|
115
115
|
"Convert a module `name` to a name relative to `fname`"
|
|
116
116
|
assert not level
|
|
@@ -122,7 +122,7 @@ def relative_import(name, fname, level=0):
|
|
|
122
122
|
if not all(o=='.' for o in res): res='.'+res
|
|
123
123
|
return res.replace(os.path.sep, ".")
|
|
124
124
|
|
|
125
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
125
|
+
# %% ../nbs/api/02_maker.ipynb #d031e0e0
|
|
126
126
|
# Based on https://github.com/thonny/thonny/blob/master/thonny/ast_utils.py
|
|
127
127
|
def _mark_text_ranges(
|
|
128
128
|
source: str|bytes, # Source code to add ranges to
|
|
@@ -140,7 +140,7 @@ def _mark_text_ranges(
|
|
|
140
140
|
child.end_lineno, child.end_col_offset = child.lineno, child.col_offset+2
|
|
141
141
|
return root.body
|
|
142
142
|
|
|
143
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
143
|
+
# %% ../nbs/api/02_maker.ipynb #655d3b95
|
|
144
144
|
def update_import(source, tree, libname, f=relative_import):
|
|
145
145
|
if not tree: return
|
|
146
146
|
if sys.version_info < (3,8): tree = _mark_text_ranges(source)
|
|
@@ -160,7 +160,7 @@ def import2relative(cell:NbCell, libname):
|
|
|
160
160
|
src = update_import(cell.source, cell.parsed_(), libname)
|
|
161
161
|
if src: cell.set_source(src)
|
|
162
162
|
|
|
163
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
163
|
+
# %% ../nbs/api/02_maker.ipynb #c9e055fe
|
|
164
164
|
@patch
|
|
165
165
|
def _last_future(self:ModuleMaker, cells):
|
|
166
166
|
"Returns the location of a `__future__` in `cells`"
|
|
@@ -169,13 +169,13 @@ def _last_future(self:ModuleMaker, cells):
|
|
|
169
169
|
isinstance(t,ast.ImportFrom) and t.module=='__future__' for t in tree))+1
|
|
170
170
|
except ValueError: return 0
|
|
171
171
|
|
|
172
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
172
|
+
# %% ../nbs/api/02_maker.ipynb #8b552b48
|
|
173
173
|
def _import2relative(cells, lib_path=None):
|
|
174
174
|
"Converts `cells` to use `import2relative` based on `lib_path`"
|
|
175
175
|
if lib_path is None: lib_path = get_config().lib_path
|
|
176
176
|
for cell in cells: cell.import2relative(lib_path)
|
|
177
177
|
|
|
178
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
178
|
+
# %% ../nbs/api/02_maker.ipynb #5bff9d71
|
|
179
179
|
def _retr_mdoc(cells):
|
|
180
180
|
"Search for md meta quote line, used to create module docstring"
|
|
181
181
|
md1 = first(o for o in cells if o.cell_type=='markdown' and o.source.startswith('# '))
|
|
@@ -185,7 +185,7 @@ def _retr_mdoc(cells):
|
|
|
185
185
|
summ = summ.lstrip('> ').strip()
|
|
186
186
|
return f'"""{summ}"""\n\n' if summ else ''
|
|
187
187
|
|
|
188
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
188
|
+
# %% ../nbs/api/02_maker.ipynb #cdd205d6
|
|
189
189
|
@patch
|
|
190
190
|
def make(self:ModuleMaker, cells, all_cells=None, lib_path=None):
|
|
191
191
|
"Write module containing `cells` with `__all__` generated from `all_cells`"
|
|
@@ -208,11 +208,11 @@ def make(self:ModuleMaker, cells, all_cells=None, lib_path=None):
|
|
|
208
208
|
f.write(_retr_mdoc(cells))
|
|
209
209
|
f.write(f"# AUTOGENERATED! DO NOT EDIT! File to edit: {self.dest2nb}.")
|
|
210
210
|
if last_future > 0: write_cells(cells[:last_future], self.hdr, f)
|
|
211
|
-
if self.parse and not self.solo_nb: f.write(f"\n\n# %% auto 0\n__all__ = {all_str}")
|
|
212
|
-
write_cells(cells[last_future:], self.hdr, f,
|
|
211
|
+
if self.parse and not self.solo_nb: f.write(f"\n\n# %% auto #0\n__all__ = {all_str}")
|
|
212
|
+
write_cells(cells[last_future:], self.hdr, f, solo_nb=self.solo_nb)
|
|
213
213
|
f.write('\n')
|
|
214
214
|
|
|
215
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
215
|
+
# %% ../nbs/api/02_maker.ipynb #6515a9d7
|
|
216
216
|
@patch
|
|
217
217
|
def _update_all(self:ModuleMaker, all_cells, alls):
|
|
218
218
|
return pformat(alls + self.make_all(all_cells), width=160)
|
|
@@ -224,7 +224,7 @@ def _make_exists(self:ModuleMaker, cells, all_cells=None):
|
|
|
224
224
|
update_var('__all__', partial(self._update_all, all_cells), fn=self.fname)
|
|
225
225
|
with self.fname.open('a', encoding="utf-8") as f: write_cells(cells, self.hdr, f)
|
|
226
226
|
|
|
227
|
-
# %% ../nbs/api/02_maker.ipynb
|
|
227
|
+
# %% ../nbs/api/02_maker.ipynb #63c95e1e
|
|
228
228
|
def _basic_export_nb2(fname, name, dest=None):
|
|
229
229
|
"A basic exporter to bootstrap nbdev using `ModuleMaker`"
|
|
230
230
|
if dest is None: dest = get_config().lib_path
|
nbdev/merge.py
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/07_merge.ipynb.
|
|
4
4
|
|
|
5
|
-
# %% auto 0
|
|
5
|
+
# %% auto #0
|
|
6
6
|
__all__ = ['conf_re', 'unpatch', 'nbdev_fix', 'nbdev_merge']
|
|
7
7
|
|
|
8
|
-
# %% ../nbs/api/07_merge.ipynb
|
|
8
|
+
# %% ../nbs/api/07_merge.ipynb #f2c8f7ea
|
|
9
9
|
from .imports import *
|
|
10
10
|
from .config import *
|
|
11
11
|
from .export import *
|
|
@@ -18,7 +18,7 @@ from fastcore import shutil
|
|
|
18
18
|
import subprocess
|
|
19
19
|
from difflib import SequenceMatcher
|
|
20
20
|
|
|
21
|
-
# %% ../nbs/api/07_merge.ipynb
|
|
21
|
+
# %% ../nbs/api/07_merge.ipynb #b496277c
|
|
22
22
|
_BEG,_MID,_END = '<'*7,'='*7,'>'*7
|
|
23
23
|
conf_re = re.compile(rf'^{_BEG}\s+(\S+)\n(.*?)^{_MID}\n(.*?)^{_END}\s+([\S ]+)\n', re.MULTILINE|re.DOTALL)
|
|
24
24
|
|
|
@@ -28,7 +28,7 @@ def _unpatch_f(before, cb1, cb2, c, r):
|
|
|
28
28
|
r.append(c)
|
|
29
29
|
return cb2
|
|
30
30
|
|
|
31
|
-
# %% ../nbs/api/07_merge.ipynb
|
|
31
|
+
# %% ../nbs/api/07_merge.ipynb #92a460f3
|
|
32
32
|
def unpatch(s:str):
|
|
33
33
|
"Takes a string with conflict markers and returns the two original files, and their branch names"
|
|
34
34
|
*main,last = conf_re.split(s)
|
|
@@ -38,7 +38,7 @@ def unpatch(s:str):
|
|
|
38
38
|
c2b = _unpatch_f(before, c2b, c2_branch, c2, r2)
|
|
39
39
|
return ''.join(r1+[last]), ''.join(r2+[last]), c1b, c2b
|
|
40
40
|
|
|
41
|
-
# %% ../nbs/api/07_merge.ipynb
|
|
41
|
+
# %% ../nbs/api/07_merge.ipynb #35ff58e3
|
|
42
42
|
def _make_md(code): return [dict(source=f'`{code}`', cell_type="markdown", metadata={})]
|
|
43
43
|
def _make_conflict(a,b, branch1, branch2):
|
|
44
44
|
return _make_md(f'{_BEG} {branch1}') + a+_make_md(_MID)+b + _make_md(f'{_END} {branch2}')
|
|
@@ -55,7 +55,7 @@ def _merge_cells(a, b, brancha, branchb, theirs):
|
|
|
55
55
|
prev_sa,prev_sb = sa+sz,sb+sz
|
|
56
56
|
return res,conflict
|
|
57
57
|
|
|
58
|
-
# %% ../nbs/api/07_merge.ipynb
|
|
58
|
+
# %% ../nbs/api/07_merge.ipynb #cc492d30
|
|
59
59
|
@call_parse
|
|
60
60
|
def nbdev_fix(nbname:str, # Notebook filename to fix
|
|
61
61
|
outname:str=None, # Filename of output notebook (defaults to `nbname`)
|
|
@@ -77,12 +77,12 @@ def nbdev_fix(nbname:str, # Notebook filename to fix
|
|
|
77
77
|
else: print("Successfully merged conflicts!")
|
|
78
78
|
return conflict
|
|
79
79
|
|
|
80
|
-
# %% ../nbs/api/07_merge.ipynb
|
|
80
|
+
# %% ../nbs/api/07_merge.ipynb #481a6bdf
|
|
81
81
|
def _git_branch_merge():
|
|
82
82
|
try: return only(v for k,v in os.environ.items() if k.startswith('GITHEAD'))
|
|
83
83
|
except ValueError: return
|
|
84
84
|
|
|
85
|
-
# %% ../nbs/api/07_merge.ipynb
|
|
85
|
+
# %% ../nbs/api/07_merge.ipynb #801ba5a9
|
|
86
86
|
def _git_rebase_head():
|
|
87
87
|
for d in ('apply','merge'):
|
|
88
88
|
d = Path(f'.git/rebase-{d}')
|
|
@@ -91,14 +91,14 @@ def _git_rebase_head():
|
|
|
91
91
|
msg = run(f'git show-branch --no-name {cmt}')
|
|
92
92
|
return f'{cmt[:7]} ({msg})'
|
|
93
93
|
|
|
94
|
-
# %% ../nbs/api/07_merge.ipynb
|
|
94
|
+
# %% ../nbs/api/07_merge.ipynb #a39cf098
|
|
95
95
|
def _git_merge_file(base, ours, theirs):
|
|
96
96
|
"`git merge-file` with expected labels depending on if a `merge` or `rebase` is in-progress"
|
|
97
97
|
l_theirs = _git_rebase_head() or _git_branch_merge() or 'THEIRS'
|
|
98
98
|
cmd = f"git merge-file -L HEAD -L BASE -L '{l_theirs}' {ours} {base} {theirs}"
|
|
99
99
|
return subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
|
100
100
|
|
|
101
|
-
# %% ../nbs/api/07_merge.ipynb
|
|
101
|
+
# %% ../nbs/api/07_merge.ipynb #40796199
|
|
102
102
|
@call_parse
|
|
103
103
|
def nbdev_merge(base:str, ours:str, theirs:str, path:str):
|
|
104
104
|
"Git merge driver for notebooks"
|
nbdev/migrate.py
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/16_migrate.ipynb.
|
|
4
4
|
|
|
5
|
-
# %% auto 0
|
|
5
|
+
# %% auto #0
|
|
6
6
|
__all__ = ['MigrateProc', 'fp_md_fm', 'migrate_nb', 'migrate_md', 'nbdev_migrate']
|
|
7
7
|
|
|
8
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
8
|
+
# %% ../nbs/api/16_migrate.ipynb #5b687fa0-dc50-48df-8bfc-e98df34e7572
|
|
9
9
|
from .process import *
|
|
10
10
|
from .frontmatter import *
|
|
11
11
|
from .frontmatter import _fm2dict, _re_fm_md, _dict2fm, _insertfm
|
|
@@ -16,20 +16,20 @@ from .showdoc import show_doc
|
|
|
16
16
|
from fastcore.all import *
|
|
17
17
|
import shutil
|
|
18
18
|
|
|
19
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
19
|
+
# %% ../nbs/api/16_migrate.ipynb #52f60fb5-bc54-474a-876c-9146dd092681
|
|
20
20
|
def _cat_slug(fmdict):
|
|
21
21
|
"Get the partial slug from the category front matter."
|
|
22
22
|
slug = '/'.join(fmdict.get('categories', ''))
|
|
23
23
|
return '/' + slug if slug else ''
|
|
24
24
|
|
|
25
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
25
|
+
# %% ../nbs/api/16_migrate.ipynb #9fac0338-a503-4680-984f-60153843d5ef
|
|
26
26
|
def _file_slug(fname):
|
|
27
27
|
"Get the partial slug from the filename."
|
|
28
28
|
p = Path(fname)
|
|
29
29
|
dt = '/'+p.name[:10].replace('-', '/')+'/'
|
|
30
30
|
return dt + p.stem[11:]
|
|
31
31
|
|
|
32
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
32
|
+
# %% ../nbs/api/16_migrate.ipynb #689bf354
|
|
33
33
|
def _replace_fm(d:dict, # dictionary you wish to conditionally change
|
|
34
34
|
k:str, # key to check
|
|
35
35
|
val:str,# value to check if d[k] == v
|
|
@@ -47,14 +47,14 @@ def _fp_fm(d):
|
|
|
47
47
|
d = _replace_fm(d, 'hide', 'true', {'draft': 'true'})
|
|
48
48
|
return d
|
|
49
49
|
|
|
50
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
50
|
+
# %% ../nbs/api/16_migrate.ipynb #3146ce27
|
|
51
51
|
def _fp_image(d):
|
|
52
52
|
"Correct path of fastpages images to reference the local directory."
|
|
53
53
|
prefix = 'images/copied_from_nb/'
|
|
54
54
|
if d.get('image', '').startswith(prefix): d['image'] = d['image'].replace(prefix, '')
|
|
55
55
|
return d
|
|
56
56
|
|
|
57
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
57
|
+
# %% ../nbs/api/16_migrate.ipynb #244b0d01-a166-4549-9a45-1f8b1195c3c8
|
|
58
58
|
def _rm_quote(s):
|
|
59
59
|
title = re.search('''"(.*?)"''', s)
|
|
60
60
|
return title.group(1) if title else s
|
|
@@ -81,7 +81,7 @@ def _fp_convert(fm:dict, path:Path):
|
|
|
81
81
|
if fm.get('comments'): fm.pop('comments') #true by itself is not a valid value for comments https://quarto.org/docs/output-formats/html-basics.html#commenting, and the default is true
|
|
82
82
|
return fm
|
|
83
83
|
|
|
84
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
84
|
+
# %% ../nbs/api/16_migrate.ipynb #c8440f8b-f69e-44d2-8556-8869c1eedf0f
|
|
85
85
|
class MigrateProc(Processor):
|
|
86
86
|
"Migrate fastpages front matter in notebooks to a raw cell."
|
|
87
87
|
def begin(self):
|
|
@@ -89,7 +89,7 @@ class MigrateProc(Processor):
|
|
|
89
89
|
if getattr(first(self.nb.cells), 'cell_type', None) == 'raw': del self.nb.cells[0]
|
|
90
90
|
_insertfm(self.nb, self.nb.frontmatter_)
|
|
91
91
|
|
|
92
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
92
|
+
# %% ../nbs/api/16_migrate.ipynb #d5d575f3-b3b8-487d-8740-b1ebdccf6b34
|
|
93
93
|
def fp_md_fm(path):
|
|
94
94
|
"Make fastpages front matter in markdown files quarto compliant."
|
|
95
95
|
p = Path(path)
|
|
@@ -100,12 +100,12 @@ def fp_md_fm(path):
|
|
|
100
100
|
return _re_fm_md.sub(_dict2fm(fm), md)
|
|
101
101
|
else: return md
|
|
102
102
|
|
|
103
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
103
|
+
# %% ../nbs/api/16_migrate.ipynb #1abf7dc6-4a01-4c44-bdc3-0147820091ca
|
|
104
104
|
_alias = merge({k:'code-fold: true' for k in ['collapse', 'collapse_input', 'collapse_hide']},
|
|
105
105
|
{'collapse_show':'code-fold: show', 'hide_input': 'echo: false', 'hide': 'include: false', 'hide_output': 'output: false'})
|
|
106
106
|
def _subv1(s): return _alias.get(s, s)
|
|
107
107
|
|
|
108
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
108
|
+
# %% ../nbs/api/16_migrate.ipynb #0dde9fe8-d3ad-47b8-bd87-85b9536e9f96
|
|
109
109
|
def _re_v1():
|
|
110
110
|
d = ['default_exp', 'export', 'exports', 'exporti', 'hide', 'hide_input', 'collapse_show', 'collapse',
|
|
111
111
|
'collapse_hide', 'collapse_input', 'hide_output', 'default_cls_lvl']
|
|
@@ -118,7 +118,7 @@ def _repl_directives(code_str):
|
|
|
118
118
|
def _fmt(x): return f"#| {_subv1(x[2].replace('-', '_').strip())}"
|
|
119
119
|
return _re_v1().sub(_fmt, code_str)
|
|
120
120
|
|
|
121
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
121
|
+
# %% ../nbs/api/16_migrate.ipynb #cddcad93-1e44-4cbe-8dbd-9538533d0f8e
|
|
122
122
|
def _repl_v1dir(cell):
|
|
123
123
|
"Replace nbdev v1 with v2 directives."
|
|
124
124
|
if cell.get('source') and cell.get('cell_type') == 'code':
|
|
@@ -128,21 +128,21 @@ def _repl_v1dir(cell):
|
|
|
128
128
|
if not ss: pass
|
|
129
129
|
else: cell['source'] = '\n'.join([_repl_directives(c) for c in ss[:first_code]] + ss[first_code:])
|
|
130
130
|
|
|
131
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
131
|
+
# %% ../nbs/api/16_migrate.ipynb #e99a0998-cbfc-46ca-a068-5695437ebc5a
|
|
132
132
|
_re_callout = re.compile(r'^>\s(Warning|Note|Important|Tip):(.*)', flags=re.MULTILINE)
|
|
133
133
|
def _co(x): return ":::{.callout-"+x[1].lower()+"}\n\n" + f"{x[2].strip()}\n\n" + ":::"
|
|
134
134
|
def _convert_callout(s):
|
|
135
135
|
"Convert nbdev v1 to v2 callouts."
|
|
136
136
|
return _re_callout.sub(_co, s)
|
|
137
137
|
|
|
138
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
138
|
+
# %% ../nbs/api/16_migrate.ipynb #5b19ae68-9d40-498f-bcda-38496b139a27
|
|
139
139
|
_re_video = re.compile(r'^>\syoutube:(.*)', flags=re.MULTILINE)
|
|
140
140
|
def _v(x): return "{{< " + f"video {x[1].strip()}" + " >}}"
|
|
141
141
|
def _convert_video(s):
|
|
142
142
|
"Replace nbdev v1 with v2 video embeds."
|
|
143
143
|
return _re_video.sub(_v, s)
|
|
144
144
|
|
|
145
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
145
|
+
# %% ../nbs/api/16_migrate.ipynb #614a8cb8-5c43-45de-b93f-8646e549cc0e
|
|
146
146
|
_shortcuts = compose(_convert_video, _convert_callout)
|
|
147
147
|
|
|
148
148
|
def _repl_v1shortcuts(cell):
|
|
@@ -150,7 +150,7 @@ def _repl_v1shortcuts(cell):
|
|
|
150
150
|
if cell.get('source') and cell.get('cell_type') == 'markdown':
|
|
151
151
|
cell['source'] = _shortcuts(cell['source'])
|
|
152
152
|
|
|
153
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
153
|
+
# %% ../nbs/api/16_migrate.ipynb #9383e062-487b-4259-ab96-f427994742cc
|
|
154
154
|
def migrate_nb(path, overwrite=True):
|
|
155
155
|
"Migrate Notebooks from nbdev v1 and fastpages."
|
|
156
156
|
nbp = NBProcessor(path, procs=[FrontmatterProc, MigrateProc, _repl_v1shortcuts, _repl_v1dir], rm_directives=False)
|
|
@@ -158,14 +158,14 @@ def migrate_nb(path, overwrite=True):
|
|
|
158
158
|
if overwrite: write_nb(nbp.nb, path)
|
|
159
159
|
return nbp.nb
|
|
160
160
|
|
|
161
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
161
|
+
# %% ../nbs/api/16_migrate.ipynb #e10f1558-95cb-49a6-b1e6-affd6fa3ecd2
|
|
162
162
|
def migrate_md(path, overwrite=True):
|
|
163
163
|
"Migrate Markdown Files from fastpages."
|
|
164
164
|
txt = fp_md_fm(path)
|
|
165
165
|
if overwrite: path.write_text(txt)
|
|
166
166
|
return txt
|
|
167
167
|
|
|
168
|
-
# %% ../nbs/api/16_migrate.ipynb
|
|
168
|
+
# %% ../nbs/api/16_migrate.ipynb #3eb0cd02-e1ee-4910-be82-570434b974b5
|
|
169
169
|
@call_parse
|
|
170
170
|
def nbdev_migrate(
|
|
171
171
|
path:str=None, # A path or glob containing notebooks and markdown files to migrate
|