git: 15c25307e519 - main - math/py-fsph: Fix build

From: Yuri Victorovich <yuri_at_FreeBSD.org>
Date: Tue, 07 Jul 2026 02:36:06 UTC
The branch main has been updated by yuri:

URL: https://cgit.FreeBSD.org/ports/commit/?id=15c25307e519baec007102de2118449b1f9ead14

commit 15c25307e519baec007102de2118449b1f9ead14
Author:     Yuri Victorovich <yuri@FreeBSD.org>
AuthorDate: 2026-07-07 02:14:49 +0000
Commit:     Yuri Victorovich <yuri@FreeBSD.org>
CommitDate: 2026-07-07 02:36:03 +0000

    math/py-fsph: Fix build
    
    Reported by:    fallout
---
 math/py-fsph/Makefile                    | 20 +++++++-----
 math/py-fsph/files/patch-fsph___fsph.pyx | 52 ++++++++++++++++++++++++++++++++
 math/py-fsph/files/patch-pyproject.toml  |  9 ++++++
 math/py-fsph/files/patch-setup.py        | 28 +++++++++++++++++
 4 files changed, 101 insertions(+), 8 deletions(-)

diff --git a/math/py-fsph/Makefile b/math/py-fsph/Makefile
index 7ad997de3775..85220285c020 100644
--- a/math/py-fsph/Makefile
+++ b/math/py-fsph/Makefile
@@ -1,25 +1,29 @@
 PORTNAME=	fsph
 DISTVERSIONPREFIX=	v
 DISTVERSION=	0.3.0
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	math
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
 
 MAINTAINER=	yuri@FreeBSD.org
 COMMENT=	Library to quickly compute series of complex spherical harmonics
-WWW=		https://fsph.readthedocs.io/en/latest/
+WWW=		https://fsph.readthedocs.io/en/latest/ \
+		https://github.com/glotzerlab/fsph
 
 LICENSE=	MIT
 LICENSE_FILE=	${WRKSRC}/LICENSE
 
-PY_DEPENDS=	${PYTHON_PKGNAMEPREFIX}numpy1>=1.16:math/py-numpy1@${PY_FLAVOR}
-#		${PYTHON_PKGNAMEPREFIX}tensorflow>0:science/py-tensorflow@${PY_FLAVOR} # tensorflow is an optional dependency that is currently broken: https://github.com/glotzerlab/fsph/issues/6
-BUILD_DEPENDS=	${PY_SETUPTOOLS} \
-		${PYTHON_PKGNAMEPREFIX}wheel>0:devel/py-wheel@${PY_FLAVOR} \
-		${PY_DEPENDS}
+PY_DEPENDS=	${PYTHON_PKGNAMEPREFIX}numpy>=1.16:math/py-numpy@${PY_FLAVOR}
+#PY_DEPENDS+=	${PYTHON_PKGNAMEPREFIX}tensorflow>0:science/py-tensorflow@${PY_FLAVOR} # tensorflow is an optional dependency and the build breaks with it
+BUILD_DEPENDS=	${PYTHON_PKGNAMEPREFIX}cython>0:lang/cython@${PY_FLAVOR} \
+		${PY_DEPENDS} \
+		${PY_SETUPTOOLS} \
+		${PYTHON_PKGNAMEPREFIX}wheel>0:devel/py-wheel@${PY_FLAVOR}
 RUN_DEPENDS=	${PY_DEPENDS}
+TEST_DEPENDS=	${PYTHON_PKGNAMEPREFIX}hypothesis>0:devel/py-hypothesis@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}scipy>0:science/py-scipy@${PY_FLAVOR}
 
-USES=		compiler:c++14-lang localbase python
+USES=		compiler:c++17-lang localbase python
 USE_PYTHON=	pep517 autoplist pytest
 
 USE_GITHUB=	yes
