Skip to content

Commit

Permalink
python: fix Model.subchains() and Chain.subchains()
Browse files Browse the repository at this point in the history
uses recently added nb::call_policy to keep model/chain alive
as long as the returned values are alive.

requires nanobind 2.4.0

finally fixes #317
  • Loading branch information
wojdyr committed Dec 13, 2024
1 parent 76aab64 commit 6610157
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 4 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[build-system]
requires = [
"scikit-build-core ~=0.10.7",
"nanobind >=2.2",
"nanobind >=2.4",
"typing-extensions >=4.0; python_version < '3.11'"
]
build-backend = "scikit_build_core.build"
Expand Down
17 changes: 15 additions & 2 deletions python/mol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ NB_MAKE_OPAQUE(info_map_type)

namespace {

// cf. returns_references_to in nanobind docs
struct returns_references {
static void precall(PyObject **, size_t, nb::detail::cleanup_list *) {}

static void postcall(PyObject **args, size_t, nb::handle ret) {
if (!nb::isinstance<nb::sequence>(ret))
throw std::runtime_error("return value should be a sequence");
for (nb::handle nurse : ret)
nb::detail::keep_alive(nurse.ptr(), args[0]);
}
};

template<typename T, typename C>
C& add_item(T& container, C child, int pos) {
if ((size_t) pos > container.size()) // true also for negative pos
Expand Down Expand Up @@ -223,7 +235,7 @@ void add_mol(nb::module_& m) {
(ResidueSpan (Model::*)(const std::string&)) &Model::get_subchain,
nb::arg("name"), nb::rv_policy::reference_internal)
.def("subchains", (std::vector<ResidueSpan> (Model::*)()) &Model::subchains,
nb::rv_policy::reference_internal)
nb::call_policy<returns_references>())
.def("find_residue_group", &Model::find_residue_group,
nb::arg("chain"), nb::arg("seqid"),
nb::keep_alive<0, 1>())
Expand Down Expand Up @@ -316,7 +328,8 @@ void add_mol(nb::module_& m) {
.def("add_residue", add_child<Chain, Residue>,
nb::arg("residue"), nb::arg("pos")=-1,
nb::rv_policy::reference_internal)
.def("subchains", (std::vector<ResidueSpan> (Chain::*)()) &Chain::subchains)
.def("subchains", (std::vector<ResidueSpan> (Chain::*)()) &Chain::subchains,
nb::call_policy<returns_references>())
.def("whole", (ResidueSpan (Chain::*)()) &Chain::whole,
nb::keep_alive<0, 1>())
.def("get_polymer", (ResidueSpan (Chain::*)()) &Chain::get_polymer,
Expand Down
2 changes: 1 addition & 1 deletion tools/upstream-check.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from urllib.request import urlopen

TAGGED_REPOS = {
'wjakob/nanobind': 'v2.2.0',
'wjakob/nanobind': 'v2.4.0',
'scikit-build/scikit-build-core': 'v0.10.7',
'taocpp/PEGTL': '2.8.3',
'cxong/tinydir': '1.2.6',
Expand Down

0 comments on commit 6610157

Please sign in to comment.