{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#|default_exp sync" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# sync\n", "\n", "> Propagating small changes in the library back to notebooks" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The library is primarily developed in notebooks so any big changes should be made there. But sometimes, it's easier to fix small bugs or typos in the modules directly. `nbdev_update_lib` is the function that will propagate those changes back to the corresponding notebooks. Note that you can't create new cells or reorder cells with that functionality, so your corrections should remain limited." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#|export\n", "from nbdev.imports import *\n", "from nbdev.config import *\n", "from nbdev.maker import *\n", "from nbdev.process import *\n", "from nbdev.export import *\n", "\n", "from execnb.nbio import *\n", "from fastcore.script import *\n", "from fastcore.xtras import *\n", "\n", "import ast,tempfile" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#|hide\n", "from pdb import set_trace\n", "from fastcore.test import *" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#|export\n", "def absolute_import(name, fname, level):\n", " \"Unwarps a relative import in `name` according to `fname`\"\n", " if not level: return name\n", " mods = fname.split(os.path.sep)\n", " if not name: return '.'.join(mods)\n", " return '.'.join(mods[:len(mods)-level+1]) + f\".{name}\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "test_eq(absolute_import('xyz', 'nbdev', 0), 'xyz')\n", "test_eq(absolute_import('', 'nbdev', 1), 'nbdev')\n", "test_eq(absolute_import('core', 'nbdev', 1), 'nbdev.core')\n", "test_eq(absolute_import('core', 'nbdev/vision', 2), 'nbdev.core')\n", "test_eq(absolute_import('transform', 'nbdev/vision', 1), 'nbdev.vision.transform')\n", "test_eq(absolute_import('notebook.core', 'nbdev/data', 2), 'nbdev.notebook.core')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#|export\n", "_re_import = re.compile(\"from\\s+\\S+\\s+import\\s+\\S\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#|hide\n", "assert _re_import.match('from foo import bar')\n", "assert not _re_import.match('#from foo import bar')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#|export\n", "def _to_absolute(code, lib_name):\n", " if not _re_import.search(code): return code\n", " res = update_import(code, ast.parse(code).body, lib_name, absolute_import)\n", " return ''.join(res) if res else code\n", "\n", "def _update_lib(nbname, nb_locs, lib_name=None):\n", " if lib_name is None: lib_name = get_config().lib_name\n", " nbp = NBProcessor(nbname, ExportModuleProc(), rm_directives=False)\n", " nb = nbp.nb\n", " nbp.process()\n", "\n", " for name,idx,code in nb_locs:\n", " assert name==nbname\n", " cell = nb.cells[int(idx)]\n", " lines = cell.source.splitlines(True)\n", " directives = ''.join(cell.source.splitlines(True)[:len(cell.directives_)])\n", " cell.source = directives + _to_absolute(code, lib_name)\n", " write_nb(nb, nbname)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#|export\n", "def _get_call(s):\n", " top,*rest = s.splitlines()\n", " return (*top.split(),'\\n'.join(rest))\n", "\n", "@call_parse\n", "def nbdev_update(fname:str): # A Python file name to update\n", " \"Propagate change in modules matching `fname` to notebooks that created them\"\n", " if os.environ.get('IN_TEST',0): return\n", " code_cells = Path(fname).read_text().split(\"\\n# %% \")[1:]\n", " locs = L(_get_call(s) for s in code_cells if not s.startswith('auto '))\n", " for nbname,nb_locs in groupby(locs, 0).items(): _update_lib(nbname, nb_locs)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#|hide\n", "# nbdev_update(\"../nbdev/sync.py\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Export -" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#|hide\n", "#|eval: false\n", "from nbdev.doclinks import nbdev_export\n", "nbdev_export()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 4 }