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