nbdev 2.3.27__py3-none-any.whl → 2.3.29__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/processors.py CHANGED
@@ -1,11 +1,13 @@
1
+ """Some processors for NBProcessor"""
2
+
1
3
  # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/10_processors.ipynb.
2
4
 
3
5
  # %% auto 0
4
6
  __all__ = ['populate_language', 'insert_warning', 'cell_lang', 'add_show_docs', 'fdiv', 'boxify', 'mv_exports', 'add_links',
5
- 'add_fold', 'strip_ansi', 'strip_hidden_metadata', 'hide_', 'hide_line', 'filter_stream_', 'clean_magics',
6
- 'rm_header_dash', 'rm_export', 'clean_show_doc', 'exec_show_docs', 'FilterDefaults']
7
+ 'add_fold', 'strip_ansi', 'strip_hidden_metadata', 'hide_', 'hide_line', 'filter_stream_', 'ai_magics',
8
+ 'clean_magics', 'rm_header_dash', 'rm_export', 'clean_show_doc', 'exec_show_docs', 'FilterDefaults']
7
9
 
8
- # %% ../nbs/api/10_processors.ipynb 2
10
+ # %% ../nbs/api/10_processors.ipynb
9
11
  import ast
10
12
  import importlib
11
13
 
@@ -23,7 +25,7 @@ from fastcore.imports import *
23
25
  from fastcore.xtras import *
24
26
  import sys,yaml
25
27
 
26
- # %% ../nbs/api/10_processors.ipynb 7
28
+ # %% ../nbs/api/10_processors.ipynb
27
29
  _langs = 'bash|html|javascript|js|latex|markdown|perl|ruby|sh|svg'
28
30
  _lang_pattern = re.compile(rf'^\s*%%\s*({_langs})\s*$', flags=re.MULTILINE)
29
31
 
@@ -36,13 +38,13 @@ class populate_language(Processor):
36
38
  if lang: cell.metadata.language = lang[0]
37
39
  else: cell.metadata.language = self.language
38
40
 
39
- # %% ../nbs/api/10_processors.ipynb 9
41
+ # %% ../nbs/api/10_processors.ipynb
40
42
  class insert_warning(Processor):
41
43
  "Insert Autogenerated Warning Into Notebook after the first cell."
42
44
  content = "<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->"
43
45
  def begin(self): self.nb.cells.insert(1, mk_cell(self.content, 'markdown'))
44
46
 
45
- # %% ../nbs/api/10_processors.ipynb 13
47
+ # %% ../nbs/api/10_processors.ipynb
46
48
  _def_types = (ast.FunctionDef,ast.AsyncFunctionDef,ast.ClassDef)
47
49
  def _def_names(cell, shown):
48
50
  cellp = cell.parsed_()
@@ -55,7 +57,7 @@ def _get_nm(tree):
55
57
  else: val = try_attrs(i.value, 'id', 'func', 'attr')
56
58
  return f'{val}.{i.attr}' if isinstance(i, ast.Attribute) else i.id
57
59
 
58
- # %% ../nbs/api/10_processors.ipynb 14
60
+ # %% ../nbs/api/10_processors.ipynb
59
61
  def _show_docs(trees):
60
62
  return [t for t in trees if isinstance(t,ast.Expr) and nested_attr(t, 'value.func.id')=='show_doc']
61
63
 
@@ -82,20 +84,20 @@ class add_show_docs(Processor):
82
84
  nb.cells.insert(cell.idx_+1, new_cell)
83
85
  nb.has_docs_ = shown_docs or exports
84
86
 
85
- # %% ../nbs/api/10_processors.ipynb 17
87
+ # %% ../nbs/api/10_processors.ipynb
86
88
  def fdiv(attrs=''):
87
89
  "Create a fenced div markdown cell in quarto"
88
90
  if attrs: attrs = ' {'+attrs+'}'
89
91
  return mk_cell(':::'+attrs, cell_type='markdown')
90
92
 
91
- # %% ../nbs/api/10_processors.ipynb 19
93
+ # %% ../nbs/api/10_processors.ipynb
92
94
  def boxify(cells):
93
95
  "Add a box around `cells`"
94
96
  if not isinstance(cells, list): cells = [cells]
95
97
  res = [fdiv('.py-2 .px-3 .mb-4 fig-align="center" .border .rounded .shadow-sm')]
96
98
  return res+cells+[fdiv()]
97
99
 
98
- # %% ../nbs/api/10_processors.ipynb 20
100
+ # %% ../nbs/api/10_processors.ipynb
99
101
  class mv_exports(Processor):
100
102
  "Move `exports` cells to after the `show_doc`"
101
103
  def begin(self):
@@ -108,7 +110,7 @@ class mv_exports(Processor):
108
110
  srccell = cells.pop(idx)
109
111
  cells[idx:idx] = [doccell,srccell]
110
112
 
111
- # %% ../nbs/api/10_processors.ipynb 21
113
+ # %% ../nbs/api/10_processors.ipynb
112
114
  _re_defaultexp = re.compile(r'^\s*#\|\s*default_exp\s+(\S+)', flags=re.MULTILINE)
113
115
 
114
116
  def _default_exp(nb):
@@ -117,7 +119,7 @@ def _default_exp(nb):
117
119
  default_exp = first(code_src.filter().map(_re_defaultexp.search).filter())
118
120
  return default_exp.group(1) if default_exp else None
119
121
 
120
- # %% ../nbs/api/10_processors.ipynb 23
122
+ # %% ../nbs/api/10_processors.ipynb
121
123
  def add_links(cell):
122
124
  "Add links to markdown cells"
123
125
  nl = NbdevLookup()
@@ -126,13 +128,13 @@ def add_links(cell):
126
128
  if hasattr(o, 'data') and hasattr(o['data'], 'text/markdown'):
127
129
  o.data['text/markdown'] = [nl.link_line(s) for s in o.data['text/markdown']]
128
130
 
129
- # %% ../nbs/api/10_processors.ipynb 25
131
+ # %% ../nbs/api/10_processors.ipynb
130
132
  def add_fold(cell):
131
133
  "Add `code-fold` to `exports` cells"
132
134
  if cell.cell_type != 'code' or 'exports' not in cell.directives_: return
133
135
  cell.source = f'#| code-fold: show\n#| code-summary: "Exported source"\n{cell.source}'
134
136
 
135
- # %% ../nbs/api/10_processors.ipynb 28
137
+ # %% ../nbs/api/10_processors.ipynb
136
138
  _re_ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
137
139
 
138
140
  def strip_ansi(cell):
@@ -140,17 +142,17 @@ def strip_ansi(cell):
140
142
  for outp in cell.get('outputs', []):
141
143
  if outp.get('name')=='stdout': outp['text'] = [_re_ansi_escape.sub('', o) for o in outp.text]
142
144
 
143
- # %% ../nbs/api/10_processors.ipynb 30
145
+ # %% ../nbs/api/10_processors.ipynb
144
146
  def strip_hidden_metadata(cell):
145
147
  '''Strips "hidden" metadata property from code cells so it doesn't interfere with docs rendering'''
146
148
  if cell.cell_type == 'code' and 'metadata' in cell: cell.metadata.pop('hidden',None)
147
149
 
148
- # %% ../nbs/api/10_processors.ipynb 31
150
+ # %% ../nbs/api/10_processors.ipynb
149
151
  def hide_(cell):
150
152
  "Hide cell from output"
151
153
  del(cell['source'])
152
154
 
153
- # %% ../nbs/api/10_processors.ipynb 33
155
+ # %% ../nbs/api/10_processors.ipynb
154
156
  def _re_hideline(lang=None): return re.compile(fr'{langs[lang]}\|\s*hide_line\s*$', re.MULTILINE)
155
157
 
156
158
  def hide_line(cell):
@@ -159,7 +161,7 @@ def hide_line(cell):
159
161
  if cell.cell_type == 'code' and _re_hideline(lang).search(cell.source):
160
162
  cell.source = '\n'.join([c for c in cell.source.splitlines() if not _re_hideline(lang).search(c)])
161
163
 
162
- # %% ../nbs/api/10_processors.ipynb 36
164
+ # %% ../nbs/api/10_processors.ipynb
163
165
  def filter_stream_(cell, *words):
164
166
  "Remove output lines containing any of `words` in `cell` stream output"
165
167
  if not words: return
@@ -167,14 +169,23 @@ def filter_stream_(cell, *words):
167
169
  if outp.output_type == 'stream':
168
170
  outp['text'] = [l for l in outp.text if not re.search('|'.join(words), l)]
169
171
 
170
- # %% ../nbs/api/10_processors.ipynb 38
172
+ # %% ../nbs/api/10_processors.ipynb
173
+ _aimagics_pattern = re.compile(r'^\s*(%%ai.? |%%ai.?$)', re.MULTILINE)
174
+
175
+ def ai_magics(cell):
176
+ "A preprocessor to convert AI magics to markdown"
177
+ if cell.cell_type == 'code' and _aimagics_pattern.search(cell.source):
178
+ cell.cell_type ='markdown'
179
+ cell.source = '\n'.join(cell.source.splitlines()[1:])
180
+
181
+ # %% ../nbs/api/10_processors.ipynb
171
182
  _magics_pattern = re.compile(r'^\s*(%%|%).*', re.MULTILINE)
172
183
 
173
184
  def clean_magics(cell):
174
185
  "A preprocessor to remove cell magic commands"
175
186
  if cell.cell_type == 'code': cell.source = _magics_pattern.sub('', cell.source).strip()
176
187
 
177
- # %% ../nbs/api/10_processors.ipynb 40
188
+ # %% ../nbs/api/10_processors.ipynb
178
189
  _re_hdr_dash = re.compile(r'^#+\s+.*\s+-\s*$', re.MULTILINE)
179
190
 
180
191
  def rm_header_dash(cell):
@@ -183,14 +194,14 @@ def rm_header_dash(cell):
183
194
  src = cell.source.strip()
184
195
  if cell.cell_type == 'markdown' and src.startswith('#') and src.endswith(' -'): del(cell['source'])
185
196
 
186
- # %% ../nbs/api/10_processors.ipynb 42
197
+ # %% ../nbs/api/10_processors.ipynb
187
198
  _hide_dirs = {'export','exporti', 'hide','default_exp'}
188
199
 
189
200
  def rm_export(cell):
190
201
  "Remove cells that are exported or hidden"
191
202
  if cell.directives_ and (cell.directives_.keys() & _hide_dirs): del(cell['source'])
192
203
 
193
- # %% ../nbs/api/10_processors.ipynb 44
204
+ # %% ../nbs/api/10_processors.ipynb
194
205
  _re_showdoc = re.compile(r'^show_doc', re.MULTILINE)
195
206
  def _is_showdoc(cell): return cell['cell_type'] == 'code' and _re_showdoc.search(cell.source)
196
207
  def _add_directives(cell, d):
@@ -202,7 +213,7 @@ def clean_show_doc(cell):
202
213
  if not _is_showdoc(cell): return
203
214
  _add_directives(cell, {'output':'asis','echo':'false'})
204
215
 
205
- # %% ../nbs/api/10_processors.ipynb 45
216
+ # %% ../nbs/api/10_processors.ipynb
206
217
  def _ast_contains(trees, types):
207
218
  for tree in trees:
208
219
  for node in ast.walk(tree):
@@ -223,7 +234,7 @@ def _do_eval(cell):
223
234
  return True
224
235
  if _show_docs(trees): return True
225
236
 
226
- # %% ../nbs/api/10_processors.ipynb 46
237
+ # %% ../nbs/api/10_processors.ipynb
227
238
  class exec_show_docs(Processor):
228
239
  "Execute cells needed for `show_docs` output, including exported cells and imports"
