nbdev 3.1.0__tar.gz → 3.2.0__tar.gz

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.
Files changed (38) hide show
  1. {nbdev-3.1.0/nbdev.egg-info → nbdev-3.2.0}/PKG-INFO +6 -3
  2. {nbdev-3.1.0 → nbdev-3.2.0}/README.md +4 -1
  3. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/__init__.py +1 -1
  4. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/_modidx.py +2 -0
  5. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/cli.py +10 -7
  6. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/config.py +3 -2
  7. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/export.py +9 -8
  8. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/merge.py +7 -5
  9. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/migrate.py +9 -7
  10. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/processors.py +10 -4
  11. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/qmd.py +34 -24
  12. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/quarto.py +15 -8
  13. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/showdoc.py +6 -4
  14. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/test.py +17 -13
  15. {nbdev-3.1.0 → nbdev-3.2.0/nbdev.egg-info}/PKG-INFO +6 -3
  16. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev.egg-info/requires.txt +1 -1
  17. {nbdev-3.1.0 → nbdev-3.2.0}/pyproject.toml +1 -1
  18. {nbdev-3.1.0 → nbdev-3.2.0}/CONTRIBUTING.md +0 -0
  19. {nbdev-3.1.0 → nbdev-3.2.0}/LICENSE +0 -0
  20. {nbdev-3.1.0 → nbdev-3.2.0}/MANIFEST.in +0 -0
  21. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/clean.py +0 -0
  22. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/diff.py +0 -0
  23. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/doclinks.py +0 -0
  24. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/extract_attachments.py +0 -0
  25. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/frontmatter.py +0 -0
  26. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/imports.py +0 -0
  27. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/maker.py +0 -0
  28. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/process.py +0 -0
  29. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/release.py +0 -0
  30. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/scrubmagics.py +0 -0
  31. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/serve.py +0 -0
  32. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/serve_drv.py +0 -0
  33. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev/sync.py +0 -0
  34. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev.egg-info/SOURCES.txt +0 -0
  35. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev.egg-info/dependency_links.txt +0 -0
  36. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev.egg-info/entry_points.txt +0 -0
  37. {nbdev-3.1.0 → nbdev-3.2.0}/nbdev.egg-info/top_level.txt +0 -0
  38. {nbdev-3.1.0 → nbdev-3.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nbdev
3
- Version: 3.1.0
3
+ Version: 3.2.0
4
4
  Summary: Create delightful software with Jupyter Notebooks
5
5
  Author-email: "Jeremy Howard and the fast.ai community" <j@fast.ai>
6
6
  License: Apache-2.0
@@ -16,7 +16,7 @@ Classifier: License :: OSI Approved :: Apache Software License
16
16
  Requires-Python: >=3.9
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
- Requires-Dist: fastcore>=1.14.1
19
+ Requires-Dist: fastcore>=1.14.6
20
20
  Requires-Dist: execnb>=0.2.4
21
21
  Requires-Dist: astunparse
22
22
  Requires-Dist: ghapi>=2.0.0
@@ -158,7 +158,7 @@ available commands:
158
158
  nbdev-pypi Create and upload Python package to PyPI
159
159
  nbdev-readme Create README.md from readme_nb (index.ipynb by default)
160
160
  nbdev-release-both Release both conda and PyPI packages
161
- nbdev-release-gh Calls `nbdev_changelog`, lets you edit the result, then pushes to git and calls `nbdev_release_git`
161
+ nbdev-release-gh Calls `nbdev-changelog`, lets you edit the result, then pushes to git and calls `nbdev-release-git`
162
162
  nbdev-release-git Tag and create a release in GitHub for the current version
163
163
  nbdev-requirements Writes a `requirements.txt` file to `directory` based on pyproject.toml.
164
164
  nbdev-sidebar Create sidebar.yml
@@ -184,6 +184,9 @@ some_module.something()
184
184
  Instead, split this into two cells, one which does `import some_module`,
185
185
  and the other which does `some_module.something()`.
186
186
 
187
+ Only top-level statements count: `try: import` blocks and imports inside
188
+ function definitions are fine.
189
+
187
190
  The reason for this is that when we create your documentation website,
188
191
  we ensure that all of the signatures for functions you document are up
189
192
  to date, by running the imports, exported cells, and
@@ -114,7 +114,7 @@ available commands:
114
114
  nbdev-pypi Create and upload Python package to PyPI
115
115
  nbdev-readme Create README.md from readme_nb (index.ipynb by default)
116
116
  nbdev-release-both Release both conda and PyPI packages
117
- nbdev-release-gh Calls `nbdev_changelog`, lets you edit the result, then pushes to git and calls `nbdev_release_git`
117
+ nbdev-release-gh Calls `nbdev-changelog`, lets you edit the result, then pushes to git and calls `nbdev-release-git`
118
118
  nbdev-release-git Tag and create a release in GitHub for the current version
119
119
  nbdev-requirements Writes a `requirements.txt` file to `directory` based on pyproject.toml.
120
120
  nbdev-sidebar Create sidebar.yml
@@ -140,6 +140,9 @@ some_module.something()
140
140
  Instead, split this into two cells, one which does `import some_module`,
141
141
  and the other which does `some_module.something()`.
142
142
 
143
+ Only top-level statements count: `try: import` blocks and imports inside
144
+ function definitions are fine.
145
+
143
146
  The reason for this is that when we create your documentation website,
144
147
  we ensure that all of the signatures for functions you document are up
145
148
  to date, by running the imports, exported cells, and
@@ -1,4 +1,4 @@
1
- __version__ = "3.1.0"
1
+ __version__ = "3.2.0"
2
2
 
3
3
  from .doclinks import nbdev_export
4
4
  from .showdoc import show_doc
@@ -225,6 +225,7 @@ d = { 'settings': { 'branch': 'main',
225
225
  'nbdev.processors._is_showdoc': ('api/processors.html#_is_showdoc', 'nbdev/processors.py'),
226
226
  'nbdev.processors._re_hideline': ('api/processors.html#_re_hideline', 'nbdev/processors.py'),
227
227
  'nbdev.processors._show_docs': ('api/processors.html#_show_docs', 'nbdev/processors.py'),
228
+ 'nbdev.processors._tl_contains': ('api/processors.html#_tl_contains', 'nbdev/processors.py'),
228
229
  'nbdev.processors._want_doc': ('api/processors.html#_want_doc', 'nbdev/processors.py'),
229
230
  'nbdev.processors.add_fold': ('api/processors.html#add_fold', 'nbdev/processors.py'),
230
231
  'nbdev.processors.add_links': ('api/processors.html#add_links', 'nbdev/processors.py'),
@@ -287,6 +288,7 @@ d = { 'settings': { 'branch': 'main',
287
288
  'nbdev.quarto._nbglob_docs': ('api/quarto.html#_nbglob_docs', 'nbdev/quarto.py'),
288
289
  'nbdev.quarto._pre': ('api/quarto.html#_pre', 'nbdev/quarto.py'),
289
290
  'nbdev.quarto._pre_docs': ('api/quarto.html#_pre_docs', 'nbdev/quarto.py'),
291
+ 'nbdev.quarto._readme_cands': ('api/quarto.html#_readme_cands', 'nbdev/quarto.py'),
290
292
  'nbdev.quarto._recursive_parser': ('api/quarto.html#_recursive_parser', 'nbdev/quarto.py'),
291
293
  'nbdev.quarto._save_cached_contributing': ('api/quarto.html#_save_cached_contributing', 'nbdev/quarto.py'),
292
294
  'nbdev.quarto._save_cached_readme': ('api/quarto.html#_save_cached_readme', 'nbdev/quarto.py'),
@@ -169,18 +169,21 @@ async def nbdev_update_license(
169
169
  # %% ../nbs/api/13_cli.ipynb #412b4cd2
170
170
  @call_parse
171
171
  @delegates(nb_export, but=['procs', 'mod_maker'])
172
- def nb_export_cli(nbname,
173
- debug:store_true=False, # Debug flag
174
- **kwargs):
172
+ def nb_export_cli(
173
+ nbname,
174
+ debug:store_true=False, # Debug flag
175
+ **kwargs
176
+ ):
175
177
  "Export a single nbdev notebook to a python script."
176
178
  return nb_export(nbname=nbname, debug=debug, **kwargs)
177
179
 
178
180
  # %% ../nbs/api/13_cli.ipynb #aaa472e7
179
181
  @call_parse
180
- def watch_export(nbs:str=None, # Nb directory to watch for changes
181
- lib:str=None, # Export directory to write py files to
182
- force:bool=False # Ignore nbdev config if in nbdev project
183
- ):
182
+ def watch_export(
183
+ nbs:str=None, # Nb directory to watch for changes
184
+ lib:str=None, # Export directory to write py files to
185
+ force:bool=False # Ignore nbdev config if in nbdev project
186
+ ):
184
187
  '''Use `nb_export` on ipynb files in `nbs` directory on changes using nbdev config if available'''
185
188
  cfg = get_config() if is_nbdev() else None
186
189
  nbs = nbs or (cfg.nbs_path if cfg else '.')
@@ -236,7 +236,7 @@ def get_config(path=None, also_settings=False):
236
236
  nbdev = {**user, **d.get('tool', {}).get('nbdev', {})}
237
237
  return ConfigToml(nbdev, d.get('project', {}), cfg_file)
238
238
  if also_settings:
239
- from fastcore.foundation import Config
239
+ from fastcore.xtras import Config
240
240
  cfg = Config.find('settings.ini', path)
241
241
  if cfg: return cfg
242
242
  cfg_path = Path(path or Path.cwd()).expanduser().absolute()
@@ -265,7 +265,8 @@ def nbpath2docurl(nb_path):
265
265
  "Hosted docs URL (with `.md` suffix) for notebook `nb_path`, or '' if no `doc_host`"
266
266
  cfg = get_config()
267
267
  if not cfg.doc_host: return ''
268
- p = Path(nb_path).resolve().relative_to(cfg.path('nbs_path'))
268
+ try: p = Path(nb_path).resolve().relative_to(cfg.path('nbs_path'))
269
+ except ValueError: return ""
269
270
  return f"{cfg.doc_host.rstrip('/')}{cfg.doc_baseurl.rstrip('/')}/{nbpath2html(p).as_posix()}.md"
270
271
 
271
272
  # %% ../nbs/api/01_config.ipynb #163177f2
@@ -36,14 +36,15 @@ class ExportModuleProc:
36
36
  _exports_=_export_
37
37
 
38
38
  # %% ../nbs/api/04_export.ipynb #76717e36
39
- def nb_export(nbname:str, # Filename of notebook
40
- lib_path:str=None, # Path to destination library. If not in a nbdev project, defaults to current directory.
41
- procs=None, # Processors to use
42
- name:str=None, # Name of python script {name}.py to create.
43
- mod_maker=ModuleMaker,
44
- debug:bool=False, # Debug mode
45
- solo_nb:bool=False # Export single notebook outside of an nbdev project.
46
- ):
39
+ def nb_export(
40
+ nbname:str, # Filename of notebook
41
+ lib_path:str=None, # Path to destination library. If not in a nbdev project, defaults to current directory.
42
+ procs=None, # Processors to use
43
+ name:str=None, # Name of python script {name}.py to create.
44
+ mod_maker=ModuleMaker,
45
+ debug:bool=False, # Debug mode
46
+ solo_nb:bool=False # Export single notebook outside of an nbdev project.
47
+ ):
47
48
  "Create module(s) from notebook"
48
49
  if lib_path is None: lib_path = get_config().lib_path if is_nbdev() else '.'
49
50
  exp = ExportModuleProc()
@@ -60,11 +60,13 @@ def _merge_cells(a, b, brancha, branchb, theirs):
60
60
 
61
61
  # %% ../nbs/api/07_merge.ipynb #cc492d30
62
62
  @call_parse
63
- def nbdev_fix(nbname:str, # Notebook filename to fix
64
- outname:str=None, # Filename of output notebook (defaults to `nbname`)
65
- nobackup:bool_arg=True, # Do not backup `nbname` to `nbname`.bak if `outname` not provided
66
- theirs:bool=False, # Use their outputs and metadata instead of ours
67
- noprint:bool=False): # Do not print info about whether conflicts are found
63
+ def nbdev_fix(
64
+ nbname:str, # Notebook filename to fix
65
+ outname:str=None, # Filename of output notebook (defaults to `nbname`)
66
+ nobackup:bool_arg=True, # Do not backup `nbname` to `nbname`.bak if `outname` not provided
67
+ theirs:bool=False, # Use their outputs and metadata instead of ours
68
+ noprint:bool=False # Do not print info about whether conflicts are found
69
+ ):
68
70
  "Create working notebook from conflicted notebook `nbname`"
69
71
  nbname = Path(nbname)
70
72
  if not nobackup and not outname: shutil.copy(nbname, nbname.with_suffix('.ipynb.bak'))
@@ -32,11 +32,12 @@ def _file_slug(fname):
32
32
  return dt + p.stem[11:]
33
33
 
34
34
  # %% ../nbs/api/16_migrate.ipynb #689bf354
35
- def _replace_fm(d:dict, # dictionary you wish to conditionally change
36
- k:str, # key to check
37
- val:str,# value to check if d[k] == v
38
- repl_dict:dict #dictionary that will be used as a replacement
39
- ):
35
+ def _replace_fm(
36
+ d:dict, # dictionary you wish to conditionally change
37
+ k:str, # key to check
38
+ val:str,# value to check if d[k] == v
39
+ repl_dict:dict #dictionary that will be used as a replacement
40
+ ):
40
41
  "replace key `k` in dict `d` if d[k] == val with `repl_dict`"
41
42
  if str(d.get(k, '')).lower().strip() == str(val.lower()).strip():
42
43
  d.pop(k)
@@ -191,8 +192,9 @@ def _migrate_workflows(path):
191
192
  wf_path = Path(path) / '.github/workflows'
192
193
  if not wf_path.exists(): return
193
194
  replacements = [
194
- ('fastai/workflows/quarto-ghp@', 'fastai/workflows/quarto-ghp3@'),
195
- ('fastai/workflows/nbdev-ci@', 'fastai/workflows/nbdev3-ci@'),
195
+ ('fastai/workflows/quarto-ghp@', 'AnswerDotAI/workflows/quarto-ghp3@'),
196
+ ('fastai/workflows/nbdev-ci@', 'AnswerDotAI/workflows/nbdev3-ci@'),
197
+ ('fastai/workflows/', 'AnswerDotAI/workflows/'),
196
198
  ]
197
199
  for f in (*wf_path.glob('*.yml'), *wf_path.glob('*.yaml')):
198
200
  txt = f.read_text()
@@ -182,11 +182,15 @@ def ai_magics(cell):
182
182
  cell.source = '\n'.join(cell.source.splitlines()[1:])
183
183
 
184
184
  # %% ../nbs/api/10_processors.ipynb #5a9c8fd4
185
- _magics_pattern = re.compile(r'^\s*(%%|%).*', re.MULTILINE)
185
+ _def_strip_magics = '%load_ext %autoreload %reload_ext %matplotlib %config'
186
186
 
187
187
  def clean_magics(cell):
188
- "A preprocessor to remove cell magic commands"
189
- if cell.cell_type == 'code': cell.source = _magics_pattern.sub('', cell.source).strip()
188
+ "Remove housekeeping magics: those named in the `strip_magics` config (space-separated, default `_def_strip_magics`)"
189
+ mm = str(get_config().get('strip_magics', _def_strip_magics)).split()
190
+ if not mm or cell.cell_type != 'code': return
191
+ pat = re.compile(rf"^\s*({'|'.join(re.escape(m) for m in mm)})\b.*", re.MULTILINE)
192
+ cell.source = pat.sub('', cell.source).strip()
193
+
190
194
 
191
195
  # %% ../nbs/api/10_processors.ipynb #93e27a52
192
196
  _re_hdr_dash = re.compile(r'^#+\s+.*\s+-\s*$', re.MULTILINE)
@@ -223,6 +227,8 @@ def _ast_contains(trees, types):
223
227
  for node in ast.walk(tree):
224
228
  if isinstance(node, types): return True
225
229
 
230
+ def _tl_contains(trees, types): return any(isinstance(t, types) for t in trees)
231
+
226
232
  def _do_eval(cell):
227
233
  if cell_lang(cell) != 'python': return
228
234
  if not cell.source or 'nbdev_export'+'()' in cell.source: return
@@ -233,7 +239,7 @@ def _do_eval(cell):
233
239
  _show_dirs = {'export','exports','exporti','exec_doc'}
234
240
  if cell.directives_.keys() & _show_dirs: return True
235
241
  if _ast_contains(trees, (ast.Import, ast.ImportFrom)):
236
- if _ast_contains(trees, (ast.Expr, ast.Assign)):
242
+ if _tl_contains(trees, (ast.Import, ast.ImportFrom)) and _tl_contains(trees, (ast.Expr, ast.Assign)):
237
243
  warn(f'Found cells containing imports and other code. See FAQ.\n---\n{cell.source}\n---\n')
238
244
  return True
239
245
  if _show_docs(trees): return True
@@ -14,10 +14,12 @@ from fastcore.utils import *
14
14
  from fastcore.meta import delegates
15
15
 
16
16
  # %% ../nbs/api/15_qmd.ipynb #5a64f1f4
17
- def meta(md, # Markdown to add meta to
18
- classes=None, # List of CSS classes to add
19
- style=None, # Dict of CSS styles to add
20
- **kwargs): # Additional attributes to add to meta
17
+ def meta(
18
+ md, # Markdown to add meta to
19
+ classes=None, # List of CSS classes to add
20
+ style=None, # Dict of CSS styles to add
21
+ **kwargs # Additional attributes to add to meta
22
+ ):
21
23
  "A metadata section for qmd div in `{}`"
22
24
  if style: kwargs['style'] = "; ".join(f'{k}: {v}' for k,v in style.items())
23
25
  props = ' '.join(f'{k}="{v}"' for k,v in kwargs.items())
@@ -29,21 +31,25 @@ def meta(md, # Markdown to add meta to
29
31
  return md + ("{" + meta + "}" if meta else "")
30
32
 
31
33
  # %% ../nbs/api/15_qmd.ipynb #52637a70
32
- def div(txt, # Markdown to add meta to
33
- classes=None, # List of CSS classes to add
34
- style=None, # Dict of CSS styles to add
35
- **kwargs):
34
+ def div(
35
+ txt, # Markdown to add meta to
36
+ classes=None, # List of CSS classes to add
37
+ style=None, # Dict of CSS styles to add
38
+ **kwargs
39
+ ):
36
40
  "A qmd div with optional metadata section"
37
41
  return meta("::: ", classes=classes, style=style, **kwargs) + f"\n\n{txt}\n\n:::\n\n"
38
42
 
39
43
  # %% ../nbs/api/15_qmd.ipynb #f9f499f4
40
- def img(fname, # Image to link to
41
- classes=None, # List of CSS classes to add
42
- style=None, # Dict of CSS styles to add
43
- height=None, # Height attribute
44
- relative=None, # Tuple of (position,px)
45
- link=False, # Hyperlink to this image
46
- **kwargs):
44
+ def img(
45
+ fname, # Image to link to
46
+ classes=None, # List of CSS classes to add
47
+ style=None, # Dict of CSS styles to add
48
+ height=None, # Height attribute
49
+ relative=None, # Tuple of (position,px)
50
+ link=False, # Hyperlink to this image
51
+ **kwargs
52
+ ):
47
53
  "A qmd image"
48
54
  kwargs,style = kwargs or {}, style or {}
49
55
  if height: kwargs["height"]= f"{height}px"
@@ -55,23 +61,27 @@ def img(fname, # Image to link to
55
61
  return f'[{res}]({fname})' if link else res
56
62
 
57
63
  # %% ../nbs/api/15_qmd.ipynb #16d7aa5f
58
- def btn(txt, # Button text
59
- link, # Button link URL
60
- classes=None, # List of CSS classes to add
61
- style=None, # Dict of CSS styles to add
62
- **kwargs):
64
+ def btn(
65
+ txt, # Button text
66
+ link, # Button link URL
67
+ classes=None, # List of CSS classes to add
68
+ style=None, # Dict of CSS styles to add
69
+ **kwargs
70
+ ):
63
71
  "A qmd button"
64
72
  return meta(f'[{txt}]({link})', classes=classes, style=style, role="button")
65
73
 
66
74
  # %% ../nbs/api/15_qmd.ipynb #e414ed33
67
- def tbl_row(cols:list, # Auto-stringified columns to show in the row
68
- ):
75
+ def tbl_row(
76
+ cols:list, # Auto-stringified columns to show in the row
77
+ ):
69
78
  "Create a markdown table row from `cols`"
70
79
  return '|' + '|'.join(str(c or '') for c in cols) + '|'
71
80
 
72
81
  # %% ../nbs/api/15_qmd.ipynb #38f0641b
73
- def tbl_sep(sizes:int|list=3 # List of column sizes, or single `int` if all sizes the same
74
- ):
82
+ def tbl_sep(
83
+ sizes:int|list=3 # List of column sizes, or single `int` if all sizes the same
84
+ ):
75
85
  "Create a markdown table separator with relative column size `sizes`"
76
86
  if isinstance(sizes,int): sizes = [3]*sizes
77
87
  return tbl_row('-'*s for s in sizes)
@@ -249,15 +249,20 @@ def _copytree(a,b):
249
249
  copy_tree(a, b)
250
250
 
251
251
  # %% ../nbs/api/14_quarto.ipynb #caeaa153
252
+ def _readme_cands(cache, cfg):
253
+ "Locations where `quarto render -o README.md` may put its output, which differs by quarto version"
254
+ return cache/cfg.doc_path.name/'README.md', cache/'README.md'
255
+
252
256
  def _save_cached_readme(cache, cfg):
253
- tmp_doc_path = cache/cfg.doc_path.name
254
- readme = tmp_doc_path/'README.md'
255
- if readme.exists():
256
- readme_path = cfg.config_path/'README.md'
257
- if readme_path.exists(): readme_path.unlink() # py37 doesn't have `missing_ok`
258
- move(readme, cfg.config_path)
259
- _rdmi = tmp_doc_path/((cache/cfg.readme_nb).stem + '_files') # Supporting files for README
260
- if _rdmi.exists(): _copytree(_rdmi, cfg.config_path/_rdmi.name)
257
+ cands = _readme_cands(cache, cfg)
258
+ readme = next((f for f in cands if f.exists()), None)
259
+ if not readme: raise FileNotFoundError(f"quarto render did not produce a README.md in any of: {cands}")
260
+ readme_path = cfg.config_path/'README.md'
261
+ if readme_path.exists(): readme_path.unlink() # py37 doesn't have `missing_ok`
262
+ move(readme, cfg.config_path)
263
+ _rdmi = readme.parent/((cache/cfg.readme_nb).stem + '_files') # Supporting files for README
264
+ if _rdmi.exists(): _copytree(_rdmi, cfg.config_path/_rdmi.name)
265
+
261
266
 
262
267
  # %% ../nbs/api/14_quarto.ipynb #45d6bb5d
263
268
  @call_parse
@@ -272,6 +277,8 @@ def nbdev_readme(
272
277
 
273
278
  with _SidebarYmlRemoved(path): # to avoid rendering whole website
274
279
  cache = proc_nbs(path)
280
+ for f in _readme_cands(cache, cfg):
281
+ if f.exists(): f.unlink() # remove stale renders from either quarto layout
275
282
  _sprun(f'cd "{cache}" && quarto render "{cache/cfg.readme_nb}" -o README.md -t gfm --no-execute')
276
283
 
277
284
  _save_cached_readme(cache, cfg)
@@ -34,10 +34,12 @@ class BasicMarkdownRenderer(MarkdownRenderer):
34
34
  return doc+super()._repr_markdown_()
35
35
 
36
36
  # %% ../nbs/api/08_showdoc.ipynb #1256ef79
37
- def show_doc(sym, # Symbol to document
38
- renderer=None, # Optional renderer (defaults to markdown)
39
- name:str|None=None, # Optionally override displayed name of `sym`
40
- title_level:int=3): # Heading level to use for symbol name
37
+ def show_doc(
38
+ sym, # Symbol to document
39
+ renderer=None, # Optional renderer (defaults to markdown)
40
+ name:str|None=None, # Optionally override displayed name of `sym`
41
+ title_level:int=3 # Heading level to use for symbol name
42
+ ):
41
43
  "Show signature and docstring for `sym`"
42
44
  if renderer is None: renderer = get_config().get('renderer', None)
43
45
  if renderer is None: renderer=BasicMarkdownRenderer
@@ -25,15 +25,17 @@ from fastcore.nbio import *
25
25
  from execnb.shell import *
26
26
 
27
27
  # %% ../nbs/api/12_test.ipynb #3f4fa1ad
28
- def test_nb(fn, # file name of notebook to test
29
- skip_flags=None, # list of flags marking cells to skip
30
- force_flags=None, # list of flags marking cells to always run
31
- do_print=False, # print completion?
32
- showerr=True, # print errors to stderr?
33
- basepath=None, # path to add to sys.path
34
- verbose=False, # stream stdout/stderr from cells to console?
35
- save=False, # write outputs back to notebook on success?
36
- profile:bool=None): # load the IPython profile, as `ipykernel` does? (default: `exec_profile` config key)
28
+ def test_nb(
29
+ fn, # file name of notebook to test
30
+ skip_flags=None, # list of flags marking cells to skip
31
+ force_flags=None, # list of flags marking cells to always run
32
+ do_print=False, # print completion?
33
+ showerr=True, # print errors to stderr?
34
+ basepath=None, # path to add to sys.path
35
+ verbose=False, # stream stdout/stderr from cells to console?
36
+ save=False, # write outputs back to notebook on success?
37
+ profile:bool=None # load the IPython profile, as `ipykernel` does? (default: `exec_profile` config key)
38
+ ):
37
39
  "Execute tests in notebook in `fn` except those with `skip_flags`"
38
40
  faulthandler.register(signal.SIGINT, file=sys.__stderr__, all_threads=True, chain=True)
39
41
  fn = Path(fn)
@@ -73,9 +75,10 @@ def test_nb(fn, # file name of notebook to test
73
75
 
74
76
 
75
77
  # %% ../nbs/api/12_test.ipynb #d8bf1f1b-935d-4b69-ba96-827c5d7213f0
76
- def _keep_file(p:Path, # filename for which to check for `indicator_fname`
77
- ignore_fname:str # filename that will result in siblings being ignored
78
- ) -> bool:
78
+ def _keep_file(
79
+ p:Path, # filename for which to check for `indicator_fname`
80
+ ignore_fname:str # filename that will result in siblings being ignored
81
+ ) -> bool:
79
82
  "Returns False if `indicator_fname` is a sibling to `fname` else True"
80
83
  if p.exists(): return not bool(p.parent.ls().attrgot('name').filter(lambda x: x == ignore_fname))
81
84
  else: True
@@ -93,7 +96,8 @@ def nbdev_test(
93
96
  ignore_fname:str='.notest', # Filename that will result in siblings being ignored
94
97
  verbose:bool=False, # Print stdout/stderr from notebook cells?
95
98
  save:bool=False, # Write outputs back to notebooks on success?
96
- **kwargs):
99
+ **kwargs
100
+ ):
97
101
  "Test in parallel notebooks matching `path`, passing along `flags`"
98
102
  cfg = get_config(Path(path).resolve() if path else None)
99
103
  skip_flags = cfg.tst_flags
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nbdev
3
- Version: 3.1.0
3
+ Version: 3.2.0
4
4
  Summary: Create delightful software with Jupyter Notebooks
5
5
  Author-email: "Jeremy Howard and the fast.ai community" <j@fast.ai>
6
6
  License: Apache-2.0
@@ -16,7 +16,7 @@ Classifier: License :: OSI Approved :: Apache Software License
16
16
  Requires-Python: >=3.9
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
- Requires-Dist: fastcore>=1.14.1
19
+ Requires-Dist: fastcore>=1.14.6
20
20
  Requires-Dist: execnb>=0.2.4
21
21
  Requires-Dist: astunparse
22
22
  Requires-Dist: ghapi>=2.0.0
@@ -158,7 +158,7 @@ available commands:
158
158
  nbdev-pypi Create and upload Python package to PyPI
159
159
  nbdev-readme Create README.md from readme_nb (index.ipynb by default)
160
160
  nbdev-release-both Release both conda and PyPI packages
161
- nbdev-release-gh Calls `nbdev_changelog`, lets you edit the result, then pushes to git and calls `nbdev_release_git`
161
+ nbdev-release-gh Calls `nbdev-changelog`, lets you edit the result, then pushes to git and calls `nbdev-release-git`
162
162
  nbdev-release-git Tag and create a release in GitHub for the current version
163
163
  nbdev-requirements Writes a `requirements.txt` file to `directory` based on pyproject.toml.
164
164
  nbdev-sidebar Create sidebar.yml
@@ -184,6 +184,9 @@ some_module.something()
184
184
  Instead, split this into two cells, one which does `import some_module`,
185
185
  and the other which does `some_module.something()`.
186
186
 
187
+ Only top-level statements count: `try: import` blocks and imports inside
188
+ function definitions are fine.
189
+
187
190
  The reason for this is that when we create your documentation website,
188
191
  we ensure that all of the signatures for functions you document are up
189
192
  to date, by running the imports, exported cells, and
@@ -1,4 +1,4 @@
1
- fastcore>=1.14.1
1
+ fastcore>=1.14.6
2
2
  execnb>=0.2.4
3
3
  astunparse
4
4
  ghapi>=2.0.0
@@ -19,7 +19,7 @@ classifiers = [
19
19
  "License :: OSI Approved :: Apache Software License",
20
20
  ]
21
21
  dynamic = ["version"]
22
- dependencies = [ "fastcore>=1.14.1", "execnb>=0.2.4", "astunparse", "ghapi>=2.0.0", "watchdog", "asttokens",
22
+ dependencies = [ "fastcore>=1.14.6", "execnb>=0.2.4", "astunparse", "ghapi>=2.0.0", "watchdog", "asttokens",
23
23
  "setuptools", "build", "fastgit", "pyyaml", "tomli; python_version < '3.11'", ]
24
24
 
25
25
  [project.optional-dependencies]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes