[pypy-commit] pypy default: fix iters that fail due to modification to return a length_hint of 0, and add a
pjenvey
noreply at buildbot.pypy.org
Fri Jan 25 01:30:09 CET 2013
Author: Philip Jenvey <pjenvey at underboss.org>
Branch:
Changeset: r60434:cbb68962961a
Date: 2013-01-24 16:28 -0800
http://bitbucket.org/pypy/pypy/changeset/cbb68962961a/
Log: fix iters that fail due to modification to return a length_hint of
0, and add a couple PEP 424 workarounds to make test_iterlen pass
diff --git a/lib-python/2.7/test/test_iterlen.py b/lib-python/2.7/test/test_iterlen.py
--- a/lib-python/2.7/test/test_iterlen.py
+++ b/lib-python/2.7/test/test_iterlen.py
@@ -94,7 +94,11 @@
def test_no_len_for_infinite_repeat(self):
# The repeat() object can also be infinite
- self.assertRaises(TypeError, len, repeat(None))
+ if test_support.check_impl_detail(pypy=True):
+ # 3.4 (PEP 424) behavior
+ self.assertEqual(len(repeat(None)), NotImplemented)
+ else:
+ self.assertRaises(TypeError, len, repeat(None))
class TestXrange(TestInvariantWithoutMutations):
@@ -230,6 +234,7 @@
self.assertRaises(RuntimeError, b.extend, BadLen())
self.assertRaises(RuntimeError, b.extend, BadLengthHint())
+ @test_support.impl_detail("PEP 424 disallows None results", pypy=False)
def test_invalid_hint(self):
# Make sure an invalid result doesn't muck-up the works
self.assertEqual(list(NoneLengthHint()), list(range(10)))
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -281,7 +281,6 @@
RegrTest('test_ioctl.py'),
RegrTest('test_isinstance.py', core=True),
RegrTest('test_iter.py', core=True),
- RegrTest('test_iterlen.py', skip="undocumented internal API behavior __length_hint__"),
RegrTest('test_itertools.py', core=True, usemodules="itertools struct"),
RegrTest('test_json.py'),
RegrTest('test_kqueue.py'),
diff --git a/pypy/module/_collections/interp_deque.py b/pypy/module/_collections/interp_deque.py
--- a/pypy/module/_collections/interp_deque.py
+++ b/pypy/module/_collections/interp_deque.py
@@ -521,7 +521,11 @@
return self.space.wrap(self.counter)
def next(self):
- self.deque.checklock(self.lock)
+ if self.lock is not self.deque.lock:
+ self.counter = 0
+ raise OperationError(
+ self.space.w_RuntimeError,
+ self.space.wrap("deque mutated during iteration"))
if self.counter == 0:
raise OperationError(self.space.w_StopIteration, self.space.w_None)
self.counter -= 1
@@ -560,7 +564,11 @@
return self.space.wrap(self.counter)
def next(self):
- self.deque.checklock(self.lock)
+ if self.lock is not self.deque.lock:
+ self.counter = 0
+ raise OperationError(
+ self.space.w_RuntimeError,
+ self.space.wrap("deque mutated during iteration"))
if self.counter == 0:
raise OperationError(self.space.w_StopIteration, self.space.w_None)
self.counter -= 1
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -352,7 +352,7 @@
self.pos = 0
def length(self):
- if self.dictimplementation is not None:
+ if self.dictimplementation is not None and self.len != -1:
return self.len - self.pos
return 0
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -898,7 +898,7 @@
raise NotImplementedError
def length(self):
- if self.setimplementation is not None:
+ if self.setimplementation is not None and self.len != -1:
return self.len - self.pos
return 0
diff --git a/pypy/objspace/std/test/test_lengthhint.py b/pypy/objspace/std/test/test_lengthhint.py
--- a/pypy/objspace/std/test/test_lengthhint.py
+++ b/pypy/objspace/std/test/test_lengthhint.py
@@ -6,7 +6,7 @@
SIZE = 4
ITEMS = range(SIZE)
- def _test_length_hint(self, w_obj):
+ def _test_length_hint(self, w_obj, w_mutate=None):
space = self.space
assert space.length_hint(w_obj, 8) == self.SIZE
@@ -18,6 +18,13 @@
space.next(w_iter)
assert space.length_hint(w_iter, 8) == self.SIZE - 1
+ if w_mutate is not None:
+ # Test handling of collections that enforce length
+ # immutability during iteration
+ space.call_function(w_mutate)
+ space.raises_w(space.w_RuntimeError, space.next, w_iter)
+ assert space.length_hint(w_iter, 8) == 0
+
def test_bytearray(self):
space = self.space
w_bytearray = space.call_function(space.w_bytearray,
@@ -31,16 +38,20 @@
self._test_length_hint(w_dict)
def test_dict_iterkeys(self):
- w_iterkeys = self.space.appexec([], """():
- return dict.fromkeys(%r).iterkeys()
- """ % self.ITEMS)
- self._test_length_hint(w_iterkeys)
+ space = self.space
+ w_iterkeys, w_mutate = space.fixedview(space.appexec([], """():
+ d = dict.fromkeys(%r)
+ return d.iterkeys(), d.popitem
+ """ % self.ITEMS), 2)
+ self._test_length_hint(w_iterkeys, w_mutate)
def test_dict_values(self):
- w_itervalues = self.space.appexec([], """():
- return dict.fromkeys(%r).itervalues()
- """ % self.ITEMS)
- self._test_length_hint(w_itervalues)
+ space = self.space
+ w_itervalues, w_mutate = space.fixedview(space.appexec([], """():
+ d = dict.fromkeys(%r)
+ return d.itervalues(), d.popitem
+ """ % self.ITEMS), 2)
+ self._test_length_hint(w_itervalues, w_mutate)
def test_frozenset(self):
space = self.space
@@ -50,7 +61,8 @@
def test_set(self):
space = self.space
w_set = space.call_function(space.w_set, space.wrap(self.ITEMS))
- self._test_length_hint(w_set)
+ w_mutate = space.getattr(w_set, space.wrap('pop'))
+ self._test_length_hint(w_set, w_mutate)
def test_list(self):
self._test_length_hint(self.space.wrap(self.ITEMS))
@@ -101,12 +113,19 @@
self._test_length_hint(W_Repeat(space, space.wrap(22),
space.wrap(self.SIZE)))
- def test_collections_deque(self):
+ def _setup_deque(self):
space = self.space
w_deque = W_Deque(space)
space.call_method(w_deque, '__init__', space.wrap(self.ITEMS))
- self._test_length_hint(w_deque)
- self._test_length_hint(w_deque.reviter())
+ w_mutate = space.getattr(w_deque, space.wrap('pop'))
+ return w_deque, w_mutate
+
+ def test_collections_deque(self):
+ self._test_length_hint(*self._setup_deque())
+
+ def test_collections_deque_rev(self):
+ w_deque, w_mutate = self._setup_deque()
+ self._test_length_hint(w_deque.reviter(), w_mutate)
def test_default(self):
space = self.space
More information about the pypy-commit
mailing list