[pypy-commit] pypy py3.5: add PyStopIterationObject

arigo pypy.commits at gmail.com
Thu Mar 9 11:25:38 EST 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r90610:f8357b98a4c2
Date: 2017-03-09 17:24 +0100
http://bitbucket.org/pypy/pypy/changeset/f8357b98a4c2/

Log:	add PyStopIterationObject

diff --git a/pypy/module/cpyext/include/pyerrors.h b/pypy/module/cpyext/include/pyerrors.h
--- a/pypy/module/cpyext/include/pyerrors.h
+++ b/pypy/module/cpyext/include/pyerrors.h
@@ -36,6 +36,11 @@
 PyAPI_FUNC(int) PyOS_snprintf(char *str, size_t size, const  char  *format, ...);
 PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va);
 
+typedef struct {
+    PyObject_HEAD       /* xxx PyException_HEAD in CPython */
+    PyObject *value;
+} PyStopIterationObject;
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -4,13 +4,47 @@
 from pypy.interpreter.error import OperationError, oefmt, strerror as _strerror
 from pypy.interpreter import pytraceback
 from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, CONST_STRING
+from pypy.module.cpyext.api import PyObjectFields, cpython_struct
+from pypy.module.cpyext.api import bootstrap_function, slot_function
+from pypy.module.cpyext.pyobject import make_typedescr
 from pypy.module.exceptions.interp_exceptions import W_RuntimeWarning
+from pypy.module.exceptions.interp_exceptions import W_StopIteration
 from pypy.module.cpyext.pyobject import (
     PyObject, PyObjectP, make_ref, from_ref, Py_DecRef)
 from pypy.module.cpyext.state import State
 from pypy.module.cpyext.import_ import PyImport_Import
 from rpython.rlib import rposix, jit
 
+PyStopIterationObjectStruct = lltype.ForwardReference()
+PyStopIterationObject = lltype.Ptr(PyStopIterationObjectStruct)
+PyStopIterationObjectFields = PyObjectFields + \
+    (("value", PyObject), )
+cpython_struct("PyStopIterationObject", PyStopIterationObjectFields,
+               PyStopIterationObjectStruct)
+
+ at bootstrap_function
+def init_stopiterationobject(space):
+    "Type description of PyStopIterationObject"
+    make_typedescr(W_StopIteration.typedef,
+                   basestruct=PyStopIterationObject.TO,
+                   attach=stopiteration_attach,
+                   dealloc=stopiteration_dealloc)
+
+def stopiteration_attach(space, py_obj, w_obj, w_userdata=None):
+    py_stopiteration = rffi.cast(PyStopIterationObject, py_obj)
+    assert isinstance(w_obj, W_StopIteration)
+    # note: assumes that w_value is read-only; changes on one side won't
+    # be reflected on the other side
+    py_stopiteration.c_value = make_ref(space, w_obj.w_value)
+
+ at slot_function([PyObject], lltype.Void)
+def stopiteration_dealloc(space, py_obj):
+    py_stopiteration = rffi.cast(PyStopIterationObject, py_obj)
+    Py_DecRef(space, py_stopiteration.c_value)
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
+
+
 @cpython_api([PyObject, PyObject], lltype.Void)
 def PyErr_SetObject(space, w_type, w_value):
     """This function is similar to PyErr_SetString() but lets you specify an
diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test/test_pyerrors.py
--- a/pypy/module/cpyext/test/test_pyerrors.py
+++ b/pypy/module/cpyext/test/test_pyerrors.py
@@ -443,3 +443,15 @@
             module.test()
         assert len(l) == 1
         assert "foo 42 bar" in str(l[0])
+
+    def test_StopIteration_value(self):
+        module = self.import_extension('foo', [
+                ("test", "METH_O",
+                 '''
+                 PyObject *o = ((PyStopIterationObject *)args)->value;
+                 Py_INCREF(o);
+                 return o;
+                 '''),
+                ])
+        res = module.test(StopIteration("foo!"))
+        assert res == "foo!"


More information about the pypy-commit mailing list