-- 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 +#if defined(NB_VERSION_MAJOR) && NB_VERSION_MAJOR >= 3 +template +auto usual_iterator(const S&, T& value) { + return nb::make_iterator(nb::type(), "iterator", value); +} +template +auto usual_iterator(const S&, T& value) { + return nb::make_iterator(nb::type(), "iterator", value); +} +#else +template auto usual_iterator(const S&, T& value) { return nb::make_iterator(nb::type(), "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(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&)) &Scaling::set_parameters) .def("prepare_points", &Scaling::prepare_points, - nb::arg("calc"), nb::arg("obs"), nb::arg("mask")=static_cast(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(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")) ;