Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion nbdev/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def _find_nbdev_pyproject(path=None):
# %% ../nbs/api/01_config.ipynb #3dac70e0
nbdev_defaults = dict(nbs_path='nbs', doc_path='_docs', tst_flags='notest', recursive=True, readme_nb='index.ipynb',
clean_ids=True, clear_all=False, put_version_in_init=True, jupyter_hooks=False, custom_sidebar=False, branch='main',
doc_procs=[], export_procs=[], exec_profile=True, cell_timeout=600)
doc_procs=[], export_procs=[], exec_profile=True, exec_all=False, cell_timeout=600)

_path_keys = 'lib_path', 'nbs_path', 'doc_path'

Expand Down
19 changes: 14 additions & 5 deletions nbdev/processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,15 @@ def _ast_contains(trees, types):

def _tl_contains(trees, types): return any(isinstance(t, types) for t in trees)

def _do_eval(cell):
def _do_eval(cell, all_cells=False, dflt=True, flags=frozenset()):
if cell_lang(cell) != 'python': return
if not cell.source or 'nbdev_export'+'()' in cell.source: return
trees = cell.parsed_()
if cell.cell_type != 'code' or not trees: return
if all_cells:
v = cell.directives_.get('eval')
run = dflt if v is None else v.lower() != 'false'
return run and not (cell.directives_.keys() & flags) and 'skip-execution' not in cell.metadata.get('tags', [])
if cell.directives_.get('eval', '').lower() == 'false': return

_show_dirs = {'export','exports','exporti','exec_doc'}
Expand All @@ -245,17 +249,22 @@ def _do_eval(cell):

# %% ../nbs/api/10_processors.ipynb #867cf721
class exec_show_docs(Processor):
"Execute cells needed for `show_docs` output, including exported cells and imports"
"Execute cells needed for `show_docs` output, including exported cells and imports, or every cell under `exec_all`"
def begin(self):
if nb_lang(self.nb) != 'python': return
self.k = CaptureShell(profile=bool(get_config().exec_profile))
cfg,fm = get_config(),getattr(self.nb, 'frontmatter_', {})
self.all_cells = str2bool(fm.get('exec_all', cfg.exec_all))
self.dflt = fm_default_eval(fm)
flags = cfg.tst_flags
self.flags = set(flags.split() if isinstance(flags, str) else flags)
self.k = CaptureShell(profile=bool(cfg.exec_profile))
self.k.run_cell('from nbdev.showdoc import show_doc')

def __call__(self, cell):
if not self.nb.has_docs_ or not hasattr(self, 'k'): return
if not hasattr(self, 'k') or not (self.nb.has_docs_ or self.all_cells): return
fm = getattr(self.nb, 'frontmatter_', {})
if str2bool(fm.get('skip_showdoc', False)): return
if _do_eval(cell): self.k.cell(cell)
if _do_eval(cell, self.all_cells, self.dflt, self.flags): self.k.cell(cell)
title = fm.get('title', '')
if (e := self.k.exc):
raise Exception(f"Error{' in notebook: '+title if title else ''} in cell {cell.idx_} :\n{cell.source}\n{type(e).__name__}: {e}") from e
Expand Down
9 changes: 6 additions & 3 deletions nbs/api/01_config.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@
"#| export\n",
"nbdev_defaults = dict(nbs_path='nbs', doc_path='_docs', tst_flags='notest', recursive=True, readme_nb='index.ipynb',\n",
" clean_ids=True, clear_all=False, put_version_in_init=True, jupyter_hooks=False, custom_sidebar=False, branch='main',\n",
" doc_procs=[], export_procs=[], exec_profile=True, cell_timeout=600)\n",
" doc_procs=[], export_procs=[], exec_profile=True, exec_all=False, cell_timeout=600)\n",
"\n",
"_path_keys = 'lib_path', 'nbs_path', 'doc_path'"
]
Expand Down Expand Up @@ -1287,10 +1287,13 @@
"solveit": {
"default_code": true,
"mode": "learning",
"reasoning_effort": "h",
"reasoning_model": "anthropic/claude-opus-5-5",
"standard_effort": "m",
"standard_model": "openai/gpt-6-luna",
"use_fence": false,
"use_thinking": false,
"use_tools": true,
"ver": 2
"use_tools": true
}
},
"nbformat": 4,
Expand Down
55 changes: 48 additions & 7 deletions nbs/api/10_processors.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -704,11 +704,15 @@
"\n",
"def _tl_contains(trees, types): return any(isinstance(t, types) for t in trees)\n",
"\n",
"def _do_eval(cell):\n",
"def _do_eval(cell, all_cells=False, dflt=True, flags=frozenset()):\n",
" if cell_lang(cell) != 'python': return\n",
" if not cell.source or 'nbdev_export'+'()' in cell.source: return\n",
" trees = cell.parsed_()\n",
" if cell.cell_type != 'code' or not trees: return\n",
" if all_cells:\n",
" v = cell.directives_.get('eval')\n",
" run = dflt if v is None else v.lower() != 'false'\n",
" return run and not (cell.directives_.keys() & flags) and 'skip-execution' not in cell.metadata.get('tags', [])\n",
" if cell.directives_.get('eval', '').lower() == 'false': return\n",
"\n",
" _show_dirs = {'export','exports','exporti','exec_doc'}\n",
Expand Down Expand Up @@ -753,17 +757,22 @@
"source": [
"#| export\n",
"class exec_show_docs(Processor):\n",
" \"Execute cells needed for `show_docs` output, including exported cells and imports\"\n",
" \"Execute cells needed for `show_docs` output, including exported cells and imports, or every cell under `exec_all`\"\n",
" def begin(self):\n",
" if nb_lang(self.nb) != 'python': return\n",
" self.k = CaptureShell(profile=bool(get_config().exec_profile))\n",
" cfg,fm = get_config(),getattr(self.nb, 'frontmatter_', {})\n",
" self.all_cells = str2bool(fm.get('exec_all', cfg.exec_all))\n",
" self.dflt = fm_default_eval(fm)\n",
" flags = cfg.tst_flags\n",
" self.flags = set(flags.split() if isinstance(flags, str) else flags)\n",
" self.k = CaptureShell(profile=bool(cfg.exec_profile))\n",
" self.k.run_cell('from nbdev.showdoc import show_doc')\n",
"\n",
" def __call__(self, cell):\n",
" if not self.nb.has_docs_ or not hasattr(self, 'k'): return\n",
" if not hasattr(self, 'k') or not (self.nb.has_docs_ or self.all_cells): return\n",
" fm = getattr(self.nb, 'frontmatter_', {})\n",
" if str2bool(fm.get('skip_showdoc', False)): return\n",
" if _do_eval(cell): self.k.cell(cell)\n",
" if _do_eval(cell, self.all_cells, self.dflt, self.flags): self.k.cell(cell)\n",
" title = fm.get('title', '')\n",
" if (e := self.k.exc):\n",
" raise Exception(f\"Error{' in notebook: '+title if title else ''} in cell {cell.idx_} :\\n{cell.source}\\n{type(e).__name__}: {e}\") from e\n",
Expand All @@ -784,7 +793,7 @@
"id": "ded579a9",
"metadata": {},
"source": [
"`exec_show_docs` runs the cells the docs need: exports, imports, `show_doc` calls, and anything marked `exec_doc`. A notebook whose frontmatter sets `skip_showdoc: true` is not executed at all during docs rendering, so its stored outputs are used as-is."
"`exec_show_docs` runs the cells the docs need: exports, imports, `show_doc` calls, and anything marked `exec_doc`. With `exec_all` set it runs every cell instead. A notebook whose frontmatter sets `skip_showdoc: true` is not executed at all during docs rendering, whatever else is set, and its stored outputs are used as-is."
]
},
{
Expand All @@ -798,6 +807,29 @@
"assert res"
]
},
{
"cell_type": "markdown",
"id": "e42c2a07",
"metadata": {},
"source": [
"`exec_all: true` in a notebook's frontmatter, or `exec_all = true` under `[tool.nbdev]` for a whole project, runs every code cell the test runner would run, so a notebook with no exports or `show_doc` calls is executed too. Cells that `nbdev-test` skips, through `eval: false` or a `tst_flags` flag such as `notest`, are skipped here as well:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9d58ac3b",
"metadata": {},
"outputs": [],
"source": [
"cells = [mk_cell('---\\nexec_all: true\\n---', 'raw'), mk_cell('x = 1'), mk_cell('x + 1'),\n",
" mk_cell('#| notest\\nraise Exception(\"skipped by tst_flags\")'), mk_cell('#| eval: false\\nraise Exception(\"skipped by eval\")')]\n",
"nb = dict2nb(dict(cells=cells, metadata={}, nbformat=4, nbformat_minor=5))\n",
"nb.path_ = 'exec_all.ipynb'\n",
"NBProcessor(nb=nb, procs=[FrontmatterProc, add_show_docs, exec_show_docs]).process()\n",
"test_eq(nb.cells[2].outputs[0].data['text/plain'], ['2'])"
]
},
{
"cell_type": "markdown",
"id": "b1a63b85",
Expand Down Expand Up @@ -878,7 +910,16 @@
"source": []
}
],
"metadata": {},
"metadata": {
"solveit": {
"mode": "learning",
"reasoning_effort": "h",
"reasoning_model": "anthropic/claude-opus-5-5",
"standard_effort": "m",
"standard_model": "openai/gpt-6-luna",
"use_thinking": false
}
},
"nbformat": 4,
"nbformat_minor": 5
}
12 changes: 11 additions & 1 deletion nbs/explanations/directives.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,7 @@
"\n",
"- `skip_exec: true` makes `nbdev-test` skip the notebook and report it as passing. Use it when the notebook needs credentials or live services unavailable in the test environment.\n",
"- `skip_showdoc: true` makes docs rendering use stored outputs without executing cells.\n",
"- `exec_all: true` makes docs rendering execute every cell, not only exports, imports and `show_doc` calls. `exec_all = true` under `[tool.nbdev]` does the same for every notebook in the project.\n",
"\n",
"For example, nbdev's own `api/19_diff.ipynb` sets `skip_exec: true`, and `tutorials/modular_nbdev.ipynb` sets `skip_showdoc: true`."
]
Expand Down Expand Up @@ -829,7 +830,16 @@
"source": []
}
],
"metadata": {},
"metadata": {
"solveit": {
"mode": "learning",
"reasoning_effort": "h",
"reasoning_model": "anthropic/claude-opus-5-5",
"standard_effort": "m",
"standard_model": "openai/gpt-6-luna",
"use_thinking": false
}
},
"nbformat": 4,
"nbformat_minor": 5
}
13 changes: 12 additions & 1 deletion nbs/explanations/docs.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,8 @@
"---\n",
"```\n",
"\n",
"To do that for every notebook in a project, set `exec_all = true` under `[tool.nbdev]` in `pyproject.toml`. Cells that `nbdev-test` skips, through `eval: false` or a `tst_flags` flag, are skipped here as well.\n",
"\n",
"#### Skipping Execution\n",
"\n",
"Likewise, you can instruct nbdev to not execute any cells when rendering your docs with the following front matter:\n",
Expand Down Expand Up @@ -593,7 +595,16 @@
"source": []
}
],
"metadata": {},
"metadata": {
"solveit": {
"mode": "learning",
"reasoning_effort": "h",
"reasoning_model": "anthropic/claude-opus-5-5",
"standard_effort": "m",
"standard_model": "openai/gpt-6-luna",
"use_thinking": false
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading