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.
- {nbdev-3.3.23/nbdev.egg-info → nbdev-3.3.25}/PKG-INFO +1 -1
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/__init__.py +1 -1
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/config.py +1 -1
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/quarto.py +6 -4
- nbdev-3.3.25/nbdev/readme_filter.py +36 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/release.py +2 -2
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/skill.py +8 -8
- {nbdev-3.3.23 → nbdev-3.3.25/nbdev.egg-info}/PKG-INFO +1 -1
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev.egg-info/SOURCES.txt +1 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/tests/test_quarto_render.py +35 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/CONTRIBUTING.md +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/LICENSE +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/README.md +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/_modidx.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/clean.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/cli.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/diff.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/doclinks.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/export.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/extract_attachments.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/frontmatter.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/imports.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/maker.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/merge.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/migrate.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/moddocs.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/process.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/processors.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/qmd.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/quarto_render.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/scrubmagics.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/serve.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/serve_drv.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/showdoc.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/sync.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev/test.py +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev.egg-info/dependency_links.txt +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev.egg-info/entry_points.txt +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev.egg-info/requires.txt +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/nbdev.egg-info/top_level.txt +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/pyproject.toml +0 -0
- {nbdev-3.3.23 → nbdev-3.3.25}/setup.cfg +0 -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.
|
|
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(
|
|
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
|
-
|
|
67
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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().
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
"""
|
|
@@ -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] ', 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 '' 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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|