Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ModuleNotFoundError while using @testbook('....ipynb', execute=True) #152

Open
sanfeu opened this issue Jan 6, 2023 · 2 comments
Open

Comments

@sanfeu
Copy link

sanfeu commented Jan 6, 2023

Hello

In my notebook, I import a variable in a py file.
While the notebook is running while executed manually, it failed to be executed while using @testbook

image

#mini_config.py
schema_name = 'ds_handson_sanfeu'

image

#test_mini_loader.py
from testbook import testbook
@testbook('./src/mini_loader.ipynb', execute=True)
def test_check_country_spit(tb):
    assert True

The test fails with this error log:

./tests/test_mini_loader.py::test_check_module Failed: [undefined]nbclient.exceptions.CellExecutionError: An error occurred while executing the following cell:
------------------
from mini_config import schema_name
------------------

#x1B[1;31m---------------------------------------------------------------------------#x1B[0m
#x1B[1;31mModuleNotFoundError#x1B[0m                       Traceback (most recent call last)
Cell #x1B[1;32mIn[1], line 1#x1B[0m
#x1B[1;32m----> 1#x1B[0m #x1B[38;5;28;01mfrom#x1B[39;00m #x1B[38;5;21;01mmini_config#x1B[39;00m #x1B[38;5;28;01mimport#x1B[39;00m schema_name

#x1B[1;31mModuleNotFoundError#x1B[0m: No module named 'mini_config'
ModuleNotFoundError: No module named 'mini_config'
args = (), kwargs = {}

    @functools.wraps(func)
    def wrapper(*args, **kwargs):  # pragma: no cover
        with self.client.setup_kernel():
>           self._prepare()

.venv\lib\site-packages\testbook\testbook.py:62: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv\lib\site-packages\testbook\testbook.py:46: in _prepare
    self.client.execute()
.venv\lib\site-packages\testbook\client.py:147: in execute
    super().execute_cell(cell, index)
.venv\lib\site-packages\jupyter_core\utils\__init__.py:166: in wrapped
    return loop.run_until_complete(inner)
C:\Python39_64\lib\asyncio\base_events.py:642: in run_until_complete
    return future.result()
.venv\lib\site-packages\nbclient\client.py:1021: in async_execute_cell
    await self._check_raise_for_error(cell, cell_index, exec_reply)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <testbook.client.TestbookNotebookClient object at 0x000001D10D95A3A0>
cell = {'cell_type': 'code', 'execution_count': 1, 'id': '149206e7-45bc-46df-9799-a3cd321ccc7d', 'metadata': {'tags': [], 'ex...1b[1;31mModuleNotFoundError\x1b[0m: No module named 'mini_config'"]}], 'source': 'from mini_config import schema_name'}
cell_index = 0
exec_reply = {'buffers': [], 'content': {'ename': 'ModuleNotFoundError', 'engine_info': {'engine_id': -1, 'engine_uuid': '3eb7cbaf-...e, 'engine': '3eb7cbaf-c9fa-4c23-ab69-14121e5bb42c', 'started': '2023-01-06T17:40:58.354058Z', 'status': 'error'}, ...}

    async def _check_raise_for_error(
        self, cell: NotebookNode, cell_index: int, exec_reply: t.Optional[t.Dict]
    ) -> None:
    
        if exec_reply is None:
            return None
    
        exec_reply_content = exec_reply['content']
        if exec_reply_content['status'] != 'error':
            return None
    
        cell_allows_errors = (not self.force_raise_errors) and (
            self.allow_errors
            or exec_reply_content.get('ename') in self.allow_error_names
            or "raises-exception" in cell.metadata.get("tags", [])
        )
        await run_hook(
            self.on_cell_error, cell=cell, cell_index=cell_index, execute_reply=exec_reply
        )
        if not cell_allows_errors:
>           raise CellExecutionError.from_cell_and_msg(cell, exec_reply_content)
E           nbclient.exceptions.CellExecutionError: An error occurred while executing the following cell:
E           ------------------
E           from mini_config import schema_name
E           ------------------
E           
E           #x1B[1;31m---------------------------------------------------------------------------#x1B[0m
E           #x1B[1;31mModuleNotFoundError#x1B[0m                       Traceback (most recent call last)
E           Cell #x1B[1;32mIn[1], line 1#x1B[0m
E           #x1B[1;32m----> 1#x1B[0m #x1B[38;5;28;01mfrom#x1B[39;00m #x1B[38;5;21;01mmini_config#x1B[39;00m #x1B[38;5;28;01mimport#x1B[39;00m schema_name
E           
E           #x1B[1;31mModuleNotFoundError#x1B[0m: No module named 'mini_config'
E           ModuleNotFoundError: No module named 'mini_config'

.venv\lib\site-packages\nbclient\client.py:915: CellExecutionError

I am working with python 3.9.6, in a venv built directly in the repertory.
My environment is

anyio==3.6.2
argon2-cffi==21.3.0
argon2-cffi-bindings==21.2.0
arrow==1.2.3
asttokens==2.2.1
attrs==22.2.0
Babel==2.11.0
backcall==0.2.0
beautifulsoup4==4.11.1
bleach==5.0.1
certifi==2022.12.7
cffi==1.15.1
charset-normalizer==2.1.1
colorama==0.4.6
comm==0.1.2
debugpy==1.6.5
decorator==5.1.1
defusedxml==0.7.1
entrypoints==0.4
exceptiongroup==1.1.0
executing==1.2.0
fastjsonschema==2.16.2
fqdn==1.5.1
idna==3.4
importlib-metadata==6.0.0
iniconfig==1.1.1
ipykernel==6.19.4
ipython==8.8.0
ipython-genutils==0.2.0
ipywidgets==8.0.4
isoduration==20.11.0
jedi==0.18.2
Jinja2==3.1.2
json5==0.9.11
jsonpointer==2.3
jsonschema==4.17.3
jupyter==1.0.0
jupyter-console==6.4.4
jupyter-events==0.5.0
jupyter_client==7.4.8
jupyter_core==5.1.2
jupyter_server==2.0.6
jupyter_server_terminals==0.4.3
jupyterlab==3.5.2
jupyterlab-pygments==0.2.2
jupyterlab-widgets==3.0.5
jupyterlab_server==2.18.0
MarkupSafe==2.1.1
matplotlib-inline==0.1.6
mistune==2.0.4
nbclassic==0.4.8
nbclient==0.7.2
nbconvert==7.2.7
nbformat==5.7.1
nest-asyncio==1.5.6
notebook==6.5.2
notebook_shim==0.2.2
packaging==22.0
pandocfilters==1.5.0
parso==0.8.3
pickleshare==0.7.5
platformdirs==2.6.2
pluggy==1.0.0
prometheus-client==0.15.0
prompt-toolkit==3.0.36
psutil==5.9.4
pure-eval==0.2.2
pycparser==2.21
Pygments==2.14.0
pyrsistent==0.19.3
pytest==7.2.0
python-dateutil==2.8.2
python-json-logger==2.0.4
pytz==2022.7
pywin32==305
pywinpty==2.0.10
PyYAML==6.0
pyzmq==24.0.1
qtconsole==5.4.0
QtPy==2.3.0
requests==2.28.1
rfc3339-validator==0.1.4
rfc3986-validator==0.1.1
Send2Trash==1.8.0
six==1.16.0
sniffio==1.3.0
soupsieve==2.3.2.post1
stack-data==0.6.2
terminado==0.17.1
testbook==0.4.2
tinycss2==1.2.1
tomli==2.0.1
tornado==6.2
traitlets==5.8.0
uri-template==1.2.0
urllib3==1.26.13
wcwidth==0.2.5
webcolors==1.12
webencodings==0.5.1
websocket-client==1.4.2
widgetsnbextension==4.0.5
zipp==3.11.0

I tried init / play with sys.path but without success.
Sorry if I missed something obvious. Can you help?

PS: Thanks a lot for this module, which will probably change the life of my coworkers soon.

@sanfeu
Copy link
Author

sanfeu commented Jan 9, 2023

I found the way around.

While executing from notebook, sys.path contains root/src .
While running from testbook, sys.path contains root/.

I tried to change sys.path in my test.py file, but it has no effect on the notebook execution (I suppose independent kernel is launched).

So what worked for me is to inject a cell at the beginning of the notebook execution thta set my syspath as needed:

tb.inject("""
                import sys
                sys.path.append('./src')
                """
                , before=0, run=False)

@WeakLemonDrink
Copy link

WeakLemonDrink commented Jul 17, 2024

I came across this error too but you can set the correct path by configuring the nbclient.NotebookClient which is a parent of TestbookNotebookClient. See also the nbclient docs.

You can update your decorator call to the following:

@testbook('./src/mini_loader.ipynb', execute=True, resources={"metadata": {"path": "src/"}})

This will set the execution path correctly without the need for the injected code. It may be useful to add this to the docs as its not intuitive that testbook should set a different path when compared to executing the notebook directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants