Repository: PyWavelets/pywt (language: python)

Issue:
Bug: cannot run tests with an editable installation of `pyWavelets`, possible `pytesttester` test collection discrepancy?
## Description

Hi, I'm trying to run the test suite using `pytest` against an editable installation of pyWavelets/`pywt`, and it looks like the `PytestTester` class in the `pywt/_pytesttester.py` module is not configured to run against on editable installations (with the `-e .` command-line flag) in the same way it seems to run in CI for non-editable installations (`pip install .`)

## MWE, i.e., steps to reproduce

In a terminal, run

```
pip install numpy==1.23.3 cython meson-python  # Python 3.11, build-time requirements sourced from the build-system table in pyproject.toml
pip install -e .
pip install pytest
```

and then,

1. `pytest --pyargs pywt` does not work and returns the following trace:

<details><summary>Expand to view logs</summary>
<p>

```bash
====================================================================== test session starts ======================================================================
platform darwin -- Python 3.11.7, pytest-8.0.1, pluggy-1.4.0
rootdir: /Users/agriyakhetarpal/Desktop/Work/pywt
configfile: pytest.ini
collected 0 items / 1 error                                                                                                                                     

============================================================================ ERRORS =============================================================================
_______________________________________________________________ ERROR collecting pywt/__init__.py _______________________________________________________________
venv/lib/python3.11/site-packages/pluggy/_hooks.py:501: in __call__
    return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
        firstresult = True
        kwargs     = {'collector': <Module __init__.py>, 'name': 'test', 'obj': <pywt._pytesttester.PytestTester object at 0x1068ad7d0>}
        self       = <HookCaller 'pytest_pycollect_makeitem'>
venv/lib/python3.11/site-packages/pluggy/_manager.py:119: in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
        firstresult = True
        hook_name  = 'pytest_pycollect_makeitem'
        kwargs     = {'collector': <Module __init__.py>, 'name': 'test', 'obj': <pywt._pytesttester.PytestTester object at 0x1068ad7d0>}
        methods    = [<HookImpl plugin_name='python', plugin=<module '_pytest.python' from '/Users/agriyakhetarpal/Desktop/Work/pywt/venv/l...test.unittest' from '/Users/agriyakhetarpal/Desktop/Work/pywt/venv/lib/python3.11/site-packages/_pytest/unittest.py'>>]
        self       = <_pytest.config.PytestPluginManager object at 0x105633550>
venv/lib/python3.11/site-packages/_pytest/python.py:260: in pytest_pycollect_makeitem
    warnings.warn_explicit(
E   pytest.PytestCollectionWarning: cannot collect 'test' because it is not a function.
        collector  = <Module __init__.py>
        filename   = PosixPath('/Users/agriyakhetarpal/Desktop/Work/pywt/pywt/_pytesttester.py')
        lineno     = 72
        name       = 'test'
        obj        = <pywt._pytesttester.PytestTester object at 0x1068ad7d0>
==================================================================== short test summary info ====================================================================
ERROR pywt/__init__.py - pytest.PytestCollectionWarning: cannot collect 'test' because it is not a function.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
```

With `pywt.test()`, there is another error on editable installations:

```python
    113 import pytest
    115 module = sys.modules[self.module_name]
--> 116 module_path = os.path.abspath(module.__path__[0])
    118 # setup the pytest arguments
    119 pytest_args = ["-l"]

IndexError: list index out of range
```


</p>
</details> 

## Workarounds

However, for now,

1. `pytest .`,
2. `pytest pywt`

seem to work as usual and proceed with the collection of 1036 tests in total. These commands have been tested in a fresh, `virtualenv`-based virtual environment with Python 3.11.7 on a macOS M-series machine.

## Additional notes

The bug seems to be coming from the `--pyargs` configuration in `pywt/_pytesttester.py` here:

https://github.com/PyWavelets/pywt/blob/e69b126c096868b0ea7650d38ed11cd95a9dc182/pywt/_pytesttester.py#L150-L156

