PyWavelets / pywt

PyWavelets - Wavelet Transforms in Python
http://pywavelets.readthedocs.org
MIT License
1.97k stars 460 forks source link

Issue running tests on local repo #699

Closed cyschneck closed 4 months ago

cyschneck commented 4 months ago

I am running a local instance of the repo on a Linux/Ubuntu environment with Python 3.10.13 and have not been able to run the testing suite

I followed the build instructions as follows:

git clone https://github.com/PyWavelets/pywt.git PyWavelets

Created a conda virtual env

conda create -c conda-forge -n pywavelets python=3.10
conda activate pywavelets 

Then, ran the install commands

(pywavelets) PyWavelets $ pip install .

But the issue arises when I attempt to run the testing suite

pytest .

But since pytest wasn't originally installed as part of pip it throws

(pywavelets) PyWavelets$ pytest .
The program 'pytest' is currently not installed.

Which can be fixed with conda install pytest

However, after install pytest, when I attempt I run pytest . it cannot find the pywt extensions ModuleNotFoundError: No module named 'pywt._extensions._pywt'

___________________________________________________ ERROR collecting test session ____________________________________________________
../../miniconda3/envs/pywavelets/lib/python3.10/site-packages/_pytest/config/__init__.py:642: in _importconftest
    mod = import_path(conftestpath, mode=importmode, root=rootpath)
        conftestpath = PosixPath('/home/user/Github/PyWavelets/pywt/conftest.py')
        exc_info   = (<class 'ModuleNotFoundError'>, ModuleNotFoundError("No module named 'pywt._extensions._pywt'"), <traceback object at 0x7f60ca57c0c0>)
        existing   = None
        importmode = 'prepend'
        pkgpath    = PosixPath('/home/user/Github/PyWavelets/pywt')
        rootpath   = PosixPath('/home/user/Github/PyWavelets')
        self       = <_pytest.config.PytestPluginManager object at 0x7f60caf99660>
../../miniconda3/envs/pywavelets/lib/python3.10/site-packages/_pytest/pathlib.py:565: in import_path
    importlib.import_module(module_name)
        mode       = <ImportMode.prepend: 'prepend'>
        module_name = 'pywt.conftest'
        names      = ['pywt', 'conftest']
        p          = PosixPath('/home/user/Github/PyWavelets/pywt/conftest.py')
        path       = PosixPath('/home/user/Github/PyWavelets/pywt/conftest.py')
        pkg_path   = PosixPath('/home/user/Github/PyWavelets/pywt')
        pkg_root   = PosixPath('/home/user/Github/PyWavelets')
        root       = PosixPath('/home/user/Github/PyWavelets')

I've run this on my local fork and the main repo and have remade and cleaned the directory a few times, but have not had any luck. How can I install the extensions along with the repo?

rgommers commented 4 months ago

Hi @cyschneck, the extensions are installed fine - what is happening is that when you run pytest ., an import of the local pywt/ tree is attempted rather than the installed package. Try this:

cd demo
pytest --pyargs pywt 

Or alternatively:

cd demo  # or any other clean dir
python -c "import pywt; pywt.test()"
cyschneck commented 4 months ago

This works for running the tests in the demo file, but I wanted to run the tests directory (PyWavelets/pywt/tests). But running pytest . and pytest --pyargs pywt outside the demo file throws the same module error

ImportError while loading conftest '/home/user/Github/pywt/pywt/conftest.py'.
../__init__.py:15: in <module>
    from ._extensions._pywt import *
E   ModuleNotFoundError: No module named 'pywt._extensions._pywt'
rgommers commented 4 months ago

This works for running the tests in the demo file, but I wanted to run the tests directory (PyWavelets/pywt/tests).

They are the same tests. You cannot run the tests from within the git repo unless you're using an editable install, exactly because pytest will then find the pywt directory in the git repo and try to import it instead of the install pywt.

So there's two ways of running the tests:

  1. install the package, and run either pytest --pyargs pywt or python -c "import pywt; pywt.test()" (away from the root of the repo)
  2. do an editable install with pip install -e . --no-build-isolation and then run pytest or pytest pywt in the root of the repo

This is the standard problem with pytest, it needs to find the right package. A source layout in the repo of src/pkgname avoids that issue, but we (and many/most python packages) don't use that.

agriyakhetarpal commented 4 months ago

This is the standard problem with pytest, it needs to find the right package. A source layout in the repo of src/pkgname avoids that issue, but we (and many/most python packages) don't use that.

Should this be a cue that we should move to an src/ layout? I looked at the directory structure for the Meson configuration, and it looks like it should be doable with changing

subdir('pywt')

in the root-level meson.build file to point to src/pywt/, and the rest of the directories should be the same (the inner meson.build directories look like they don't use any absolute paths so that should make it easier).

rgommers commented 4 months ago

It's not impossible, but I'm also not really keen to do that, since that will be a lot of code churn and result in merge conflicts for all open PRs and in-progress branches anyone may have. What we have here is a very standard layout for a repo with a Python package, so it's just one of those "you have to know this about how pytest works" things.

cyschneck commented 4 months ago

Thanks for the help! The pip install -e . (combined with a conda install pytest ) was what I needed. I wanted to run the tests test folder under the pywt subfolder.

conda create -c conda-forge -n pywavelets python=3.10
conda activate pywavelets
pip install -e .
conda install pytest
cd pywt
pytest

Trying to build with pip install -e . --no-build-isolation gave some issues with meson-python. But I was able to run the tests folder this way

rgommers commented 4 months ago

Trying to build with pip install -e . --no-build-isolation gave some issues with meson-python. But I was able to run the tests folder this way

--no-build-isolation disables auto-installing build dependencies; if you had added conda install meson-python beforehand it would work.

Seems like things are working for you now though, so looks like we're all good here - hence I'll close this issue.