diff --git a/nbdev/_modidx.py b/nbdev/_modidx.py index 004968d89..07d4d0676 100644 --- a/nbdev/_modidx.py +++ b/nbdev/_modidx.py @@ -26,7 +26,8 @@ 'nbdev.cli.nb_export_cli': ('api/cli.html#nb_export_cli', 'nbdev/cli.py'), 'nbdev.cli.nbdev_filter': ('api/cli.html#nbdev_filter', 'nbdev/cli.py'), 'nbdev.cli.nbdev_new': ('api/cli.html#nbdev_new', 'nbdev/cli.py'), - 'nbdev.cli.nbdev_update_license': ('api/cli.html#nbdev_update_license', 'nbdev/cli.py')}, + 'nbdev.cli.nbdev_update_license': ('api/cli.html#nbdev_update_license', 'nbdev/cli.py'), + 'nbdev.cli.watch_export': ('api/cli.html#watch_export', 'nbdev/cli.py')}, 'nbdev.config': { 'nbdev.config._apply_defaults': ('api/config.html#_apply_defaults', 'nbdev/config.py'), 'nbdev.config._basic_export_nb': ('api/config.html#_basic_export_nb', 'nbdev/config.py'), 'nbdev.config._cfg2txt': ('api/config.html#_cfg2txt', 'nbdev/config.py'), diff --git a/nbdev/cli.py b/nbdev/cli.py index 0ca4620f2..2c4c31b17 100644 --- a/nbdev/cli.py +++ b/nbdev/cli.py @@ -5,6 +5,7 @@ # %% ../nbs/api/13_cli.ipynb 2 from __future__ import annotations import warnings +import time from .config import * from .process import * @@ -12,10 +13,11 @@ from .doclinks import * from .test import * from .clean import * -from .quarto import nbdev_readme, refresh_quarto_yml +from .quarto import nbdev_readme, refresh_quarto_yml, fs_watchdog from .export import nb_export from .frontmatter import FrontmatterProc +from fastcore.xtras import run from execnb.nbio import * from fastcore.meta import * from fastcore.utils import * @@ -28,7 +30,8 @@ import os, tarfile, sys # %% auto 0 -__all__ = ['mapping', 'nbdev_filter', 'extract_tgz', 'nbdev_new', 'nbdev_update_license', 'nb_export_cli', 'chelp'] +__all__ = ['mapping', 'nbdev_filter', 'extract_tgz', 'nbdev_new', 'nbdev_update_license', 'nb_export_cli', 'watch_export', + 'chelp'] # %% ../nbs/api/13_cli.ipynb @call_parse @@ -168,6 +171,25 @@ def nb_export_cli(nbname, "Export a single nbdev notebook to a python script." return nb_export(nbname=nbname, debug=debug, **kwargs) +# %% ../nbs/api/13_cli.ipynb +@call_parse +def watch_export(nbs:str=None, # Nb directory to watch for changes + lib:str=None, # Export directory to write py files to + force:bool=False # Ignore nbdev config if in nbdev project + ): + '''Use `nb_export` on ipynb files in `nbs` directory on changes using nbdev config if available''' + cfg = get_config() if is_nbdev() else None + nbs = nbs or (cfg.nbs_path if cfg else '.') + lib = lib or (cfg.lib_path if cfg else '.') + if cfg and (nbs != cfg.nbs_path or lib != cfg.lib_path) and not force: + raise ValueError("In nbdev project. Use --force to override config.") + def _export(e,lib=lib): + p = e.src_path + if (not '.ipynb_checkpoints' in p and p.endswith('.ipynb') and not Path(p).name.startswith('.~')): + run(f'nb_export --lib_path {lib} "{p}"') + with fs_watchdog(_export, nbs): + while True: time.sleep(1) + # %% ../nbs/api/13_cli.ipynb @call_parse def chelp(): diff --git a/nbs/api/13_cli.ipynb b/nbs/api/13_cli.ipynb index 33feb8320..3696109c7 100644 --- a/nbs/api/13_cli.ipynb +++ b/nbs/api/13_cli.ipynb @@ -30,6 +30,7 @@ "#|export\n", "from __future__ import annotations\n", "import warnings\n", + "import time\n", "\n", "from nbdev.config import *\n", "from nbdev.process import *\n", @@ -37,10 +38,11 @@ "from nbdev.doclinks import *\n", "from nbdev.test import *\n", "from nbdev.clean import *\n", - "from nbdev.quarto import nbdev_readme, refresh_quarto_yml\n", + "from nbdev.quarto import nbdev_readme, refresh_quarto_yml, fs_watchdog\n", "from nbdev.export import nb_export\n", "from nbdev.frontmatter import FrontmatterProc\n", "\n", + "from fastcore.xtras import run\n", "from execnb.nbio import *\n", "from fastcore.meta import *\n", "from fastcore.utils import *\n", @@ -304,6 +306,33 @@ " return nb_export(nbname=nbname, debug=debug, **kwargs)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "aaa472e7", + "metadata": {}, + "outputs": [], + "source": [ + "#|export\n", + "@call_parse\n", + "def watch_export(nbs:str=None, # Nb directory to watch for changes\n", + " lib:str=None, # Export directory to write py files to\n", + " force:bool=False # Ignore nbdev config if in nbdev project\n", + " ):\n", + " '''Use `nb_export` on ipynb files in `nbs` directory on changes using nbdev config if available'''\n", + " cfg = get_config() if is_nbdev() else None\n", + " nbs = nbs or (cfg.nbs_path if cfg else '.')\n", + " lib = lib or (cfg.lib_path if cfg else '.')\n", + " if cfg and (nbs != cfg.nbs_path or lib != cfg.lib_path) and not force:\n", + " raise ValueError(\"In nbdev project. Use --force to override config.\")\n", + " def _export(e,lib=lib):\n", + " p = e.src_path\n", + " if (not '.ipynb_checkpoints' in p and p.endswith('.ipynb') and not Path(p).name.startswith('.~')):\n", + " run(f'nb_export --lib_path {lib} \"{p}\"')\n", + " with fs_watchdog(_export, nbs):\n", + " while True: time.sleep(1)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -380,7 +409,8 @@ "\u001b[1m\u001b[94mnbdev_test\u001b[22m\u001b[39m Test in parallel notebooks matching `path`, passing along `flags`\n", "\u001b[1m\u001b[94mnbdev_trust\u001b[22m\u001b[39m Trust notebooks matching `fname`\n", "\u001b[1m\u001b[94mnbdev_update\u001b[22m\u001b[39m Propagate change in modules matching `fname` to notebooks that created them\n", - "\u001b[1m\u001b[94mnbdev_update_license\u001b[22m\u001b[39m Allows you to update the license of your project.\n" + "\u001b[1m\u001b[94mnbdev_update_license\u001b[22m\u001b[39m Allows you to update the license of your project.\n", + "\u001b[1m\u001b[94mwatch_export\u001b[22m\u001b[39m None\n" ] } ], diff --git a/settings.ini b/settings.ini index 5fe59afb6..07354571c 100644 --- a/settings.ini +++ b/settings.ini @@ -51,6 +51,7 @@ console_scripts = nbdev_create_config=nbdev.config:nbdev_create_config nbdev_proc_nbs=nbdev.quarto:nbdev_proc_nbs nbdev_help=nbdev.cli:chelp nb_export=nbdev.cli:nb_export_cli + watch_export=nbdev.cli:watch_export tst_flags = notest nbs_path = nbs doc_path = _docs