which I'm not totally sure about, but it seems to be searching for `test` inside `pywt/__init__.py` as an importable Python module – while it is an instance of the `PytestTester` class.


Discussion / hints:

Fix patch:
diff --git a/pyproject.toml b/pyproject.toml
index 046ae7fc..f799ae1d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,7 +7,7 @@
 [build-system]
 build-backend = "mesonpy"
 requires = [
-    "meson-python>=0.15.0",
+    "meson-python>=0.16.0",
     "Cython>=3.0.4",
 
     # numpy requirement for wheel builds for distribution on PyPI - building


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 9fa4c29a..f84d0417 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -1,4 +1,4 @@
-name: Linux and macOS tests
+name: Tests
 
 on:
   push:
@@ -9,18 +9,26 @@ on:
       - main
       - v1.**
 
+concurrency:
+  # avoid duplicate runs on both pushes and PRs
+  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+  cancel-in-progress: true
+
+env:
+  # Coloured output for GitHub Actions
+  FORCE_COLOR: 3
+  # Some common environment variables for both GNU/Linux and macOS jobs
+  MPLBACKEND: Agg
+  CYTHON_TRACE: 1
+  CYTHONSPEC: cython
+  NUMPY_MIN: numpy==1.23.0
+  CYTHON_MIN: cython==3.0.4
+  SCIPY_MIN: scipy==1.9.0
+
 jobs:
   test_pywavelets_linux:
     name: linux-cp${{ matrix.python-version }}-${{ matrix.OPTIONS_NAME }}
     runs-on: ubuntu-latest
-    env:
-      MPLBACKEND: Agg
-      CYTHON_TRACE: 1
-      CYTHONSPEC: cython
-      NUMPY_MIN: numpy==1.23.0
-      CYTHON_MIN: cython==3.0.4
-      SCIPY_MIN: scipy==1.9.0
-
     strategy:
       # Ensure that a wheel builder finishes even if another fails
       fail-fast: false
@@ -49,7 +57,9 @@ jobs:
             python-version: "3.12"
             PIP_FLAGS: "--pre"
             OPTIONS_NAME: "pre-releases"
-
+          - platform_id: manylinux_x86_64
+            python-version: "3.12"
+            OPTIONS_NAME: "editable-install"
     steps:
       - name: Checkout PyWavelets
         uses: actions/checkout@v4
@@ -68,6 +78,7 @@ jobs:
           USE_SDIST: ${{ matrix.USE_SDIST }}
           USE_SCIPY: ${{ matrix.USE_SCIPY }}
           REFGUIDE_CHECK: ${{ matrix.REFGUIDE_CHECK }}
+          OPTIONS_NAME: ${{ matrix.OPTIONS_NAME }}
         run: |
           uname -a
           df -h
@@ -100,10 +111,16 @@ jobs:
                 pip install . -v
             fi
 
+          if [ "${OPTIONS_NAME}" == "editable-install" ]; then
+              pip install meson-python>=0.16.0 matplotlib pytest ninja
+              pip install -e . --no-build-isolation
+          fi
+
       - name: Run tests
         env:
           USE_SDIST: ${{ matrix.USE_SDIST }}
           REFGUIDE_CHECK: ${{ matrix.REFGUIDE_CHECK }}
+          OPTIONS_NAME: ${{ matrix.OPTIONS_NAME }}
         run: |
           set -o pipefail
           # Move out of source directory to avoid finding local pywt
@@ -125,14 +142,6 @@ jobs:
   test_pywavelets_macos:
     name: macos-cp${{ matrix.python-version }}-${{ matrix.OPTIONS_NAME }}
     runs-on: macos-latest
-    env:
-      MPLBACKEND: Agg
-      CYTHON_TRACE: 1
-      CYTHONSPEC: cython
-      NUMPY_MIN: numpy==1.23.0
-      CYTHON_MIN: cython==3.0.4
-      SCIPY_MIN: scipy==1.9.0
-
     strategy:
       # Ensure that a wheel builder finishes even if another fails
       fail-fast: false