229
240
  def begin(self):
@@ -250,13 +261,13 @@ class exec_show_docs(Processor):
250
261
  widgets = {**old, **new, 'state': {**old.get('state', {}), **new['state']}}
251
262
  self.nb.metadata['widgets'] = {mimetype: widgets}
252
263
 
253
- # %% ../nbs/api/10_processors.ipynb 48
264
+ # %% ../nbs/api/10_processors.ipynb
254
265
  def _import_obj(s):
255
266
  mod_nm, obj_nm = s.split(':')
256
267
  mod = importlib.import_module(mod_nm)
257
268
  return getattr(mod, obj_nm)
258
269
 
259
- # %% ../nbs/api/10_processors.ipynb 49
270
+ # %% ../nbs/api/10_processors.ipynb
260
271
  class FilterDefaults:
261
272
  "Override `FilterDefaults` to change which notebook processors are used"
262
273
  def xtra_procs(self):
@@ -266,7 +277,8 @@ class FilterDefaults:
266
277
  def base_procs(self):
267
278
  return [FrontmatterProc, populate_language, add_show_docs, insert_warning,
268
279
  strip_ansi, hide_line, filter_stream_, rm_header_dash,
269
- clean_show_doc, exec_show_docs, rm_export, clean_magics, hide_, add_links, add_fold, mv_exports, strip_hidden_metadata]
280
+ clean_show_doc, exec_show_docs, rm_export, ai_magics, clean_magics, hide_, add_links,
281
+ add_fold, mv_exports, strip_hidden_metadata]
270
282
 
271
283
  def procs(self):
272
284
  "Processors for export"
nbdev/qmd.py CHANGED
@@ -1,3 +1,5 @@
1
+ """Basic qmd generation helpers (experimental)"""
2
+
1
3
  # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/15_qmd.ipynb.
2
4
 
3
5
  # %% ../nbs/api/15_qmd.ipynb 2
@@ -10,7 +12,7 @@ from fastcore.meta import delegates
10
12
  # %% auto 0
11
13
  __all__ = ['meta', 'div', 'img', 'btn', 'tbl_row', 'tbl_sep']
12
14
 
