Author: Armin Rigo <[email protected]>
Branch: cpyext-ext
Changeset: r82646:3af62800d459
Date: 2016-03-01 21:15 +0100
http://bitbucket.org/pypy/pypy/changeset/3af62800d459/
Log: Test and fix for tp_iter and tp_iternext (also fixes the latter to
not raise StopIteration but simply return NULL in case of
exhaustion)
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -336,14 +336,6 @@
space.get_and_call_args(w_descr, w_self, args)
return 0
-@cpython_api([PyObject], PyObject, header=None)
-def slot_tp_iter(space, w_self):
- return space.iter(w_self)
-
-@cpython_api([PyObject], PyObject, header=None)
-def slot_tp_iternext(space, w_self):
- return space.next(w_self)
-
from rpython.rlib.nonconst import NonConstant
SLOTS = {}
@@ -437,6 +429,33 @@
return space.call_function(str_fn, w_self)
api_func = slot_tp_str.api_func
+ elif name == 'tp_iter':
+ iter_fn = w_type.getdictvalue(space, '__iter__')
+ if iter_fn is None:
+ return
+
+ @cpython_api([PyObject], PyObject, header=header)
+ @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
+ def slot_tp_iter(space, w_self):
+ return space.call_function(iter_fn, w_self)
+ api_func = slot_tp_iter.api_func
+
+ elif name == 'tp_iternext':
+ iternext_fn = w_type.getdictvalue(space, 'next')
+ if iternext_fn is None:
+ return
+
+ @cpython_api([PyObject], PyObject, header=header)
+ @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
+ def slot_tp_iternext(space, w_self):
+ try:
+ return space.call_function(iternext_fn, w_self)
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ return None
+ api_func = slot_tp_iternext.api_func
+
else:
return
diff --git a/pypy/module/cpyext/test/test_typeobject.py
b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -645,32 +645,49 @@
def test_tp_iter(self):
module = self.import_extension('foo', [
- ("tp_iter", "METH_O",
+ ("tp_iter", "METH_VARARGS",
'''
- if (!args->ob_type->tp_iter)
+ PyTypeObject *type = (PyTypeObject *)PyTuple_GET_ITEM(args,
0);
+ PyObject *obj = PyTuple_GET_ITEM(args, 1);
+ if (!type->tp_iter)
{
PyErr_SetNone(PyExc_ValueError);
return NULL;
}
- return args->ob_type->tp_iter(args);
+ return type->tp_iter(obj);
'''
),
- ("tp_iternext", "METH_O",
+ ("tp_iternext", "METH_VARARGS",
'''
- if (!args->ob_type->tp_iternext)
+ PyTypeObject *type = (PyTypeObject *)PyTuple_GET_ITEM(args,
0);
+ PyObject *obj = PyTuple_GET_ITEM(args, 1);
+ PyObject *result;
+ if (!type->tp_iternext)
{
PyErr_SetNone(PyExc_ValueError);
return NULL;
}
- return args->ob_type->tp_iternext(args);
+ result = type->tp_iternext(obj);
+ if (!result && !PyErr_Occurred())
+ result = PyString_FromString("stop!");
+ return result;
'''
)
])
l = [1]
- it = module.tp_iter(l)
+ it = module.tp_iter(list, l)
assert type(it) is type(iter([]))
- assert module.tp_iternext(it) == 1
- raises(StopIteration, module.tp_iternext, it)
+ assert module.tp_iternext(type(it), it) == 1
+ assert module.tp_iternext(type(it), it) == "stop!"
+ #
+ class LL(list):
+ def __iter__(self):
+ return iter(())
+ ll = LL([1])
+ it = module.tp_iter(list, ll)
+ assert type(it) is type(iter([]))
+ x = list(it)
+ assert x == [1]
def test_bool(self):
module = self.import_extension('foo', [
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit