diff --git a/nbdev/test.py b/nbdev/test.py index 1fdb0932b..9758707c2 100644 --- a/nbdev/test.py +++ b/nbdev/test.py @@ -20,6 +20,7 @@ from .doclinks import * from .process import NBProcessor, nb_lang from .frontmatter import nb_frontmatter +from .processors import _default_exp from fastcore.nbio import * from execnb.shell import * @@ -54,6 +55,8 @@ def _no_eval(cell): start = time.time() k = CaptureShell(fn) + exp = _default_exp(nb) + if exp and is_nbdev(): k.user_ns['__file__'] = str(get_config().lib_path/(exp.replace('.','/') + '.py')) if do_print: print(f'Starting {fn}') try: with working_directory(fn.parent): @@ -69,7 +72,6 @@ def _no_eval(cell): if prev_test is None: os.environ.pop('IN_TEST', None) else: os.environ['IN_TEST'] = prev_test - # %% ../nbs/api/12_test.ipynb #d8bf1f1b-935d-4b69-ba96-827c5d7213f0 def _keep_file(p:Path, # filename for which to check for `indicator_fname` ignore_fname:str # filename that will result in siblings being ignored diff --git a/nbs/api/12_test.ipynb b/nbs/api/12_test.ipynb index 387c52c13..35cf57de0 100644 --- a/nbs/api/12_test.ipynb +++ b/nbs/api/12_test.ipynb @@ -40,6 +40,7 @@ "from nbdev.doclinks import *\n", "from nbdev.process import NBProcessor, nb_lang\n", "from nbdev.frontmatter import nb_frontmatter\n", + "from nbdev.processors import _default_exp\n", "\n", "from fastcore.nbio import *\n", "from execnb.shell import *" @@ -82,6 +83,8 @@ "\n", " start = time.time()\n", " k = CaptureShell(fn)\n", + " exp = _default_exp(nb)\n", + " if exp and is_nbdev(): k.user_ns['__file__'] = str(get_config().lib_path/(exp.replace('.','/') + '.py'))\n", " if do_print: print(f'Starting {fn}')\n", " try:\n", " with working_directory(fn.parent):\n", @@ -95,7 +98,7 @@ " return res,time.time()-start\n", " finally:\n", " if prev_test is None: os.environ.pop('IN_TEST', None)\n", - " else: os.environ['IN_TEST'] = prev_test\n" + " else: os.environ['IN_TEST'] = prev_test" ] }, { @@ -138,6 +141,26 @@ "assert not success" ] }, + { + "cell_type": "markdown", + "id": "239fbed8", + "metadata": {}, + "source": [ + "If a notebook declares a `default_exp`, `__file__` is set to the path of the module it exports to, so path-dependent code (e.g. `Path(__file__).parent`) behaves the same under test as in the exported module. An explicit `__file__ =` in a cell overrides this:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f07e8a6e", + "metadata": {}, + "outputs": [], + "source": [ + "_nb = Path('../../tests/file_var.ipynb')\n", + "success,duration = test_nb(_nb)\n", + "assert success" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/pyproject.toml b/pyproject.toml index ccfbf8456..22a79bc40 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ classifiers = [ "License :: OSI Approved :: Apache Software License", ] dynamic = ["version"] -dependencies = [ "fastcore>=1.12.35", "execnb>=0.1.12", "astunparse", "ghapi>=1.0.3", "watchdog", "asttokens", +dependencies = [ "fastcore>=1.13.10", "execnb>=0.1.12", "astunparse", "ghapi>=1.0.3", "watchdog", "asttokens", "setuptools", "build", "fastgit", "pyyaml", "tomli; python_version < '3.11'", ] [project.optional-dependencies] diff --git a/tests/file_var.ipynb b/tests/file_var.ipynb new file mode 100644 index 000000000..190d1c7ae --- /dev/null +++ b/tests/file_var.ipynb @@ -0,0 +1,50 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test `__file__` is set for exported notebooks" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| default_exp file_var" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "p = Path(__file__)\n", + "assert p.name == 'file_var.py' and p.parent.name == 'nbdev'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "__file__ = 'overridden'\n", + "assert __file__ == 'overridden'" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}