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/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
- try:
62
- if has_cell_number:
63
- *nb,idx = top.split()
64
- nb = ' '.join(nb)
65
- idx = int(idx)
66
- else:
67
- nb = top
68
- idx = None
69
- except ValueError: raise ValueError(f"Unexpected format in '{p}' at cell:\n```\n# %% {cell.strip()}.\n```\n"
70
- "The expected format is: '# %% {nb_path} {cell_idx}'.")
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, idx=idx, code=code, nb_path=nb_path, py_path=p.resolve())
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 1
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, cell_number=get_config().cell_number, solo_nb=self.solo_nb)
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