insarlab / PySolid

A Python wrapper for solid Earth tides
GNU General Public License v3.0
63 stars 9 forks source link

replace `numpy.distutils` with `CMake` and `scikit-build-core` build backend #87

Closed rtburns-jpl closed 3 months ago

rtburns-jpl commented 3 months ago

As setuptools cannot natively call f2py, we call it ourselves by using a custom build extension.

Closes https://github.com/insarlab/PySolid/issues/78

(This seemed like the simplest way to do things - keep using setuptools, and have it manually call f2py under the hood.)

yunjunz commented 3 months ago

Thank you @rtburns-jpl for the PR! The circle CI testing passed, but my local testing did not, reporting that the solid.for is not compiled, which is true, as shown below. Any idea why?

conda create --name test_pysolid --yes
conda activate test_pysolid

(test_pysolid) yunjunz:~/tools>$ mamba install -c conda-forge fortran-compiler --file PySolid/requirements.txt --file PySolid/tests/requirements.txt

(test_pysolid) yunjunz:~/tools>$ python -m pip install -e PySolid
Obtaining file:///Users/yunjunz/tools/PySolid
  Installing build dependencies ... done
  Checking if build backend supports build_editable ... done
  Getting requirements to build editable ... done
  Preparing editable metadata (pyproject.toml) ... done
Requirement already satisfied: numpy in ./mambaforge/envs/test_pysolid/lib/python3.12/site-packages (from pysolid==0.3.2.post7) (2.0.0)
Requirement already satisfied: scipy in ./mambaforge/envs/test_pysolid/lib/python3.12/site-packages (from pysolid==0.3.2.post7) (1.13.1)
Building wheels for collected packages: pysolid
  Building editable for pysolid (pyproject.toml) ... done
  Created wheel for pysolid: filename=pysolid-0.3.2.post7-0.editable-cp312-cp312-macosx_10_13_x86_64.whl size=17136 sha256=6527d51b6adcdcdea448a3c076fc28b75ffb09e329ab55fb992631adeaeb05b7
  Stored in directory: /private/var/folders/16/9yhnnw8d10b2dq1dr09bx9r00000gn/T/pip-ephem-wheel-cache-launa6oe/wheels/59/5f/40/845da050940776ea855c4a700d9a4b894d994a1494b07043cb
Successfully built pysolid
Installing collected packages: pysolid
Successfully installed pysolid-0.3.2.post7
(test_pysolid) yunjunz:~/tools>$ python PySolid/tests/grid.py
--------------------------------------------------
/Users/yunjunz/tools/PySolid/tests/grid.py
Traceback (most recent call last):
  File "/Users/yunjunz/tools/mambaforge/envs/test_pysolid/lib/python3.12/site-packages/pysolid/grid.py", line 45, in calc_solid_earth_tides_grid
    from pysolid.solid import solid_grid
ModuleNotFoundError: No module named 'pysolid.solid'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/yunjunz/tools/PySolid/tests/grid.py", line 33, in <module>
    tide_u) = pysolid.calc_solid_earth_tides_grid(dt_obj, atr, verbose=True)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/yunjunz/tools/mambaforge/envs/test_pysolid/lib/python3.12/site-packages/pysolid/grid.py", line 50, in calc_solid_earth_tides_grid
    raise ImportError(msg)
ImportError: Cannot import name 'solid' from 'pysolid'!
    Maybe solid.for is NOT compiled yet.
    Check instruction at: https://github.com/insarlab/PySolid.

(test_pysolid) yunjunz:~/tools>$ python PySolid/tests/point.py 
--------------------------------------------------
/Users/yunjunz/tools/PySolid/tests/point.py
PYSOLID: calculate solid Earth tides in east/north/up direction
PYSOLID: lot/lon: 34.0/-118.0 degree
PYSOLID: start UTC: 2020-11-01T04:00:00
PYSOLID: end   UTC: 2020-12-31T02:00:00
PYSOLID: time step: 60 seconds
Traceback (most recent call last):
  File "/Users/yunjunz/tools/mambaforge/envs/test_pysolid/lib/python3.12/site-packages/pysolid/point.py", line 163, in calc_solid_earth_tides_point_per_day
    from pysolid.solid import solid_point
ModuleNotFoundError: No module named 'pysolid.solid'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/yunjunz/tools/PySolid/tests/point.py", line 28, in <module>
    tide_u) = pysolid.calc_solid_earth_tides_point(lat, lon, dt_obj0, dt_obj1, verbose=False)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/yunjunz/tools/mambaforge/envs/test_pysolid/lib/python3.12/site-packages/pysolid/point.py", line 115, in calc_solid_earth_tides_point
    tide_ui) = calc_solid_earth_tides_point_per_day(lat, lon,
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/yunjunz/tools/mambaforge/envs/test_pysolid/lib/python3.12/site-packages/pysolid/point.py", line 168, in calc_solid_earth_tides_point_per_day
    raise ImportError(msg)
ImportError: Cannot import name 'solid' from 'pysolid'!
    Maybe solid.for is NOT compiled yet.
    Check instruction at: https://github.com/insarlab/PySolid.
rtburns-jpl commented 3 months ago

Ok that took a while to sort out but I think I've got it figured out now.

At first I couldn't reproduce your issue because I was installing to a local prefix and all the files appeared to be there. python3 setup.py install --prefix dist seemed to create the solid.so extension module. But installing to a venv with pip as you did didn't seem to work. I think I had set up the output location correctly but setuptools was not "aware" of the resulting module being part of the package, so adding a layer of indirection such as a venv meant the extension module would be lost along the way.

I ultimately decided to switch over to scikit-build since the hacks I'd need to keep setuptools working would probably not be worth the hassle. I had trouble with regular scikit-build, but apparently now there is a "new-new" method, scikit-build-core, which had its fortran example code last modified just last week. So based on that example, I've got something that seems to work with both setup.py and pip venvs.

Let me know if the latest push works for you, and if anything needs clarification.

rtburns-jpl commented 3 months ago

Yeah, the manual installation still works for me. I think you're just missing meson, but you can install it from conda-forge (mamba install -c conda-forge meson).

jhkennedy commented 3 months ago

It looks like @yunjunz beat me to the feedback/review, but I just wanted to say this looks great! Thanks @rtburns-jpl