Commits

Philip Jenvey committed 56e278e

add the rest of the needed __length_hint__ impls and more tests

  • Participants
  • Parent commits 18cbe2d
  • Branches length-hint

Comments (0)

Files changed (6)

File pypy/module/_collections/interp_deque.py

     def iter(self):
         return self.space.wrap(self)
 
+    def length(self):
+        return self.space.wrap(self.counter)
+
     def next(self):
         self.deque.checklock(self.lock)
         if self.counter == 0:
         return w_x
 
 W_DequeIter.typedef = TypeDef("deque_iterator",
-    __iter__ = interp2app(W_DequeIter.iter),
-    next = interp2app(W_DequeIter.next),
+    __iter__        = interp2app(W_DequeIter.iter),
+    __length_hint__ = interp2app(W_DequeIter.length),
+    next            = interp2app(W_DequeIter.next),
 )
 W_DequeIter.typedef.acceptable_as_base_class = False
 
     def iter(self):
         return self.space.wrap(self)
 
+    def length(self):
+        return self.space.wrap(self.counter)
+
     def next(self):
         self.deque.checklock(self.lock)
         if self.counter == 0:
         return w_x
 
 W_DequeRevIter.typedef = TypeDef("deque_reverse_iterator",
-    __iter__ = interp2app(W_DequeRevIter.iter),
-    next = interp2app(W_DequeRevIter.next),
+    __iter__        = interp2app(W_DequeRevIter.iter),
+    __length_hint__ = interp2app(W_DequeRevIter.length),
+    next            = interp2app(W_DequeRevIter.next),
 )
 W_DequeRevIter.typedef.acceptable_as_base_class = False
 

File pypy/module/itertools/interp_itertools.py

     def iter_w(self):
         return self.space.wrap(self)
 
+    def length_w(self):
+        if not self.counting:
+            return self.space.w_NotImplemented
+        return self.space.wrap(self.count)
+
     def repr_w(self):
         objrepr = self.space.str_w(self.space.repr(self.w_obj))
         if self.counting:
 W_Repeat.typedef = TypeDef(
         'repeat',
         __module__ = 'itertools',
-        __new__  = interp2app(W_Repeat___new__),
-        __iter__ = interp2app(W_Repeat.iter_w),
-        next     = interp2app(W_Repeat.next_w),
-        __repr__ = interp2app(W_Repeat.repr_w),
+        __new__          = interp2app(W_Repeat___new__),
+        __iter__         = interp2app(W_Repeat.iter_w),
+        __length_hint__  = interp2app(W_Repeat.length_w),
+        next             = interp2app(W_Repeat.next_w),
+        __repr__         = interp2app(W_Repeat.repr_w),
         __doc__  = """Make an iterator that returns object over and over again.
     Runs indefinitely unless the times argument is specified.  Used
     as argument to imap() for invariant parameters to the called

File pypy/objspace/std/dicttype.py

 
 # ____________________________________________________________
 
+def descr_dictiter__length_hint__(space, w_self):
+    from pypy.objspace.std.dictmultiobject import W_BaseDictMultiIterObject
+    assert isinstance(w_self, W_BaseDictMultiIterObject)
+    return space.wrap(w_self.iteratorimplementation.length())
+
+
 def descr_dictiter__reduce__(w_self, space):
     """
     This is a slightly special case of pickling.
 
 
 dictiter_typedef = StdTypeDef("dictionaryiterator",
-    __reduce__ = gateway.interp2app(descr_dictiter__reduce__),
+    __length_hint__ = gateway.interp2app(descr_dictiter__length_hint__),
+    __reduce__      = gateway.interp2app(descr_dictiter__reduce__),
     )
 
 # ____________________________________________________________

File pypy/objspace/std/setobject.py

         return w_key
     raise OperationError(space.w_StopIteration, space.w_None)
 
-# XXX __length_hint__()
-##def len__SetIterObject(space, w_setiter):
-##    content = w_setiter.content
-##    if content is None or w_setiter.len == -1:
-##        return space.wrap(0)
-##    return space.wrap(w_setiter.len - w_setiter.pos)
-
 # some helper functions
 
 def newset(space):

File pypy/objspace/std/settype.py

 
 set_typedef.registermethods(globals())
 
-setiter_typedef = StdTypeDef("setiterator")
+def descr_setiterator__length_hint__(space, w_self):
+    from pypy.objspace.std.setobject import W_SetIterObject
+    assert isinstance(w_self, W_SetIterObject)
+    return space.wrap(w_self.iterimplementation.length())
+
+setiter_typedef = StdTypeDef("setiterator",
+    __length_hint__ = gateway.interp2app(descr_setiterator__length_hint__),
+    )

File pypy/objspace/std/test/test_lengthhint.py

+from pypy.module._collections.interp_deque import W_Deque
+from pypy.module.itertools.interp_itertools import W_Repeat
+
 class TestLengthHint:
 
     SIZE = 4
         space.next(w_iter)
         assert space.length_hint(w_iter, 8) == self.SIZE - 1
 
+    def test_bytearray(self):
+        space = self.space
+        w_bytearray = space.call_function(space.w_bytearray,
+                                          space.wrap(self.ITEMS))
+        self._test_length_hint(w_bytearray)
+
+    def test_dict(self):
+        space = self.space
+        w_dict = space.call_function(space.w_dict,
+                                     space.wrap((i, None) for i in self.ITEMS))
+        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)
+
+    def test_dict_values(self):
+        w_itervalues = self.space.appexec([], """():
+            return dict.fromkeys(%r).itervalues()
+        """ % self.ITEMS)
+        self._test_length_hint(w_itervalues)
+
+    def test_frozenset(self):
+        space = self.space
+        w_set = space.call_function(space.w_frozenset, space.wrap(self.ITEMS))
+        self._test_length_hint(w_set)
+
+    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)
+
     def test_list(self):
-        self._test_length_hint(self.space.newlist(self.ITEMS))
+        self._test_length_hint(self.space.wrap(self.ITEMS))
+
+    def test_str(self):
+        self._test_length_hint(self.space.wrap('P' * self.SIZE))
+
+    def test_unicode(self):
+        self._test_length_hint(self.space.wrap(u'Y' * self.SIZE))
 
     def test_tuple(self):
         self._test_length_hint(self.space.newtuple(self.ITEMS))
     def test_reversed(self):
         space = self.space
         w_reversed = space.call_method(space.builtin, 'reversed',
-                                       space.newlist(self.ITEMS))
+                                       space.wrap(self.ITEMS))
         assert space.int_w(
             space.call_method(w_reversed, '__length_hint__')) == self.SIZE
         self._test_length_hint(w_reversed)
                                      space.newint(self.SIZE))
         self._test_length_hint(w_xrange)
 
+    def test_itertools_repeat(self):
+        space = self.space
+        self._test_length_hint(W_Repeat(space, space.wrap(22),
+                                        space.wrap(self.SIZE)))
+
+    def test_collections_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())
+
     def test_default(self):
         space = self.space
         assert space.length_hint(space.w_False, 3) == 3
 
     def test_NotImplemented(self):
-        from pypy.interpreter.error import OperationError
         space = self.space
         w_foo = space.appexec([], """():
             class Foo(object):