ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> zope-checkins
zope-checkins
[Zope-Checkins] SVN: Zope/branches/2.10/ backport fix for LP #360761 (r105349:105351) to Zope 2.10
by Andreas Zeidler other posts by this author
Oct 29 2009 2:40AM messages near this date
[Zope-Checkins] SVN: Zope/branches/2.11/ backport fix for LP #360761 (r105349:105351) to Zope 2.11 | [Zope-Checkins] SVN: Zope/branches/2.12/ ZODB 3.9.3
Log message for revision 105352:
  backport fix for LP #360761 (r105349:105351) to Zope 2.10
  

Changed:
  U   Zope/branches/2.10/doc/CHANGES.txt
  U   Zope/branches/2.10/lib/python/Acquisition/_Acquisition.c
  U   Zope/branches/2.10/lib/python/Acquisition/tests.py

-=-
Modified: Zope/branches/2.10/doc/CHANGES.txt
===================================================================
--- Zope/branches/2.10/doc/CHANGES.txt	2009-10-29 09:18:53 UTC (rev 105351)
+++ Zope/branches/2.10/doc/CHANGES.txt	2009-10-29 09:40:08 UTC (rev 105352)
@@ -8,6 +8,9 @@
 
     Bugs fixed
 
+      - LP #360761 (backported from Acquisition trunk): fix iteration proxy
+        to pass `self` acquisition-wrapped into `__iter__` and `__getitem__`.
+
       - LP #414757 (backported from Zope trunk): don't emit a IEndRequestEvent
         when clearing a cloned request.
 

Modified: Zope/branches/2.10/lib/python/Acquisition/_Acquisition.c
===================================================================
--- Zope/branches/2.10/lib/python/Acquisition/_Acquisition.c	2009-10-29 09:18:53 UTC (rev 10
5351)
+++ Zope/branches/2.10/lib/python/Acquisition/_Acquisition.c	2009-10-29 09:40:08 UTC (rev 10
5352)
@@ -819,10 +819,35 @@
   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 * 
 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 = {

Modified: Zope/branches/2.10/lib/python/Acquisition/tests.py
===================================================================
--- Zope/branches/2.10/lib/python/Acquisition/tests.py	2009-10-29 09:18:53 UTC (rev 105351)
+++ Zope/branches/2.10/lib/python/Acquisition/tests.py	2009-10-29 09:40:08 UTC (rev 105352)
@@ -1719,8 +1719,9 @@
     iterating...
     [42]
 
-    Finally let's check that https://bugs.launchpad.net/zope2/+bug/360761
-    has been fixed:
+    Next let's check that the wrapper's __iter__ proxy falls back
+    to using the object's __getitem__ if it has no __iter__.  See
+    https://bugs.launchpad.net/zope2/+bug/360761 .
 
     > >> class C(Acquisition.Implicit):
     ...     l=[1,2,3]
@@ -1739,6 +1740,59 @@
     > >> list(c2)
     [1, 2, 3]
 
+    The __iter__proxy should also pass the wrapped object as self to
+    the __iter__ of objects defining __iter__::
+
+    > >> class C(Acquisition.Implicit):
+    ...     def __iter__(self):
+    ...         print 'iterating...'
+    ...         for i in range(5):
+    ...             yield i, self.aq_parent.name
+    > >> c = C()
+    > >> i = Impl()
+    > >> i.c = c
+    > >> i.name = 'i'
+    > >> list(i.c)
+    iterating...
+    [(0, 'i'), (1, 'i'), (2, 'i'), (3, 'i'), (4, 'i')]
+
+    And it should pass the wrapped object as self to
+    the __getitem__ of objects without an __iter__::
+
+    > >> class C(Acquisition.Implicit):
+    ...     def __getitem__(self, i):
+    ...         return self.aq_parent.l[i]
+    > >> c = C()
+    > >> i = Impl()
+    > >> i.c = c
+    > >> i.l = range(5)
+    > >> list(i.c)
+    [0, 1, 2, 3, 4]
+
+    Finally let's make sure errors are still correctly raised after having
+    to use a modified version of `PyObject_GetIter` for iterator support::
+
+    > >> class C(Acquisition.Implicit):
+    ...     pass
+    > >> c = C()
+    > >> i = Impl()
+    > >> i.c = c
+    > >> list(i.c)
+    Traceback (most recent call last):
+      ...
+    TypeError: iteration over non-sequence
+
+    > >> class C(Acquisition.Implicit):
+    ...     def __iter__(self):
+    ...         return [42]
+    > >> c = C()
+    > >> i = Impl()
+    > >> i.c = c
+    > >> list(i.c)
+    Traceback (most recent call last):
+      ...
+    TypeError: iter() returned non-iterator of type 'list'
+
     """
 
 

_______________________________________________
Zope-Checkins maillist  -  Zope-Checkins@[...].org
https://mail.zope.org/mailman/listinfo/zope-checkins

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved