nbdev 3.3.23__tar.gz → 3.3.25__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 (42) hide show
  1. {nbdev-3.3.23/nbdev.egg-info → nbdev-3.3.25}/PKG-INFO +1 -1
  2. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/__init__.py +1 -1
  3. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/config.py +1 -1
  4. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/quarto.py +6 -4
  5. nbdev-3.3.25/nbdev/readme_filter.py +36 -0
  6. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/release.py +2 -2
  7. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/skill.py +8 -8
  8. {nbdev-3.3.23 → nbdev-3.3.25/nbdev.egg-info}/PKG-INFO +1 -1
  9. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev.egg-info/SOURCES.txt +1 -0
  10. {nbdev-3.3.23 → nbdev-3.3.25}/tests/test_quarto_render.py +35 -0
  11. {nbdev-3.3.23 → nbdev-3.3.25}/CONTRIBUTING.md +0 -0
  12. {nbdev-3.3.23 → nbdev-3.3.25}/LICENSE +0 -0
  13. {nbdev-3.3.23 → nbdev-3.3.25}/README.md +0 -0
  14. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/_modidx.py +0 -0
  15. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/clean.py +0 -0
  16. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/cli.py +0 -0
  17. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/diff.py +0 -0
  18. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/doclinks.py +0 -0
  19. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/export.py +0 -0
  20. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/extract_attachments.py +0 -0
  21. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/frontmatter.py +0 -0
  22. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/imports.py +0 -0
  23. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/maker.py +0 -0
  24. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/merge.py +0 -0
  25. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/migrate.py +0 -0
  26. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/moddocs.py +0 -0
  27. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/process.py +0 -0
  28. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/processors.py +0 -0
  29. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/qmd.py +0 -0
  30. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/quarto_render.py +0 -0
  31. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/scrubmagics.py +0 -0
  32. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/serve.py +0 -0
  33. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/serve_drv.py +0 -0
  34. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/showdoc.py +0 -0
  35. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/sync.py +0 -0
  36. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/test.py +0 -0
  37. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev.egg-info/dependency_links.txt +0 -0
  38. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev.egg-info/entry_points.txt +0 -0
  39. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev.egg-info/requires.txt +0 -0
  40. {nbdev-3.3.23 → nbdev-3.3.25}/nbdev.egg-info/top_level.txt +0 -0
  41. {nbdev-3.3.23 → nbdev-3.3.25}/pyproject.toml +0 -0
  42. {nbdev-3.3.23 → nbdev-3.3.25}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nbdev
3
- Version: 3.3.23
3
+ Version: 3.3.25
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-Expression: Apache-2.0
@@ -6,7 +6,7 @@ Modules:
6
6
  - `nbdev.moddocs`: # Module docs: creating them from existing notebooks
7
7
  - `nbdev.skill`: Write, read and review nbdev notebooks as source, documentation, examples and tests. You MUST read this before any work on a project with notebooks."""
8
8
 
9
- __version__ = "3.3.23"
9
+ __version__ = "3.3.25"
10
10
 
11
11
  from .doclinks import nbdev_export
12
12
  from .showdoc import show_doc
@@ -360,7 +360,7 @@ def add_init(path=None):
360
360
  subds = (os.listdir(r/d) for d in ds)
361
361
  if _has_py(fs) or any(filter(_has_py, subds)) and not (r/_init).exists(): (r/_init).touch()
362
362
  if get_config().get('put_version_in_init', True): update_version(path)
363
- if get_config().get('update_pyproject', True): update_proj(path.parent)
363
+ if get_config().get('update_pyproject', True): update_proj(get_config().config_path)
364
364
  update_init_mdoc(path)
365
365
 
366
366
  # %% ../nbs/api/01_config.ipynb #a01b98bb
@@ -63,8 +63,8 @@ def install_quarto():
63
63
  def install():
64
64
  "Install Quarto and the current library"
65
65
  install_quarto.__wrapped__()
66
- d = get_config().lib_path
67
- if (d/'__init__.py').exists(): system(f'pip install -e "{d.parent}[dev]"')
66
+ cfg = get_config()
67
+ if (cfg.lib_path/'__init__.py').exists(): system(f'pip install -e "{cfg.config_path}[dev]"')
68
68
 
69
69
  # %% ../nbs/api/14_quarto.ipynb #b93f6def
70
70
  def _pre(p,b=True): return ' ' * (len(p.parts)) + ('- ' if b else ' ')
@@ -201,7 +201,7 @@ def refresh_quarto_yml():
201
201
  def _ensure_quarto():
202
202
  if shutil.which('quarto'): return
203
203
  print("Quarto is not installed. We will download and install it for you.")
204
- install.__wrapped__()
204
+ install_quarto.__wrapped__()
205
205
 
206
206
  # %% ../nbs/api/14_quarto.ipynb #66163c30
207
207
  def _chk_nbdev_yml(path):
@@ -290,7 +290,9 @@ def nbdev_readme(
290
290
  _strip_sidebar(cache) # to avoid rendering whole website
291
291
  for f in _readme_cands(cache, cfg):
292
292
  if f.exists(): f.unlink() # remove stale renders from either quarto layout
293
- _sprun(f'cd "{cache}" && quarto render "{cache/cfg.readme_nb}" -o README.md -t gfm --no-execute -M wrap:preserve')
293
+ from nbdev import readme_filter
294
+ filt = fr""" -M 'filters:["{readme_filter.__file__}"]'""" if cfg.doc_host else ''
295
+ _sprun(f'cd "{cache}" && quarto render "{cache/cfg.readme_nb}" -o README.md -t gfm --no-execute -M wrap:preserve{filt}')
294
296
 
295
297
  _save_cached_readme(cache, cfg)
296
298
 
@@ -0,0 +1,36 @@
1
+ r"Pandoc filter for README documentation links."
2
+
3
+ from fastcore.utils import *
4
+ from fastcore.script import *
5
+ from nbdev.config import *
6
+ from urllib.parse import urlsplit, urlunsplit, urljoin
7
+
8
+
9
+ def doc_link(target, base, nbdir='.'):
10
+ "Convert a relative documentation link to its hosted URL."
11
+ u = urlsplit(target)
12
+ p = Path(u.path)
13
+ if u.scheme or u.netloc or p.suffix not in ('.ipynb', '.qmd', '.html', '.txt'): return target
14
+ if p.suffix=='.ipynb': p = nbpath2html(p)
15
+ elif p.suffix=='.qmd': p = p.with_suffix('.html')
16
+ path = urljoin(nbdir.rstrip('/')+'/', p.as_posix()).lstrip('/')
17
+ return urljoin(base.rstrip('/')+'/', urlunsplit(('', '', path, u.query, u.fragment)))
18
+
19
+
20
+ def rewrite_links(node, base, nbdir='.'):
21
+ "Rewrite documentation links in a Pandoc syntax tree."
22
+ if isinstance(node, list):
23
+ for item in node: rewrite_links(item, base, nbdir)
24
+ elif isinstance(node, dict):
25
+ if node.get('t')=='Link': node['c'][2][0] = doc_link(node['c'][2][0], base, nbdir)
26
+ for item in node.values(): rewrite_links(item, base, nbdir)
27
+
28
+
29
+ @call_parse
30
+ def main(
31
+ fmt:str, # Output format supplied by Pandoc
32
+ ):
33
+ "Rewrite documentation links in Pandoc JSON from stdin."
34
+ cfg,doc = get_config(),loads(sys.stdin.read())
35
+ rewrite_links(doc['blocks'], cfg.doc_url, Path(cfg.readme_nb).parent.as_posix())
36
+ print(dumps(doc))
@@ -260,7 +260,7 @@ def _get_conda_meta():
260
260
  'source': {'url':rel['url'], 'sha256':rel['digests']['sha256']}
261
261
  }
262
262
 
263
- _dir = cfg.lib_path.parent
263
+ _dir = cfg.config_path
264
264
  readme = _dir/'README.md'
265
265
  descr = readme.read_text() if readme.exists() else ''
266
266
  d2 = {
@@ -360,7 +360,7 @@ def release_pypi(
360
360
  verbose:bool=False # Pass --verbose to twine upload
361
361
  ):
362
362
  "Create and upload Python package to PyPI"
363
- _dir = get_config().lib_path.parent
363
+ _dir = get_config().config_path
364
364
  q = ' --quiet' if quiet else ''
365
365
  p = ' --disable-progress-bar' if quiet else ''
366
366
  system(f'cd {_dir} && rm -rf dist build && python -m build{q}')
@@ -1,6 +1,6 @@
1
1
  """Write, read and review nbdev notebooks as source, documentation, examples and tests. You MUST read this before any work on a project with notebooks.
2
2
 
3
- # Source
3
+ ## Source
4
4
 
5
5
  Write notebooks to be read top-to-bottom, interleaving implementation, explanation, examples, outputs, and failure demonstrations. Follow these conventions in published libraries. In internal projects, match the surrounding notebooks.
6
6
 
@@ -10,7 +10,7 @@ Understand and review work through the notebooks and their `git diff`, never gen
10
10
 
11
11
  For project-level questions, read `nbs/index.ipynb`, the source of README.md; regenerate with `nbdev-readme` after changes.
12
12
 
13
- # Structure and authoring
13
+ ## Structure and authoring
14
14
 
15
15
  Choose tutorial, how-to, explanation, or reference. Open with an H1 title cell and `>` subtitle, then a brief introduction. Use H2s for major concepts without fragmenting short narratives. Each heading belongs in its own markdown cell so Jupyter can collapse sections.
16
16
 
@@ -18,13 +18,13 @@ Before changing a notebook, read the whole notebook or a summary of every cell.
18
18
 
19
19
  Develop one idea at a time: a small implementation, its explanation, and a lesson if it's a substantive API. Introduce each lesson in markdown; split it when the introduction becomes complicated. Extend existing examples rather than adding near-duplicates. Build classes with `@patch` beside each method's explanation unless that obscures the API.
20
20
 
21
- When new behavior needs a lesson, choose its narrative position, write the lesson first, run preceding cells as needed, and see it fail. Add its markdown introduction and implementation above it, then run both to see it pass. For bugs, revise an existing example to exercise the failing path; if no revision fits, add an assertion to it. If no documented behavior changes, change no lesson cells. Never add a cell merely to witness a fix.
21
+ When new behavior needs a lesson (which it often doesn't, if it's trivial logic that doesn't need teaching), choose its narrative position, write the lesson first (or better still, slightly modify and existing listen), run preceding cells as needed, and see it fail. Add its markdown introduction and implementation above it, then run both to see it pass. For bugs, revise an existing example to exercise the failing path; if no revision fits, add an assertion to it. If no documented behavior changes, change no lesson cells. Never add a cell merely to witness a fix.
22
22
 
23
23
  Read existing examples before experimenting. Explore in the notebook, not in a separate kernel check; keep useful explorations as lessons and delete the rest. Always try to leave a notebook better than you found it.
24
24
 
25
25
  Reserve underscore names for machinery without a coherent independent contract, not for everything used only internally. If a helper is only useful internally, the design is often awkward.
26
26
 
27
- # Prose and module documentation
27
+ ## Prose and module documentation
28
28
 
29
29
  In markdown, explain rationale, distinctions and guarantees. Don't narrate code line by line or write filler transitions. Place markdown where it reads correctly on the generated page, normally after the definition. Use short symbol docstrings, parameter/return docments beside signatures, and backticked symbol names for nbdev links. Extended explanation, examples, and warnings belong in markdown.
30
30
 
@@ -34,7 +34,7 @@ In markdown, explain rationale, distinctions and guarantees. Don't narrate code
34
34
 
35
35
  Check claims by running code before documenting them; preview assembly with `nbdev.export.nb_mdoc`. `nbdev-export` lists a module in package documentation and `llms.txt` if its docstring has more than the default summary. Only extend docstrings of modules read on their own. Export the opening paragraphs of `index.ipynb` for the package intro.
36
36
 
37
- # Lesson cells
37
+ ## Lesson cells
38
38
 
39
39
  A notebook guides a reader through what the code does. Readability comes first.
40
40
 
@@ -59,7 +59,7 @@ Consider a rewrite when you see these:
59
59
  - Show errors with `expect_fail`, not `try`/`except`. Move long docstrings to markdown.
60
60
  - Resolve TODO/FIXME example comments or move them to issues.
61
61
 
62
- # State and execution
62
+ ## State and execution
63
63
 
64
64
  Define values near first use, introduce shared setup, reuse established objects, and don't reassign names later cells depend on. End exploratory cells with the expression recording what was learned when useful.
65
65
 
@@ -67,7 +67,7 @@ Keep imports in dedicated cells, including in lessons: docs builds execute impor
67
67
 
68
68
  Stored outputs are generated and may be stale during editing. Don't stop work, clear them by hand, or edit notebook JSON because they no longer match the source. At PR time, regenerate them with `nbdev-test --save` if the project keeps saved outputs.
69
69
 
70
- # Directives and nbdev v3
70
+ ## Directives and nbdev v3
71
71
 
72
72
  - `#| default_exp` names the generated module; `#| export` includes a cell there. Exported underscore helpers need not be public.
73
73
  - `#| hide` hides distracting necessities from the page.
@@ -76,7 +76,7 @@ Stored outputs are generated and may be stale during editing. Don't stop work, c
76
76
 
77
77
  nbdev v3 (Jan 2026) uses `pyproject.toml`, not `settings.ini`: metadata in `[project]`, nbdev settings in `[tool.nbdev]` (default `nbs_path='nbs'`, `doc_path='_docs'`), version in `__init__.py` via `dynamic = ["version"]`, and `_modidx` in `[project.entry-points.nbdev]`. CLIs use hyphens (`nbdev-export`, `nbdev-test`); Python names retain underscores. GitHub actions are `fastai/workflows/nbdev3-ci` and `quarto-ghp3`.
78
78
 
79
- # Finish
79
+ ## Finish
80
80
 
81
81
  Revise affected prose, displays, and assertions together; changed assertions must fail on old code and pass on new. Re-read the touched narrative for readability. Run `nbdev-test <nb>`.
82
82
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nbdev
3
- Version: 3.3.23
3
+ Version: 3.3.25
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-Expression: Apache-2.0
@@ -22,6 +22,7 @@ nbdev/processors.py
22
22
  nbdev/qmd.py
23
23
  nbdev/quarto.py
24
24
  nbdev/quarto_render.py
25
+ nbdev/readme_filter.py
25
26
  nbdev/release.py
26
27
  nbdev/scrubmagics.py
27
28
  nbdev/serve.py
@@ -2,6 +2,41 @@ import json, shutil, subprocess, pytest
2
2
  from xml.etree import ElementTree as ET
3
3
  from fastcore.test import test_eq as teq
4
4
  from nbdev.quarto_render import render_quarto
5
+ from nbdev.quarto import nbdev_readme, refresh_quarto_yml
6
+ from nbdev.readme_filter import doc_link
7
+ from fastcore.nbio import new_nb, mk_cell, write_nb
8
+
9
+
10
+ @pytest.mark.skipif(not shutil.which('quarto'), reason='requires Quarto')
11
+ def test_readme_links(tmp_path, monkeypatch):
12
+ monkeypatch.chdir(tmp_path)
13
+ (tmp_path/'pyproject.toml').write_text(r'''[project]
14
+ name = "example"
15
+ [project.urls]
16
+ Documentation = "https://example.com/project/"
17
+ [tool.nbdev]
18
+ ''')
19
+ nbs = tmp_path/'nbs'
20
+ nbs.mkdir()
21
+ base = 'https://example.com/project/'
22
+ links = [('guide/01_Intro.ipynb?q=1#intro', base+'guide/intro.html?q=1#intro'),
23
+ ('guide/02_intro.qmd', base+'guide/02_intro.html'), ('guide/intro.html', base+'guide/intro.html'),
24
+ ('/llms.txt', base+'llms.txt'), ('llms-ctx.txt', base+'llms-ctx.txt'),
25
+ ('https://other.com/guide.html', 'https://other.com/guide.html'),
26
+ ('#section', '#section'), ('LICENSE', 'LICENSE')]
27
+ text = '\n\n'.join([*(f'[Link]({src})' for src,_ in links),
28
+ r'[Reference][guide] ![Image](image.png)', r'[guide]: guide/01_Intro.ipynb#intro',
29
+ '```markdown\n[Example](guide/01_Intro.ipynb)\n```'])
30
+ write_nb(new_nb([mk_cell('# Example', 'markdown'), mk_cell(text, 'markdown')]), nbs/'index.ipynb')
31
+ refresh_quarto_yml()
32
+ nbdev_readme.__wrapped__()
33
+ result = (tmp_path/'README.md').read_text()
34
+ for _,dest in links: assert f']({dest})' in result
35
+ assert f'[Reference]({base}guide/intro.html#intro)' in result
36
+ assert '![Image](image.png)' in result and '[Example](guide/01_Intro.ipynb)' in result
37
+ teq(doc_link('../guide/01_intro.ipynb', base, 'start'), base+'guide/intro.html')
38
+ teq(doc_link('/llms.txt', base, 'start'), base+'llms.txt')
39
+ teq(doc_link('//other.com/llms.txt', base), '//other.com/llms.txt')
5
40
 
6
41
 
7
42
  @pytest.mark.skipif(not shutil.which('quarto'), reason='requires Quarto')
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
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