diff --git a/math/py-fsph/files/patch-fsph___fsph.pyx b/math/py-fsph/files/patch-fsph___fsph.pyx
new file mode 100644
index 000000000000..2578db6d9f36
--- /dev/null
+++ b/math/py-fsph/files/patch-fsph___fsph.pyx
@@ -0,0 +1,52 @@
+-- Make the Cython source compatible with Cython 3 by declaring the C++
+-- template functions directly in the .pyx file. The previous cimport from
+-- cpp.pxd fails under Cython 3 with "cimported module has no attribute".
+-- This is needed to regenerate the extension for Python 3.12.
+
+--- fsph/_fsph.pyx.orig	2023-05-04 11:30:36 UTC
++++ fsph/_fsph.pyx
+@@ -8,7 +8,9 @@ from libcpp cimport bool, complex
+ from cpython cimport PyObject, Py_INCREF
+ from libcpp cimport bool, complex
+ 
+-cimport cpp
++cdef extern from "../src/spherical_harmonics.hpp" namespace "fsph":
++    void evaluate_SPH[T](void*, unsigned int, T*, T*, unsigned int, bool) nogil
++    void evaluate_SPH_with_grads[T](void*, void*, unsigned int, T*, T*, unsigned int, bool) nogil
+ 
+ np.import_array()
+ 
+@@ -59,13 +61,13 @@ def pointwise_sph(phi, theta, lmax, negative_m=True):
+         phi_f = phi.ravel()
+         theta_f = theta.ravel()
+         result_f = result.ravel()
+-        cpp.evaluate_SPH[float](&result_f[0], lmax, &phi_f[0], &theta_f[0], phi.size, negative_m)
++        evaluate_SPH[float](&result_f[0], lmax, &phi_f[0], &theta_f[0], phi.size, negative_m)
+     else:
+         result = np.empty(resultShape, dtype=np.complex128)
+         phi_d = phi.ravel()
+         theta_d = theta.ravel()
+         result_d = result.ravel()
+-        cpp.evaluate_SPH[double](&result_d[0], lmax, &phi_d[0], &theta_d[0], phi.size, negative_m)
++        evaluate_SPH[double](&result_d[0], lmax, &phi_d[0], &theta_d[0], phi.size, negative_m)
+ 
+     return result
+ 
+@@ -129,7 +131,7 @@ def pointwise_sph_grads(phi, theta, lmax, negative_m=T
+         phi_f = phi.ravel()
+         theta_f = theta.ravel()
+         result_f = result.ravel()
+-        cpp.evaluate_SPH_with_grads[float](&result_f[0], sph_target_f, lmax, &phi_f[0], &theta_f[0], phi.size, negative_m)
++        evaluate_SPH_with_grads[float](&result_f[0], sph_target_f, lmax, &phi_f[0], &theta_f[0], phi.size, negative_m)
+     else:
+         result = np.empty(resultShape, dtype=np.complex128)
+         if return_sphs:
+@@ -139,7 +141,7 @@ def pointwise_sph_grads(phi, theta, lmax, negative_m=T
+         phi_d = phi.ravel()
+         theta_d = theta.ravel()
+         result_d = result.ravel()
+-        cpp.evaluate_SPH_with_grads[double](&result_d[0], sph_target_d, lmax, &phi_d[0], &theta_d[0], phi.size, negative_m)
++        evaluate_SPH_with_grads[double](&result_d[0], sph_target_d, lmax, &phi_d[0], &theta_d[0], phi.size, negative_m)
+ 
+     if return_sphs:
+         return result, sphs
diff --git a/math/py-fsph/files/patch-pyproject.toml b/math/py-fsph/files/patch-pyproject.toml
new file mode 100644
index 000000000000..3903d4842793
--- /dev/null
+++ b/math/py-fsph/files/patch-pyproject.toml
@@ -0,0 +1,9 @@
+-- Add Cython to the build-system requirements so that the PEP 517 build
+-- can regenerate the Cython extension source for Python 3.12 compatibility.
+
+--- pyproject.toml.orig	2026-07-06 16:12:26 UTC
++++ pyproject.toml
+@@ -1,2 +1,2 @@
+ [build-system]
+-requires = ["setuptools", "wheel", "numpy"]
++requires = ["setuptools", "wheel", "numpy", "cython"]
diff --git a/math/py-fsph/files/patch-setup.py b/math/py-fsph/files/patch-setup.py
new file mode 100644
index 000000000000..a6b74e4585d3
--- /dev/null
+++ b/math/py-fsph/files/patch-setup.py
@@ -0,0 +1,28 @@
+-- Regenerate the Cython extension source at build time rather than
+-- using the bundled generated C++ file, which was produced by Cython 0.29.32
+-- and is incompatible with Python 3.12.
+
+--- setup.py.orig	2023-05-04 11:30:36 UTC
++++ setup.py
+@@ -15,15 +15,16 @@ macros = []
+     exec(version_file.read())
+ 
+ macros = []
+-extra_args = ['-std=c++14']
++extra_args = ['-std=c++17']
+ sources = []
+ 
+-CYTHONIZE = False
+-if '--cython' in sys.argv:
++CYTHONIZE = True
++try:
+     from Cython.Build import cythonize
+-    sys.argv.remove('--cython')
+-    CYTHONIZE = True
++except ImportError:
++    CYTHONIZE = False
+ 
++if CYTHONIZE:
+     def myCythonize(macros, *args, **kwargs):
+         result = cythonize(*args, **kwargs)
+         for r in result: