From 5526fba1ba9ae82dacac742b162191f9a45bec7e Mon Sep 17 00:00:00 2001 From: Gabriel Studer <gabriel.studer@unibas.ch> Date: Fri, 28 Mar 2025 15:42:58 +0100 Subject: [PATCH] Make custom iterators work in Python 3.13 Custom iterators must have __next__() and __iter__() defined. Sequence related iterators in OST only had __next__() defined and this worked up to Python 3.12. Starting in Python 3.13, list/dict comprehensions failed. More info: https://github.com/python/cpython/issues/128161 --- modules/seq/base/pymod/export_sequence.cc | 30 +++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/modules/seq/base/pymod/export_sequence.cc b/modules/seq/base/pymod/export_sequence.cc index 2b23ef15a..5522b5c8c 100644 --- a/modules/seq/base/pymod/export_sequence.cc +++ b/modules/seq/base/pymod/export_sequence.cc @@ -146,9 +146,12 @@ struct RevRegionRangeIter { } --e_; AlignedColumn col=*e_; - return col; } + + RevRegionRangeIter& iter() { + return *this; + } private: AlignedColumnIterator b_; AlignedColumnIterator e_; @@ -165,10 +168,15 @@ struct RegionRangeIter { if (b_==e_) { boost::python::objects::stop_iteration_error(); } + AlignedColumn col=*b_; ++b_; return col; } + + RegionRangeIter& iter() { + return *this; + } private: AlignedColumnIterator b_; AlignedColumnIterator e_; @@ -188,6 +196,11 @@ struct ConstSeqListIter { ++b_; return s; } + + ConstSeqListIter& iter() + { + return *this; + } private: ConstSequenceList l_; ConstSequenceList::iterator b_; @@ -208,6 +221,11 @@ struct SeqListIter { ++b_; return s; } + + SeqListIter& iter() + { + return *this; + } private: SequenceList l_; SequenceList::iterator b_; @@ -329,18 +347,26 @@ void export_sequence() class_<RegionRangeIter>("RegionRangeIter", no_init) .def("next", &RegionRangeIter::next) .def("__next__", &RegionRangeIter::next) + .def("iter", &RegionRangeIter::iter, return_value_policy<copy_non_const_reference>()) + .def("__iter__", &RegionRangeIter::iter, return_value_policy<copy_non_const_reference>()) ; - class_<RevRegionRangeIter>("RevRegionRangeIter", no_init) + class_<RevRegionRangeIter>("RevRegionRangeIter", no_init) .def("next", &RevRegionRangeIter::next) .def("__next__", &RevRegionRangeIter::next) + .def("iter", &RevRegionRangeIter::iter, return_value_policy<copy_non_const_reference>()) + .def("__iter__", &RevRegionRangeIter::iter, return_value_policy<copy_non_const_reference>()) ; class_<ConstSeqListIter>("ConstSeqListIter", no_init) .def("next", &ConstSeqListIter::next) .def("__next__", &ConstSeqListIter::next) + .def("iter", &ConstSeqListIter::iter, return_value_policy<copy_non_const_reference>()) + .def("__iter__", &ConstSeqListIter::iter, return_value_policy<copy_non_const_reference>()) ; class_<SeqListIter>("SeqListIter", no_init) .def("next", &SeqListIter::next) .def("__next__", &SeqListIter::next) + .def("iter", &SeqListIter::iter, return_value_policy<copy_non_const_reference>()) + .def("__iter__", &SeqListIter::iter, return_value_policy<copy_non_const_reference>()) ; class_<AlignmentHandle>("AlignmentHandle", init<>()) .def("GetCount", &AlignmentHandle::GetCount) -- GitLab