git: 7e67b1988fbd - main - science/py-gemmi: unbreak by backporting new patch to support nanobind-3.x
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 23 Sep 2026 07:25:57 UTC
The branch main has been updated by yuri:
URL: https://cgit.FreeBSD.org/ports/commit/?id=7e67b1988fbd560c4a05fc19904acddedfc3ed1e
commit 7e67b1988fbd560c4a05fc19904acddedfc3ed1e
Author: Yuri Victorovich <yuri@FreeBSD.org>
AuthorDate: 2026-09-23 05:44:40 +0000
Commit: Yuri Victorovich <yuri@FreeBSD.org>
CommitDate: 2026-09-23 07:25:54 +0000
science/py-gemmi: unbreak by backporting new patch to support nanobind-3.x
Also: fix the only failing testcase
---
science/py-gemmi/Makefile | 13 +--
.../patch-97c808222f468f8188f2ed87266e0d7c5a854ce2 | 113 +++++++++++++++++++++
...e_gemmi_third__party_tao_pegtl_parse__error.hpp | 14 +++
3 files changed, 132 insertions(+), 8 deletions(-)
diff --git a/science/py-gemmi/Makefile b/science/py-gemmi/Makefile
index e6b1ccec435d..44fa5af9345f 100644
--- a/science/py-gemmi/Makefile
+++ b/science/py-gemmi/Makefile
@@ -1,6 +1,7 @@
PORTNAME= gemmi
DISTVERSIONPREFIX= v
DISTVERSION= 0.7.5
+PORTREVISION= 1
CATEGORIES= science python
PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX}
@@ -12,8 +13,6 @@ WWW= https://gemmi.readthedocs.io/en/latest/ \
LICENSE= MPL20
LICENSE_FILE= ${WRKSRC}/LICENSE.txt
-BROKEN= not compatible with nanobind-3.x, see https://github.com/project-gemmi/gemmi/issues/442
-
BUILD_DEPENDS= ${PYTHON_PKGNAMEPREFIX}pip>0:devel/py-pip@${PY_FLAVOR} \
${PYTHON_PKGNAMEPREFIX}nanobind>0:devel/py-nanobind@${PY_FLAVOR} \
${PYTHON_PKGNAMEPREFIX}wheel>0:devel/py-wheel@${PY_FLAVOR} \
@@ -22,7 +21,7 @@ LIB_DEPENDS= libgemmi_cpp.so:science/gemmi
TEST_DEPENDS= ${PYTHON_PKGNAMEPREFIX}biopython>0:biology/py-biopython@${PY_FLAVOR}
USES= cmake compiler:c++17-lang localbase:ldflags python
-USE_PYTHON= flavors
+USE_PYTHON= flavors pytest
USE_GITHUB= yes
GH_ACCOUNT= project-gemmi
@@ -32,13 +31,11 @@ CMAKE_OFF= BUILD_GEMMI_PROGRAM STANDALONE_PYTHON_MODULE
CMAKE_ARGS= -DPython_EXECUTABLE=${PYTHON_CMD}
TEST_ENV= ${MAKE_ENV} PYTHONPATH=${STAGEDIR}${PYTHONPREFIX_SITELIBDIR}
-TEST_WRKSRC= ${BUILD_WRKSRC}/tests
+TEST_WRKSRC= ${WRKSRC}/tests
+TEST_ARGS= --disable-plugin-autoload
PLIST_SUB= VER=${PORTVERSION}
-do-test:
- @cd ${WRKSRC} && ${SETENV} ${TEST_ENV} ${PYTHON_CMD} -m unittest discover -v tests/
-
-# tests as of 0.7.3: test 'test_syntax_error' fails with syntax error, see https://github.com/project-gemmi/gemmi/issues/384
+# tests as of 0.7.5: 204 passed, 4 skipped in 0.54s
.include <bsd.port.mk>
diff --git a/science/py-gemmi/files/patch-97c808222f468f8188f2ed87266e0d7c5a854ce2 b/science/py-gemmi/files/patch-97c808222f468f8188f2ed87266e0d7c5a854ce2
new file mode 100644
index 000000000000..a46b2111e814
--- /dev/null
+++ b/science/py-gemmi/files/patch-97c808222f468f8188f2ed87266e0d7c5a854ce2
@@ -0,0 +1,113 @@
+-- nanobind-3.x compatibility patch from https://github.com/project-gemmi/gemmi/commit/97c808222f468f8188f2ed87266e0d7c5a854ce2
+
+diff --git CMakeLists.txt CMakeLists.txt
+index 54e1a4fd6..fbb0a27d3 100644
+--- CMakeLists.txt
++++ CMakeLists.txt
+@@ -31,6 +31,8 @@ option(GENERATE_STUBS "Generate Python type stubs" ON)
+ option(EXTRA_WARNINGS "Set extra warning flags" OFF)
+ option(USE_WMAIN "(Windows only) take Unicode arguments in gemmi program" ON)
+ option(STANDALONE_PYTHON_MODULE "Avoid linking Python module to libgemmi_cpp DLL" ON)
++option(ENABLE_SPLIT_MODE "Use nanobind split mode (BACKEND_MODULE)" OFF)
++option(ENABLE_FREE_THREADED "Enable free-threaded Python support" OFF)
+ if (WIN32)
+ set(GEMMI_INSTALL_CMAKEDIR "cmake" CACHE STRING
+ "Install path for gemmi CMake files")
+@@ -472,10 +474,20 @@ if (USE_PYTHON)
+ COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
+ OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE nb_cmake_dir)
+ list(APPEND CMAKE_PREFIX_PATH "${nb_cmake_dir}")
+- find_package(nanobind 2.4.0 CONFIG REQUIRED)
++ find_package(nanobind CONFIG REQUIRED)
++ if (nanobind_VERSION VERSION_LESS "2.4.0" OR nanobind_VERSION VERSION_GREATER_EQUAL "4.0.0")
++ message(FATAL_ERROR "nanobind version must be >= 2.4.0 and < 4.0.0 (found ${nanobind_VERSION})")
++ endif()
+ message(STATUS "Found nanobind ${nanobind_VERSION}: ${NB_DIR}")
+ endif()
+- nanobind_add_module(gemmi_py NOMINSIZE
++ set(gemmi_py_flags NOMINSIZE)
++ if (ENABLE_SPLIT_MODE)
++ list(APPEND gemmi_py_flags BACKEND_MODULE nanobind_backend)
++ endif()
++ if (ENABLE_FREE_THREADED)
++ list(APPEND gemmi_py_flags FREE_THREADED)
++ endif()
++ nanobind_add_module(gemmi_py ${gemmi_py_flags}
+ python/gemmi.cpp python/align.cpp
+ python/ccp4.cpp python/chemcomp.cpp python/cif.cpp
+ python/elem.cpp python/grid.cpp python/hkl.cpp
+diff --git python/hkl.cpp python/hkl.cpp
+index f991f90d5..91d725e48 100644
+--- python/hkl.cpp
++++ python/hkl.cpp
+@@ -318,7 +318,7 @@ void add_hkl(nb::module_& m) {
+ self.add_if_valid({h(i, 0), h(i, 1), h(i, 2)}, 0, 0, v(i), s(i));
+ self.type = DataType::Unmerged;
+ self.switch_to_asu_indices();
+- }, nb::arg("cell"), nb::arg("sg").none(false),
++ }, nb::arg("cell"), nb::arg("sg"),
+ nb::arg("miller_array"), nb::arg("value_array"), nb::arg("sigma_array"))
+ ;
+
+diff --git python/make_iterator.h python/make_iterator.h
+index bbb5c4fcf..f800754ad 100644
+--- python/make_iterator.h
++++ python/make_iterator.h
+@@ -4,7 +4,18 @@
+ // This wrapper simplifies the call to nb::make_iterator (by assuming
+ // the name "iterator") and changes the default rv_policy to what it was
+ // in pybind11 and nanobind<2.0.
+-template<nb::rv_policy Policy = nb::rv_policy::reference_internal, typename S, typename T>
++#if defined(NB_VERSION_MAJOR) && NB_VERSION_MAJOR >= 3
++template <typename S, typename T>
++auto usual_iterator(const S&, T& value) {
++ return nb::make_iterator<nb::rv_policy::reference_internal>(nb::type<S>(), "iterator", value);
++}
++template <auto Policy, typename S, typename T>
++auto usual_iterator(const S&, T& value) {
++ return nb::make_iterator<Policy>(nb::type<S>(), "iterator", value);
++}
++#else
++template <nb::rv_policy Policy = nb::rv_policy::reference_internal, typename S, typename T>
+ auto usual_iterator(const S&, T& value) {
+ return nb::make_iterator<Policy>(nb::type<S>(), "iterator", value);
+ }
++#endif
+diff --git python/mol.cpp python/mol.cpp
+index 56eb7dfec..7108965cc 100644
+--- python/mol.cpp
++++ python/mol.cpp
+@@ -36,7 +36,11 @@ struct returns_references {
+ if (!nb::isinstance<nb::sequence>(ret))
+ throw std::runtime_error("return value should be a sequence");
+ for (nb::handle nurse : ret)
++#if defined(NB_VERSION_MAJOR) && NB_VERSION_MAJOR >= 3
++ nb::keep_alive_obj(nurse, args[0]);
++#else
+ nb::detail::keep_alive(nurse.ptr(), args[0]);
++#endif
+ }
+ };
+
+diff --git python/scaling.cpp python/scaling.cpp
+index 5bc3690c7..050351b35 100644
+--- python/scaling.cpp
++++ python/scaling.cpp
+@@ -22,7 +22,7 @@ void add_scaling(nb::module_& m) {
+ .def_prop_rw("parameters", &Scaling::get_parameters,
+ (void (Scaling::*)(const std::vector<double>&)) &Scaling::set_parameters)
+ .def("prepare_points", &Scaling::prepare_points,
+- nb::arg("calc"), nb::arg("obs"), nb::arg("mask")=static_cast<FPhiData*>(nullptr))
++ nb::arg("calc"), nb::arg("obs"), nb::arg("mask")=nb::none())
+ .def("fit_isotropic_b_approximately", &Scaling::fit_isotropic_b_approximately)
+ .def("fit_b_star_approximately", &Scaling::fit_b_star_approximately)
+ .def("fit_parameters", &Scaling::fit_parameters)
+@@ -36,7 +36,7 @@ void add_scaling(nb::module_& m) {
+ })
+ .def("get_solvent_scale", &Scaling::get_solvent_scale, nb::arg("stol2"))
+ .def("scale_data", &Scaling::scale_data,
+- nb::arg("asu_data"), nb::arg("mask_data")=static_cast<FPhiData*>(nullptr))
++ nb::arg("asu_data"), nb::arg("mask_data")=nb::none())
+ .def("scale_value", &Scaling::scale_value,
+ nb::arg("hkl"), nb::arg("f_value"), nb::arg("mask_value"))
+ ;
diff --git a/science/py-gemmi/files/patch-include_gemmi_third__party_tao_pegtl_parse__error.hpp b/science/py-gemmi/files/patch-include_gemmi_third__party_tao_pegtl_parse__error.hpp
new file mode 100644
index 000000000000..e405380a2513
--- /dev/null
+++ b/science/py-gemmi/files/patch-include_gemmi_third__party_tao_pegtl_parse__error.hpp
@@ -0,0 +1,14 @@
+-- fix for the bug in the Gemmi project: https://github.com/project-gemmi/gemmi/issues/384#issuecomment-5789847575
+-- this bug causes one testcase to fail due to duplicate C++ typeinfo objects
+
+--- include/gemmi/third_party/tao/pegtl/parse_error.hpp.orig 2026-03-02 03:06:09 UTC
++++ include/gemmi/third_party/tao/pegtl/parse_error.hpp
+@@ -14,7 +14,7 @@ namespace tao
+ {
+ namespace TAO_PEGTL_NAMESPACE
+ {
+- struct parse_error
++ struct __attribute__((visibility("default"))) parse_error
+ : public std::runtime_error
+ {
+ parse_error( const std::string& msg, std::vector< position >&& in_positions )