Selaa lähdekoodia

add pybind11 implementation for stop_iteration with value

Kevin Eady 1 vuosi sitten
vanhempi
commit
30f04b4753

+ 11 - 1
include/pybind11/internal/error.h

@@ -53,7 +53,17 @@ inline auto raise_call(Args&&... args) {
     throw python_error(what, std::move(e));
 }
 
-class stop_iteration {};
+class stop_iteration {
+public:
+    stop_iteration() = default;
+
+    stop_iteration(object value) : m_value(std::move(value)) {}
+
+    object value() const { return m_value; }
+
+private:
+    object m_value;
+};
 
 class cast_error : public std::runtime_error {
     using std::runtime_error::runtime_error;

+ 8 - 1
include/pybind11/internal/function.h

@@ -562,7 +562,14 @@ private:
             py_exception(tp_IndexError, e.what());
         } catch(std::range_error& e) {
             py_exception(tp_ValueError, e.what());
-        } catch(stop_iteration&) { StopIteration(); } catch(index_error& e) {
+        } catch(stop_iteration& e) {
+            if(auto value_ptr = e.value().ptr()) {
+                bool ok = py_tpcall(tp_StopIteration, 1, value_ptr);
+                if(ok) { py_raise(py_retval()); }
+            } else {
+                StopIteration();
+            }
+        } catch(index_error& e) {
             py_exception(tp_IndexError, e.what());
         } catch(key_error& e) { py_exception(tp_KeyError, e.what()); } catch(value_error& e) {
             py_exception(tp_ValueError, e.what());

+ 6 - 0
include/pybind11/tests/error.cpp

@@ -41,6 +41,12 @@ TEST_F(PYBIND11_TEST, exception_cpp_to_python) {
     });
     py::exec("try:\n    test_stop_iteration()\nexcept StopIteration as e:\n    pass");
 
+    m.def("test_stop_iteration_value", []() {
+        throw py::stop_iteration(py::int_(42));
+    });
+    py::exec(
+        "try:\n    test_stop_iteration_value()\nexcept StopIteration as e:\n    assert e.value == 42");
+
     m.def("test_error_already_set", []() {
         KeyError(none().ptr());
         throw py::error_already_set();