Author: Mark Young <[email protected]>
Branch: 33_fix_itertools
Changeset: r84038:b8b4f1dbd1bc
Date: 2016-04-24 19:28 -0400
http://bitbucket.org/pypy/pypy/changeset/b8b4f1dbd1bc/

Log:    Sort of fix the remaining itertools tests. Translation is currently
        broken and I had to use a lot of isinstance assertions to make the
        annotator happy. Committing to ask about it.

diff --git a/pypy/module/itertools/__init__.py 
b/pypy/module/itertools/__init__.py
--- a/pypy/module/itertools/__init__.py
+++ b/pypy/module/itertools/__init__.py
@@ -49,6 +49,8 @@
         'starmap'       : 'interp_itertools.W_StarMap',
         'takewhile'     : 'interp_itertools.W_TakeWhile',
         'tee'           : 'interp_itertools.tee',
+        '_tee'          : 'interp_itertools.W_TeeIterable',
+        '_tee_chained_list' : 'interp_itertools.W_TeeChainedListNode',
         'zip_longest'  : 'interp_itertools.W_ZipLongest',
     }
 
diff --git a/pypy/module/itertools/interp_itertools.py 
b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -815,53 +815,119 @@
         raise OperationError(space.w_ValueError, space.wrap("n must be >= 0"))
 
     if isinstance(w_iterable, W_TeeIterable):     # optimization only
-        chained_list = w_iterable.chained_list
+        w_chained_list = w_iterable.w_chained_list
         w_iterator = w_iterable.w_iterator
         iterators_w = [w_iterable] * n
         for i in range(1, n):
             iterators_w[i] = space.wrap(W_TeeIterable(space, w_iterator,
-                                                      chained_list))
+                                                      w_chained_list))
     else:
         w_iterator = space.iter(w_iterable)
-        chained_list = TeeChainedListNode()
+        w_chained_list = space.wrap(W_TeeChainedListNode(space))
         iterators_w = [space.wrap(
-                           W_TeeIterable(space, w_iterator, chained_list))
+                           W_TeeIterable(space, w_iterator, w_chained_list))
                        for x in range(n)]
     return space.newtuple(iterators_w)
 
-class TeeChainedListNode(object):
-    w_obj = None
+class W_TeeChainedListNode(W_Root):
+    def __init__(self, space):
+        self.space = space
+        self.w_next = None
+        self.w_obj = None
+    
+    def reduce_w(self):
+        list_w = []
+        node = self
+        while node is not None:
+            #TODO:  Why does the annotator need this?
+            assert isinstance(node, W_TeeChainedListNode)
+            if node.w_obj is not None:
+                list_w.append(node.w_obj)
+                node = node.w_next
+        space = self.space
+        if list_w:
+            return self.space.newtuple([space.type(self),
+                                        space.newtuple([]),
+                                        space.newtuple([space.newlist(list_w)])
+                                       ])
+        else:
+            return self.space.newtuple([space.type(self),
+                                        space.newtuple([])])
 
+    def descr_setstate(self, space, w_state):
+        state = space.unpackiterable(w_state)
+        if len(state) != 1:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("invalid arguments"))
+        obj_list_w = space.unpackiterable(state[0])
+        node = self
+        for w_obj in obj_list_w:
+            assert isinstance(node, W_TeeChainedListNode)
+            node.w_obj = w_obj
+            node.w_next = W_TeeChainedListNode(self.space)
+            node = node.w_next
+
+def W_TeeChainedListNode___new__(space, w_subtype):
+    r = space.allocate_instance(W_TeeChainedListNode, w_subtype)
+    r.__init__(space)
+    return space.wrap(r)
+
+W_TeeChainedListNode.typedef = TypeDef(
+    'itertools._tee_chained_list',
+    __new__ = interp2app(W_TeeChainedListNode___new__),
+    __weakref__ = make_weakref_descr(W_TeeChainedListNode),
+    __reduce__ = interp2app(W_TeeChainedListNode.reduce_w),
+    __setstate__ = interp2app(W_TeeChainedListNode.descr_setstate)
+)
+
+W_TeeChainedListNode.typedef.acceptable_as_base_class = False
 
 class W_TeeIterable(W_Root):
-    def __init__(self, space, w_iterator, chained_list):
+    def __init__(self, space, w_iterator, w_chained_list):
         self.space = space
         self.w_iterator = w_iterator
-        assert chained_list is not None
-        self.chained_list = chained_list
+        assert w_chained_list is not None
+        self.w_chained_list = w_chained_list
 
     def iter_w(self):
         return self.space.wrap(self)
 
     def next_w(self):
-        chained_list = self.chained_list
-        w_obj = chained_list.w_obj
+        w_chained_list = self.w_chained_list
+        if w_chained_list is None:
+            raise OperationError(self.space.w_StopIteration, self.space.w_None)
+        #TODO: Is this the right thing to do?
+        assert isinstance(w_chained_list, W_TeeChainedListNode)
+        w_obj = w_chained_list.w_obj
         if w_obj is None:
-            w_obj = self.space.next(self.w_iterator)
-            chained_list.next = TeeChainedListNode()
-            chained_list.w_obj = w_obj
-        self.chained_list = chained_list.next
+            try:
+                w_obj = self.space.next(self.w_iterator)
+            except OperationError, e:
+                if e.match(self.space, self.space.w_StopIteration):
+                    self.w_chained_list = None
+                raise
+            w_chained_list.w_next = 
self.space.wrap(W_TeeChainedListNode(self.space))
+            w_chained_list.w_obj = w_obj
+        self.w_chained_list = w_chained_list.w_next
         return w_obj
 
-def W_TeeIterable___new__(space, w_subtype, w_iterable):
-    # Obscure and undocumented function.  PyPy only supports w_iterable
-    # being a W_TeeIterable, because the case where it is a general
-    # iterable is useless and confusing as far as I can tell (as the
-    # semantics are then slightly different; see the XXX in lib-python's
-    # test_itertools).
-    myiter = space.interp_w(W_TeeIterable, w_iterable)
-    return space.wrap(W_TeeIterable(space, myiter.w_iterator,
-                                           myiter.chained_list))
+    def reduce_w(self):
+        return self.space.newtuple([self.space.gettypefor(W_TeeIterable),
+                                    self.space.newtuple([
+                                        self.w_iterator,
+                                        self.w_chained_list])
+                                    ])
+        
+
+def W_TeeIterable___new__(space, w_subtype, w_iterable, w_chained_list=None):
+    if isinstance(w_iterable, W_TeeIterable):
+        myiter = space.interp_w(W_TeeIterable, w_iterable)
+        w_iterator = myiter.w_iterator
+        w_chained_list = myiter.w_chained_list
+    else:
+        w_iterator = space.iter(w_iterable)
+        w_chained_list = w_chained_list or 
space.wrap(W_TeeChainedListNode(space))
+    return space.wrap(W_TeeIterable(space, w_iterator, w_chained_list))
 
 W_TeeIterable.typedef = TypeDef(
         'itertools._tee',
@@ -869,6 +935,7 @@
         __iter__ = interp2app(W_TeeIterable.iter_w),
         __next__ = interp2app(W_TeeIterable.next_w),
         __weakref__ = make_weakref_descr(W_TeeIterable),
+        __reduce__ = interp2app(W_TeeIterable.reduce_w),
         )
 W_TeeIterable.typedef.acceptable_as_base_class = False
 
diff --git a/pypy/objspace/std/iterobject.py b/pypy/objspace/std/iterobject.py
--- a/pypy/objspace/std/iterobject.py
+++ b/pypy/objspace/std/iterobject.py
@@ -14,7 +14,7 @@
         self.index = index
 
     def getlength(self, space):
-        if self.w_seq is None:
+        if self.w_seq is None or space.is_w(self.w_seq, space.w_None):
             return space.wrap(0)
         index = self.index
         w_length = space.len(self.w_seq)
@@ -60,7 +60,7 @@
     """Sequence iterator implementation for general sequences."""
 
     def descr_next(self, space):
-        if self.w_seq is None:
+        if self.w_seq is None or space.is_w(self.w_seq, space.w_None):
             raise OperationError(space.w_StopIteration, space.w_None)
         try:
             w_item = space.getitem(self.w_seq, space.wrap(self.index))
@@ -79,7 +79,7 @@
     def descr_next(self, space):
         from pypy.objspace.std.listobject import W_ListObject
         w_seq = self.w_seq
-        if w_seq is None:
+        if w_seq is None or space.is_w(w_seq, space.w_None):
             raise OperationError(space.w_StopIteration, space.w_None)
         assert isinstance(w_seq, W_ListObject)
         index = self.index
@@ -129,7 +129,7 @@
         return space.newtuple([new_inst, space.newtuple(tup)])
 
     def descr_length_hint(self, space):
-        if self.w_seq is None:
+        if self.w_seq is None or space.is_w(self.w_seq, space.w_None):
             return space.wrap(0)
         index = self.index + 1
         w_length = space.len(self.w_seq)
@@ -147,7 +147,9 @@
         return self
 
     def descr_next(self, space):
-        if self.w_seq is None or self.index < 0:
+        if (self.w_seq is None
+            or space.is_w(self.w_seq, space.w_None)
+            or self.index < 0):
             raise OperationError(space.w_StopIteration, space.w_None)
         try:
             w_item = space.getitem(self.w_seq, space.wrap(self.index))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to