Commit 08094175 authored by Andreas Zeidler's avatar Andreas Zeidler

fix iteration proxying to pass `self` acquisition-wrapped into `__iter__` and...

fix iteration proxying to pass `self` acquisition-wrapped into `__iter__` and `__getitem__` (fixes https://bugs.launchpad.net/zope2/+bug/360761)
parent b7cbe669
...@@ -4,6 +4,10 @@ Changelog ...@@ -4,6 +4,10 @@ Changelog
2.12.4 (unreleased) 2.12.4 (unreleased)
------------------- -------------------
- Fix iteration proxying to pass `self` acquisition-wrapped into both
`__iter__` as well as `__getitem__` (this fixes
https://bugs.launchpad.net/zope2/+bug/360761).
- Add tests for the __getslice__ proxying, including open-ended slicing. - Add tests for the __getslice__ proxying, including open-ended slicing.
2.12.3 (2009-08-08) 2.12.3 (2009-08-08)
......
...@@ -942,10 +942,35 @@ Wrapper_contains(Wrapper *self, PyObject *v) ...@@ -942,10 +942,35 @@ Wrapper_contains(Wrapper *self, PyObject *v)
return c; return c;
} }
/* Support for iteration cannot rely on the internal implementation of
`PyObject_GetIter`, since the `self` passed into `__iter__` and
`__getitem__` should be acquisition-wrapped (also see LP 360761): The
wrapper obviously supports the iterator protocol so simply calling
`PyObject_GetIter(OBJECT(self))` results in an infinite recursion.
Instead the base object needs to be checked and the wrapper must only
be used when actually calling `__getitem__` or setting up a sequence
iterator. */
static PyObject * static PyObject *
Wrapper_iter(Wrapper *self) Wrapper_iter(Wrapper *self)
{ {
return PyObject_GetIter(self->obj); PyObject *obj = self->obj;
PyObject *res;
if ((res=PyObject_GetAttr(OBJECT(self),py__iter__))) {
ASSIGN(res,PyObject_CallFunction(res,NULL,NULL));
if (res != NULL && !PyIter_Check(res)) {
PyErr_Format(PyExc_TypeError,
"iter() returned non-iterator "
"of type '%.100s'",
res->ob_type->tp_name);
Py_DECREF(res);
res = NULL;
}
} else if (PySequence_Check(obj)) {
ASSIGN(res,PySeqIter_New(OBJECT(self)));
} else {
res = PyErr_Format(PyExc_TypeError, "iteration over non-sequence");
}
return res;
} }
static PySequenceMethods Wrapper_as_sequence = { static PySequenceMethods Wrapper_as_sequence = {
......
...@@ -1813,7 +1813,7 @@ def test_proxying(): ...@@ -1813,7 +1813,7 @@ def test_proxying():
slicing... slicing...
True True
Finally let's check that the wrapper's __iter__ proxy falls back Next let's check that the wrapper's __iter__ proxy falls back
to using the object's __getitem__ if it has no __iter__. See to using the object's __getitem__ if it has no __iter__. See
https://bugs.launchpad.net/zope2/+bug/360761 . https://bugs.launchpad.net/zope2/+bug/360761 .
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment