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