From 8d4fe2bb1a7c678cdc2ae09bf16fc17f16a27ae4 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Tue, 24 Sep 2024 10:00:15 +0200 Subject: [PATCH 1/5] feature requires python 3.8 --- .github/next_release.md | 3 ++- src/python/doc/installation.rst | 42 ++++++++++++++++----------------- src/python/setup.py.in | 2 +- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/.github/next_release.md b/.github/next_release.md index abd2ebd1bd..573d8ef940 100644 --- a/.github/next_release.md +++ b/.github/next_release.md @@ -20,6 +20,7 @@ Below is a list of changes: - Installation - CMake ≥ 3.15 is now required (was ≥ 3.8). + - Python ≥ 3.8 is now required (was ≥ 3.5), because of `importlib.metadata`. - Miscellaneous - The [list of bugs that were solved](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.11.0+is%3Aclosed) is available on GitHub. @@ -29,7 +30,7 @@ However, there are still GPL dependencies for many modules. We invite you to che We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages. -We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) for the modules of the User and Reference Manual, as well as for publications directly related to the GUDHI library. +We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) for the modules of the User and Reference Manual, as well as for publications directly related to the GUDHI library. Feel free to [contact us](https://gudhi.inria.fr/contact/) in case you have any questions or remarks. diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index 639a89d652..c1f7bd2c44 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -41,7 +41,7 @@ there. The library uses c++17 and requires `Boost `_ :math:`\geq` 1.71.0, `CMake `_ :math:`\geq` 3.15, -Python :math:`\geq` 3.5, `NumPy `_ :math:`\geq` 1.15.0, `Cython `_ +Python :math:`\geq` 3.8, `NumPy `_ :math:`\geq` 1.15.0, `Cython `_ :math:`\geq` 0.27 and `pybind11 `_ to compile the GUDHI Python module. It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2017 or later. @@ -145,10 +145,10 @@ You shall have something like: .. code-block:: none - Pybind11 version 2.8.1 + Pybind11 version 2.8.1 Python version 3.7.12 - Cython version 0.29.25 - Numpy version 1.21.4 + Cython version 0.29.25 + Numpy version 1.21.4 Boost version 1.77.0 + Installed modules are: off_utils;simplex_tree;rips_complex;cubical_complex;periodic_cubical_complex; persistence_graphical_tools;reader_utils;witness_complex;strong_witness_complex; @@ -156,7 +156,7 @@ You shall have something like: euclidean_strong_witness_complex; Here, you can see that the modules that need CGAL are missing, because CGAL is not installed. -:code:`persistence_graphical_tools` is installed, but +:code:`persistence_graphical_tools` is installed, but `its functions `_ will produce an error as matplotlib is not available. Unitary tests cannot be run as pytest is missing. @@ -165,23 +165,23 @@ A complete configuration would be : .. code-block:: none - Pybind11 version 2.8.1 + Pybind11 version 2.8.1 Python version 3.9.7 - Cython version 0.29.24 - Pytest version 6.2.5 - Matplotlib version 3.5.0 - Numpy version 1.21.4 - Scipy version 1.7.3 - Scikit-learn version 1.0.1 - POT version 0.8.0 + Cython version 0.29.24 + Pytest version 6.2.5 + Matplotlib version 3.5.0 + Numpy version 1.21.4 + Scipy version 1.7.3 + Scikit-learn version 1.0.1 + POT version 0.8.0 HNSWlib found PyKeOps version [pyKeOps]: 2.1 - EagerPy version 0.30.0 - TensorFlow version 2.7.0 - Sphinx version 4.3.0 - Sphinx-paramlinks version 0.5.2 - pydata_sphinx_theme version 0.13.1 - NetworkX version 3.0 + EagerPy version 0.30.0 + TensorFlow version 2.7.0 + Sphinx version 4.3.0 + Sphinx-paramlinks version 0.5.2 + pydata_sphinx_theme version 0.13.1 + NetworkX version 3.0 Eigen3 version 3.4.0 Boost version 1.74.0 CGAL version 5.3 @@ -194,7 +194,7 @@ A complete configuration would be : + Installed modules are: bottleneck;off_utils;simplex_tree;rips_complex;cubical_complex;periodic_cubical_complex; persistence_graphical_tools;reader_utils;witness_complex;strong_witness_complex;nerve_gic;subsampling; tangential_complex;alpha_complex;euclidean_witness_complex;euclidean_strong_witness_complex; - + Missing modules are: + + Missing modules are: Documentation @@ -422,7 +422,7 @@ TensorFlow requires `TensorFlow `_. The :doc:`cubical complex `, :doc:`simplex tree ` and :doc:`Rips complex ` modules require `TensorFlow`_ -for incorporating them in neural nets. +for incorporating them in neural nets. `TensorFlow`_ is also used in some automatic differentiation tests. diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 3bc8d0805e..715ecdef77 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -73,7 +73,7 @@ setup( long_description_content_type='text/x-rst', long_description='@GUDHI_LONG_DESCRIPTION@', ext_modules = ext_modules, - python_requires='>=3.5.0', + python_requires='>=3.8.0', install_requires = ['numpy >= 1.15.0',], package_data={"": ["*.dll"], }, ) From 7b6d033c934ef927bac92e2753d7e904dbdbfa5f Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Tue, 24 Sep 2024 11:53:59 +0200 Subject: [PATCH 2/5] Use importlib.metadata to guess version numbers of dependencies --- .../modules/GUDHI_third_party_libraries.cmake | 30 +++------------ src/python/CMakeLists.txt | 34 ++++++++--------- src/python/doc/installation.rst | 38 ++++++++++--------- 3 files changed, 43 insertions(+), 59 deletions(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 7c03103cba..18149ebcc2 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -145,8 +145,9 @@ if (WITH_GUDHI_PYTHON) # returns ${PYTHON_MODULE_NAME_UP}_VERSION and ${PYTHON_MODULE_NAME_UP}_FOUND function( find_python_module PYTHON_MODULE_NAME ) string(TOUPPER ${PYTHON_MODULE_NAME} PYTHON_MODULE_NAME_UP) + # Modify tracebacklimit as the exception is quite verbose when module is not found execute_process( - COMMAND ${Python_EXECUTABLE} -c "import ${PYTHON_MODULE_NAME}; print(${PYTHON_MODULE_NAME}.__version__)" + COMMAND ${Python_EXECUTABLE} -c "import sys; sys.tracebacklimit = 0; from importlib.metadata import version; print(version('${PYTHON_MODULE_NAME}'))" RESULT_VARIABLE PYTHON_MODULE_RESULT OUTPUT_VARIABLE PYTHON_MODULE_VERSION ERROR_VARIABLE PYTHON_MODULE_ERROR) @@ -167,25 +168,6 @@ if (WITH_GUDHI_PYTHON) endif() endfunction( find_python_module ) - # For modules that do not define module.__version__ - function( find_python_module_no_version PYTHON_MODULE_NAME ) - string(TOUPPER ${PYTHON_MODULE_NAME} PYTHON_MODULE_NAME_UP) - execute_process( - COMMAND ${Python_EXECUTABLE} -c "import ${PYTHON_MODULE_NAME}" - RESULT_VARIABLE PYTHON_MODULE_RESULT - ERROR_VARIABLE PYTHON_MODULE_ERROR) - if(PYTHON_MODULE_RESULT EQUAL 0) - # Remove carriage return - message ("++ Python module ${PYTHON_MODULE_NAME} found") - set(${PYTHON_MODULE_NAME_UP}_FOUND TRUE PARENT_SCOPE) - else() - message ("PYTHON_MODULE_NAME = ${PYTHON_MODULE_NAME} - - PYTHON_MODULE_RESULT = ${PYTHON_MODULE_RESULT} - - PYTHON_MODULE_ERROR = ${PYTHON_MODULE_ERROR}") - set(${PYTHON_MODULE_NAME_UP}_FOUND FALSE PARENT_SCOPE) - endif() - endfunction( find_python_module_no_version ) - if( TARGET Python::Interpreter ) find_python_module("cython") find_python_module("pytest") @@ -193,17 +175,17 @@ if (WITH_GUDHI_PYTHON) find_python_module("numpy") find_python_module("scipy") find_python_module("sphinx") - find_python_module("sklearn") - find_python_module("ot") + find_python_module("scikit-learn") + find_python_module("POT") find_python_module("pybind11") find_python_module("torch") find_python_module("pykeops") find_python_module("eagerpy") - find_python_module_no_version("hnswlib") + find_python_module("hnswlib") find_python_module("tensorflow") find_python_module("sphinx_paramlinks") find_python_module("pydata_sphinx_theme") - find_python_module_no_version("sphinxcontrib.bibtex") + find_python_module("sphinxcontrib.bibtex") find_python_module("networkx") endif() diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 5b2fad86aa..e68e8f2c64 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -131,19 +131,19 @@ if(SCIPY_FOUND) else() disable_python_documentation("scipy") endif() -if(SKLEARN_FOUND) - add_gudhi_debug_info("Scikit-learn version ${SKLEARN_VERSION}") +if(SCIKIT-LEARN_FOUND) + add_gudhi_debug_info("Scikit-learn version ${SCIKIT-LEARN_VERSION}") else() - disable_python_documentation("sklearn") + disable_python_documentation("scikit-learn") endif() -if(OT_FOUND) - add_gudhi_debug_info("POT version ${OT_VERSION}") +if(POT_FOUND) + add_gudhi_debug_info("POT version ${POT_VERSION}") else() disable_python_documentation("ot") endif() if(HNSWLIB_FOUND) # Does not have a version number... - add_gudhi_debug_info("HNSWlib found") + add_gudhi_debug_info("HNSWlib version ${HNSWLIB_VERSION}") endif() if(TORCH_FOUND) add_gudhi_debug_info("PyTorch version ${TORCH_VERSION}") @@ -176,7 +176,7 @@ else() endif() if(SPHINXCONTRIB.BIBTEX_FOUND) # Does not have a version number... - add_gudhi_debug_info("sphinxcontrib-bibtex found") + add_gudhi_debug_info("sphinxcontrib-bibtex version ${SPHINXCONTRIB.BIBTEX_VERSION}") else() disable_python_documentation("sphinxcontrib-bibtex") endif() @@ -461,7 +461,7 @@ add_test(NAME random_cubical_complex_persistence_example_py_test add_gudhi_py_test(test_cubical_complex) # Datasets are fetched for these tests -if(SKLEARN_FOUND AND WITH_GUDHI_REMOTE_TEST) +if(SCIKIT-LEARN_FOUND AND WITH_GUDHI_REMOTE_TEST) add_gudhi_py_test(test_sklearn_cubical_persistence) add_test(NAME cubical_complex_sklearn_itf_py_test @@ -590,7 +590,7 @@ add_test(NAME rips_complex_from_points_example_py_test add_gudhi_py_test(test_rips_complex) -if(SKLEARN_FOUND) +if(SCIKIT-LEARN_FOUND) # test_sklearn_rips_persistence is using gudhi.datasets.generators if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) add_gudhi_py_test(test_sklearn_rips_persistence) @@ -636,7 +636,7 @@ add_gudhi_py_test(test_reader_utils) add_gudhi_py_test(test_off) # Wasserstein -if(OT_FOUND) +if(POT_FOUND) # EagerPy dependency because of enable_autodiff=True if(EAGERPY_FOUND) add_gudhi_py_test(test_wasserstein_distance) @@ -648,7 +648,7 @@ if(OT_FOUND) endif() # Representations -if(SKLEARN_FOUND AND MATPLOTLIB_FOUND AND OT_FOUND AND TARGET CGAL::CGAL) +if(SCIKIT-LEARN_FOUND AND MATPLOTLIB_FOUND AND POT_FOUND AND TARGET CGAL::CGAL) add_gudhi_py_test(test_representations) endif() @@ -658,17 +658,17 @@ if(TENSORFLOW_FOUND) endif() # Perslay -if(TENSORFLOW_FOUND AND SKLEARN_FOUND) +if(TENSORFLOW_FOUND AND SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_perslay) endif() # Betti curves -if(SKLEARN_FOUND AND SCIPY_FOUND) +if(SCIKIT-LEARN_FOUND AND SCIPY_FOUND) add_gudhi_py_test(test_betti_curve_representations) endif() # Representations preprocessing -if(SKLEARN_FOUND) +if(SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_representations_preprocessing) endif() @@ -676,13 +676,13 @@ endif() add_gudhi_py_test(test_time_delay) # DTM -if(SCIPY_FOUND AND SKLEARN_FOUND AND TORCH_FOUND AND HNSWLIB_FOUND AND PYKEOPS_FOUND AND EAGERPY_FOUND) +if(SCIPY_FOUND AND SCIKIT-LEARN_FOUND AND TORCH_FOUND AND HNSWLIB_FOUND AND PYKEOPS_FOUND AND EAGERPY_FOUND) add_gudhi_py_test(test_knn) add_gudhi_py_test(test_dtm) endif() # Tomato -if(SCIPY_FOUND AND SKLEARN_FOUND) +if(SCIPY_FOUND AND SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_tomato) endif() @@ -697,7 +697,7 @@ if(SCIPY_FOUND) endif() # Cover complex -if(SKLEARN_FOUND) +if(SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_cover_complex) endif() diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index c1f7bd2c44..067b733efb 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -165,26 +165,28 @@ A complete configuration would be : .. code-block:: none - Pybind11 version 2.8.1 - Python version 3.9.7 - Cython version 0.29.24 - Pytest version 6.2.5 - Matplotlib version 3.5.0 - Numpy version 1.21.4 - Scipy version 1.7.3 - Scikit-learn version 1.0.1 - POT version 0.8.0 - HNSWlib found - PyKeOps version [pyKeOps]: 2.1 + Python version 3.11.9 + Pybind11 version 2.12.0 + Cython version 3.0.10 + Numpy version 1.24.3 + Pytest version 8.2.1 + Matplotlib version 3.9.0 + Scipy version 1.13.1 + Scikit-learn version 1.3.2 + POT version 0.9.4 + HNSWlib version 0.8.0 + PyTorch version 2.3.0 + PyKeOps version 2.2.3 EagerPy version 0.30.0 - TensorFlow version 2.7.0 - Sphinx version 4.3.0 - Sphinx-paramlinks version 0.5.2 - pydata_sphinx_theme version 0.13.1 - NetworkX version 3.0 + TensorFlow version 2.13.1 + Sphinx version 7.3.7 + Sphinx-paramlinks version 0.6.0 + pydata_sphinx_theme version 0.15.2 + sphinxcontrib-bibtex version 2.6.2 + NetworkX version 3.3 Eigen3 version 3.4.0 - Boost version 1.74.0 - CGAL version 5.3 + Boost version 1.84.0 + CGAL header only version 5.6.1 GMP_LIBRARIES = /usr/lib/x86_64-linux-gnu/libgmp.so GMPXX_LIBRARIES = /usr/lib/x86_64-linux-gnu/libgmpxx.so MPFR_LIBRARIES = /usr/lib/x86_64-linux-gnu/libmpfr.so From 848d853159083041511b070b85389ebb8cb217a6 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Wed, 25 Sep 2024 10:03:02 +0200 Subject: [PATCH 3/5] Specific case for PyKeops on Windows --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 18149ebcc2..ffed360461 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -179,7 +179,6 @@ if (WITH_GUDHI_PYTHON) find_python_module("POT") find_python_module("pybind11") find_python_module("torch") - find_python_module("pykeops") find_python_module("eagerpy") find_python_module("hnswlib") find_python_module("tensorflow") @@ -189,6 +188,17 @@ if (WITH_GUDHI_PYTHON) find_python_module("networkx") endif() + # Specific case for PyKeops that can be imported on Windows, but fails because it uses fcntl (not available on Windows) + # Also fcntl has no metadata, so find_python_module does not work + # "import fcntl" is about 1 sec. faster than "import pykeops" + execute_process( + COMMAND ${Python_EXECUTABLE} -c "import fcntl" + RESULT_VARIABLE FCNTL_IMPORT_MODULE_RESULT + OUTPUT_VARIABLE FCNTL_IMPORT_MODULE_OUPUT) + if(FCNTL_IMPORT_MODULE_RESULT EQUAL 0) + find_python_module("pykeops") + endif() + if(NOT GUDHI_PYTHON_PATH) message(FATAL_ERROR "ERROR: GUDHI_PYTHON_PATH is not valid.") endif(NOT GUDHI_PYTHON_PATH) From b4694d930d810c26c5aa5234dc059ce2f771595f Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Thu, 26 Sep 2024 15:59:43 +0200 Subject: [PATCH 4/5] code review: just test if windows for pykeops --- .../modules/GUDHI_third_party_libraries.cmake | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index ffed360461..a72d106bb2 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -186,18 +186,12 @@ if (WITH_GUDHI_PYTHON) find_python_module("pydata_sphinx_theme") find_python_module("sphinxcontrib.bibtex") find_python_module("networkx") + # Specific case for PyKeops that can be imported on Windows, but fails because it uses fcntl (not available on Windows) + if (NOT WIN32) + find_python_module("pykeops") + endif() endif() - # Specific case for PyKeops that can be imported on Windows, but fails because it uses fcntl (not available on Windows) - # Also fcntl has no metadata, so find_python_module does not work - # "import fcntl" is about 1 sec. faster than "import pykeops" - execute_process( - COMMAND ${Python_EXECUTABLE} -c "import fcntl" - RESULT_VARIABLE FCNTL_IMPORT_MODULE_RESULT - OUTPUT_VARIABLE FCNTL_IMPORT_MODULE_OUPUT) - if(FCNTL_IMPORT_MODULE_RESULT EQUAL 0) - find_python_module("pykeops") - endif() if(NOT GUDHI_PYTHON_PATH) message(FATAL_ERROR "ERROR: GUDHI_PYTHON_PATH is not valid.") From 9fbea63b0db06a40a80d5be379bbfda24677985a Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Thu, 26 Sep 2024 16:51:05 +0200 Subject: [PATCH 5/5] [skip ci] code review: Rework comment. Remove comments that were no more relevant. --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 2 +- src/python/CMakeLists.txt | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index a72d106bb2..6527d0be3c 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -186,7 +186,7 @@ if (WITH_GUDHI_PYTHON) find_python_module("pydata_sphinx_theme") find_python_module("sphinxcontrib.bibtex") find_python_module("networkx") - # Specific case for PyKeops that can be imported on Windows, but fails because it uses fcntl (not available on Windows) + # Specific case for PyKeops on Windows where import fails because it uses fcntl (not available on Windows) if (NOT WIN32) find_python_module("pykeops") endif() diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index e68e8f2c64..3198461820 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -142,7 +142,6 @@ else() disable_python_documentation("ot") endif() if(HNSWLIB_FOUND) - # Does not have a version number... add_gudhi_debug_info("HNSWlib version ${HNSWLIB_VERSION}") endif() if(TORCH_FOUND) @@ -175,7 +174,6 @@ else() disable_python_documentation("pydata_sphinx_theme") endif() if(SPHINXCONTRIB.BIBTEX_FOUND) - # Does not have a version number... add_gudhi_debug_info("sphinxcontrib-bibtex version ${SPHINXCONTRIB.BIBTEX_VERSION}") else() disable_python_documentation("sphinxcontrib-bibtex")