13
- # %% ../nbs/api/15_qmd.ipynb 4
15
+ # %% ../nbs/api/15_qmd.ipynb
14
16
  def meta(md, # Markdown to add meta to
15
17
  classes=None, # List of CSS classes to add
16
18
  style=None, # Dict of CSS styles to add
@@ -25,7 +27,7 @@ def meta(md, # Markdown to add meta to
25
27
  meta = ' '.join(meta)
26
28
  return md + ("{" + meta + "}" if meta else "")
27
29
 
28
- # %% ../nbs/api/15_qmd.ipynb 5
30
+ # %% ../nbs/api/15_qmd.ipynb
29
31
  def div(txt, # Markdown to add meta to
30
32
  classes=None, # List of CSS classes to add
31
33
  style=None, # Dict of CSS styles to add
@@ -33,7 +35,7 @@ def div(txt, # Markdown to add meta to
33
35
  "A qmd div with optional metadata section"
34
36
  return meta("::: ", classes=classes, style=style, **kwargs) + f"\n\n{txt}\n\n:::\n\n"
35
37
 
36
- # %% ../nbs/api/15_qmd.ipynb 6
38
+ # %% ../nbs/api/15_qmd.ipynb
37
39
  def img(fname, # Image to link to
38
40
  classes=None, # List of CSS classes to add
39
41
  style=None, # Dict of CSS styles to add
@@ -51,7 +53,7 @@ def img(fname, # Image to link to
51
53
  res = meta(f'![]({fname})', classes=classes, style=style, **kwargs)
52
54
  return f'[{res}]({fname})' if link else res
53
55
 
54
- # %% ../nbs/api/15_qmd.ipynb 7
56
+ # %% ../nbs/api/15_qmd.ipynb
55
57
  def btn(txt, # Button text
56
58
  link, # Button link URL
57
59
  classes=None, # List of CSS classes to add
@@ -60,20 +62,20 @@ def btn(txt, # Button text
60
62
  "A qmd button"
61
63
  return meta(f'[{txt}]({link})', classes=classes, style=style, role="button")
62
64
 
63
- # %% ../nbs/api/15_qmd.ipynb 8
65
+ # %% ../nbs/api/15_qmd.ipynb
64
66
  def tbl_row(cols:list, # Auto-stringified columns to show in the row
65
67
  ):
66
68
  "Create a markdown table row from `cols`"
67
69
  return '|' + '|'.join(str(c or '') for c in cols) + '|'
68
70
 
69
- # %% ../nbs/api/15_qmd.ipynb 9
71
+ # %% ../nbs/api/15_qmd.ipynb
70
72
  def tbl_sep(sizes:int|list=3 # List of column sizes, or single `int` if all sizes the same
71
73
  ):
72
74
  "Create a markdown table separator with relative column size `sizes`"
73
75
  if isinstance(sizes,int): sizes = [3]*sizes
74
76
  return tbl_row('-'*s for s in sizes)
75
77
 
76
- # %% ../nbs/api/15_qmd.ipynb 10
78
+ # %% ../nbs/api/15_qmd.ipynb
77
79
  def _install_nbdev():
78
80
  return div('''#### pip
79
81
 
nbdev/quarto.py CHANGED
@@ -1,3 +1,5 @@
1
+ """Install and interact with Quarto from nbdev"""
2
+
1
3
  # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/14_quarto.ipynb.
2
4
 
3
5
  # %% ../nbs/api/14_quarto.ipynb 3
@@ -21,12 +23,12 @@ import yaml
21
23
  __all__ = ['BASE_QUARTO_URL', 'install_quarto', 'install', 'IndentDumper', 'nbdev_sidebar', 'refresh_quarto_yml',
22
24
  'nbdev_proc_nbs', 'nbdev_readme', 'nbdev_docs', 'prepare', 'fs_watchdog', 'nbdev_preview']
23
25
 
24
- # %% ../nbs/api/14_quarto.ipynb 5
26
+ # %% ../nbs/api/14_quarto.ipynb
25
27
  def _sprun(cmd):
26
28
  try: subprocess.check_output(cmd, shell=True)
27
29
  except subprocess.CalledProcessError as cpe: sys.exit(cpe.returncode)
28
30
 
29
- # %% ../nbs/api/14_quarto.ipynb 7
31
+ # %% ../nbs/api/14_quarto.ipynb
30
32
  BASE_QUARTO_URL='https://www.quarto.org/download/latest/'
31
33
 
32
34
  def _install_linux():
@@ -53,7 +55,7 @@ def install_quarto():
53
55
  elif 'linux' in sys.platform: _install_linux()
54
56
  finally: system('sudo rm -f .installing')
55
57
 
56
- # %% ../nbs/api/14_quarto.ipynb 8
58
+ # %% ../nbs/api/14_quarto.ipynb
57
59
  @call_parse
58
60
  def install():
59
61
  "Install Quarto and the current library"
@@ -61,7 +63,7 @@ def install():
61
63
  d = get_config().lib_path
62
64
  if (d/'__init__.py').exists(): system(f'pip install -e "{d.parent}[dev]"')
63
65
 
64
- # %% ../nbs/api/14_quarto.ipynb 10
66
+ # %% ../nbs/api/14_quarto.ipynb
65
67
  def _pre(p,b=True): return ' ' * (len(p.parts)) + ('- ' if b else ' ')
66
68
  def _sort(a):
67
69
  x,y = a
@@ -78,7 +80,7 @@ def _nbglob_docs(
78
80
  **kwargs):
79
81
  return nbglob(path, file_glob=file_glob, file_re=file_re, **kwargs)
80
82
 
81
- # %% ../nbs/api/14_quarto.ipynb 11
83
+ # %% ../nbs/api/14_quarto.ipynb
82
84
  def _recursive_parser(
83
85
  dir_dict: dict, # Directory structure as a dict.
84
86
  contents: list, # `contents` list from `sidebar.yaml` template dict.
@@ -101,7 +103,7 @@ class IndentDumper(yaml.Dumper):
101
103
  def increase_indent(self, flow=False, indentless=False):
102
104
  return super(IndentDumper, self).increase_indent(flow, False)
103
105
 
104
- # %% ../nbs/api/14_quarto.ipynb 12
106
+ # %% ../nbs/api/14_quarto.ipynb
105
107
  @call_parse
106
108
  @delegates(_nbglob_docs)
107
109
  def nbdev_sidebar(
@@ -136,7 +138,7 @@ def nbdev_sidebar(
136
138
  if printit: return print(yml)
137
139
  yml_path.write_text(yml)
138
140
 
139
- # %% ../nbs/api/14_quarto.ipynb 15
141
+ # %% ../nbs/api/14_quarto.ipynb
140
142
  _quarto_yml="""project:
141
143
  type: website
142
144
 
@@ -145,6 +147,8 @@ format:
145
147
  theme: cosmo
146
148
  css: styles.css
147
149
  toc: true
150
+ keep-md: true
151
+ commonmark: default
148
152
 
149
153
  website:
150
154
  twitter-card: true
@@ -158,7 +162,7 @@ website:
158
162
 
159
163
  metadata-files: [nbdev.yml, sidebar.yml]"""
160
164
 
161
- # %% ../nbs/api/14_quarto.ipynb 16
165
+ # %% ../nbs/api/14_quarto.ipynb
162
166
  _nbdev_yml="""project:
163
167
  output-dir: {doc_path}
164
168
 
@@ -170,7 +174,7 @@ website:
170
174
  repo-url: "{git_url}"
171
175
  """
172
176
 
173
- # %% ../nbs/api/14_quarto.ipynb 17
177
+ # %% ../nbs/api/14_quarto.ipynb
174
178
  def refresh_quarto_yml():
175
179
  "Generate `_quarto.yml` from `settings.ini`."
176
180
  cfg = get_config()
@@ -184,13 +188,13 @@ def refresh_quarto_yml():
184
188
  if qy.exists() and not str2bool(cfg.get('custom_quarto_yml', True)): qy.unlink()
185
189
  if not qy.exists(): qy.write_text(_quarto_yml)
186
190
 
187
- # %% ../nbs/api/14_quarto.ipynb 18
191
+ # %% ../nbs/api/14_quarto.ipynb
188
192
  def _ensure_quarto():
189
193
  if shutil.which('quarto'): return
190
194
  print("Quarto is not installed. We will download and install it for you.")
191
195
  install.__wrapped__()
192
196
 
193
- # %% ../nbs/api/14_quarto.ipynb 19
197
+ # %% ../nbs/api/14_quarto.ipynb
194
198
  def _pre_docs(path=None, n_workers:int=defaults.cpus, **kwargs):
195
199
  cfg = get_config()
196
200
  path = Path(path) if path else cfg.nbs_path
@@ -202,21 +206,21 @@ def _pre_docs(path=None, n_workers:int=defaults.cpus, **kwargs):
202
206
  cache = proc_nbs(path, n_workers=n_workers, **kwargs)
203
207
  return cache,cfg,path
204
208
 
205
- # %% ../nbs/api/14_quarto.ipynb 20
209
+ # %% ../nbs/api/14_quarto.ipynb
206
210
  @call_parse
207
211
  @delegates(proc_nbs)
208
212
  def nbdev_proc_nbs(**kwargs):
209
213
  "Process notebooks in `path` for docs rendering"
210
214
  _pre_docs(**kwargs)[0]
211
215
 
212
- # %% ../nbs/api/14_quarto.ipynb 22
216
+ # %% ../nbs/api/14_quarto.ipynb
213
217
  def _readme_mtime_not_older(readme_path, readme_nb_path):
214
218
  if not readme_nb_path.exists():
215
219
  print(f"Could not find {readme_nb_path}")
216
220
  return True
217
221
  return readme_path.exists() and readme_path.stat().st_mtime>=readme_nb_path.stat().st_mtime
218
222
 
219
- # %% ../nbs/api/14_quarto.ipynb 23
223
+ # %% ../nbs/api/14_quarto.ipynb
220
224
  class _SidebarYmlRemoved:
221
225
  "Context manager for `nbdev_readme` to avoid rendering whole docs website"
222
226
  def __init__(self,path): self._path=path
@@ -229,14 +233,14 @@ class _SidebarYmlRemoved:
229
233
  def __exit__(self, exc_type, exc_value, exc_tb):
230
234
  if self._moved: (self._path/'sidebar.yml.bak').rename(self._yml_path)
231
235
 
232
- # %% ../nbs/api/14_quarto.ipynb 24
236
+ # %% ../nbs/api/14_quarto.ipynb
233
237
  def _copytree(a,b):
234
238
  if sys.version_info.major >=3 and sys.version_info.minor >=8: copytree(a, b, dirs_exist_ok=True)
235
239
  else:
236
240
  from distutils.dir_util import copy_tree
237
241
  copy_tree(a, b)
238
242
 
239
- # %% ../nbs/api/14_quarto.ipynb 25
243
+ # %% ../nbs/api/14_quarto.ipynb
240
244
  def _save_cached_readme(cache, cfg):
241
245
  tmp_doc_path = cache/cfg.doc_path.name
242
246
  readme = tmp_doc_path/'README.md'
@@ -247,7 +251,7 @@ def _save_cached_readme(cache, cfg):
247
251
  _rdmi = tmp_doc_path/((cache/cfg.readme_nb).stem + '_files') # Supporting files for README
248
252
  if _rdmi.exists(): _copytree(_rdmi, cfg.config_path/_rdmi.name)
249
253
 
250
- # %% ../nbs/api/14_quarto.ipynb 26
254
+ # %% ../nbs/api/14_quarto.ipynb
251
255
  @call_parse
252
256
  def nbdev_readme(
253
257
  path:str=None, # Path to notebooks
@@ -263,7 +267,7 @@ def nbdev_readme(
263
267
 
264
268
  _save_cached_readme(cache, cfg)
265
269
 
266
- # %% ../nbs/api/14_quarto.ipynb 29
270
+ # %% ../nbs/api/14_quarto.ipynb
267
271
  @call_parse
268
272
  @delegates(_nbglob_docs)
269
273
  def nbdev_docs(
@@ -277,7 +281,7 @@ def nbdev_docs(
277
281
  shutil.rmtree(cfg.doc_path, ignore_errors=True)
278
282
  move(cache/cfg.doc_path.name, cfg.config_path)
279
283
 
280
- # %% ../nbs/api/14_quarto.ipynb 31
284
+ # %% ../nbs/api/14_quarto.ipynb
281
285
  @call_parse
282
286
  def prepare():
283
287
  "Export, test, and clean notebooks, and render README if needed"
@@ -288,7 +292,7 @@ def prepare():
288
292
  refresh_quarto_yml()
289
293
  nbdev_readme.__wrapped__(chk_time=True)
290
294
 
291
- # %% ../nbs/api/14_quarto.ipynb 33
295
+ # %% ../nbs/api/14_quarto.ipynb
292
296
  @contextmanager
293
297
  def fs_watchdog(func, path, recursive:bool=True):
294
298
  "File system watchdog dispatching to `func`"
@@ -304,7 +308,7 @@ def fs_watchdog(func, path, recursive:bool=True):
304
308
  observer.stop()
305
309
  observer.join()
306
310
 
307
- # %% ../nbs/api/14_quarto.ipynb 34
311
+ # %% ../nbs/api/14_quarto.ipynb
308
312
  @call_parse
309
313
  @delegates(_nbglob_docs)
310
314
  def nbdev_preview(