[pypy-svn] r56456 - in pypy/dist/pypy/module/itertools: . test

adurdin at codespeak.net adurdin at codespeak.net
Fri Jul 11 17:14:18 CEST 2008


Author: adurdin
Date: Fri Jul 11 17:14:18 2008
New Revision: 56456

Modified:
   pypy/dist/pypy/module/itertools/__init__.py
   pypy/dist/pypy/module/itertools/interp_itertools.py
   pypy/dist/pypy/module/itertools/test/test_itertools.py
Log:
(adurdin, jlg) interp_itertools - tee() done, only one left!


Modified: pypy/dist/pypy/module/itertools/__init__.py
==============================================================================
--- pypy/dist/pypy/module/itertools/__init__.py	(original)
+++ pypy/dist/pypy/module/itertools/__init__.py	Fri Jul 11 17:14:18 2008
@@ -37,6 +37,7 @@
         'repeat'        : 'interp_itertools.W_Repeat',
         'starmap'       : 'interp_itertools.W_StarMap',
         'takewhile'     : 'interp_itertools.W_TakeWhile',
+        'tee'           : 'interp_itertools.tee',
     }
 
     appleveldefs = {

Modified: pypy/dist/pypy/module/itertools/interp_itertools.py
==============================================================================
--- pypy/dist/pypy/module/itertools/interp_itertools.py	(original)
+++ pypy/dist/pypy/module/itertools/interp_itertools.py	Fri Jul 11 17:14:18 2008
@@ -617,7 +617,7 @@
 
         return self.space.call(self.w_fun, w_obj)
 
-def W_StarMap___new__(space, w_subtype, w_fun,w_iterable):
+def W_StarMap___new__(space, w_subtype, w_fun, w_iterable):
     return space.wrap(W_StarMap(space, w_fun, w_iterable))
 
 W_StarMap.typedef = TypeDef(
@@ -642,3 +642,73 @@
 W_StarMap.typedef.acceptable_as_base_class = False
 
 
+def tee(space, w_iterable, n=2):
+    """Return n independent iterators from a single iterable.
+    Note : once tee() has made a split, the original iterable
+    should not be used anywhere else; otherwise, the iterable could get
+    advanced without the tee objects being informed.
+    
+    Note : this member of the toolkit may require significant auxiliary
+    storage (depending on how much temporary data needs to be stored).
+    In general, if one iterator is going to use most or all of the
+    data before the other iterator, it is faster to use list() instead
+    of tee()
+    
+    Equivalent to :
+    
+    def tee(iterable, n=2):
+        def gen(next, data={}, cnt=[0]):
+            for i in count():
+                if i == cnt[0]:
+                    item = data[i] = next()
+                    cnt[0] += 1
+                else:
+                    item = data.pop(i)
+                yield item
+        it = iter(iterable)
+        return tuple([gen(it.next) for i in range(n)])
+    """
+    if n < 0:
+        raise OperationError(space.w_ValueError, space.wrap("n must be >= 0"))
+    
+    tee_state = TeeState(space, w_iterable)
+    iterators_w = [space.wrap(W_TeeIterable(space, tee_state)) for x in range(n)]
+    return space.newtuple(iterators_w)
+tee.unwrap_spec = [ObjSpace, W_Root, int]
+
+class TeeState(object):
+    def __init__(self, space, w_iterable):
+        self.space = space
+        self.w_iterable = self.space.iter(w_iterable)
+        self.num_saved = 0
+        self.saved_w = []
+
+    def get_next(self, index):
+        if index >= self.num_saved:
+            w_obj = self.space.next(self.w_iterable)
+            self.saved_w.append(w_obj)
+            self.num_saved += 1
+            return w_obj
+        else:
+            return self.saved_w[index]
+
+class W_TeeIterable(Wrappable):
+    def __init__(self, space, tee_state):
+        self.space = space
+        self.tee_state = tee_state
+        self.index = 0
+
+    def iter_w(self):
+        return self.space.wrap(self)
+
+    def next_w(self):
+        try:
+            w_obj = self.tee_state.get_next(self.index)
+            return w_obj
+        finally:
+            self.index += 1
+
+W_TeeIterable.typedef = TypeDef(
+        '_tee',
+        __iter__ = interp2app(W_TeeIterable.iter_w, unwrap_spec=['self']),
+        next     = interp2app(W_TeeIterable.next_w, unwrap_spec=['self']))

Modified: pypy/dist/pypy/module/itertools/test/test_itertools.py
==============================================================================
--- pypy/dist/pypy/module/itertools/test/test_itertools.py	(original)
+++ pypy/dist/pypy/module/itertools/test/test_itertools.py	Fri Jul 11 17:14:18 2008
@@ -379,7 +379,38 @@
         it = itertools.starmap(bool, [0])
         raises(TypeError, it.next)
 
-    
+    def test_tee(self):
+        import itertools
+
+        it1, it2 = itertools.tee([])
+        raises(StopIteration, it1.next)
+        raises(StopIteration, it2.next)
+
+        it1, it2 = itertools.tee([1, 2, 3])
+        for x in [1, 2]:
+            assert it1.next() == x
+        for x in [1, 2, 3]:
+            assert it2.next() == x
+        assert it1.next() == 3
+        raises(StopIteration, it1.next)
+        raises(StopIteration, it2.next)
+
+        assert itertools.tee([], 0) == ()
+
+        iterators = itertools.tee([1, 2, 3], 10)
+        for it in iterators:
+            for x in [1, 2, 3]:
+                assert it.next() == x
+            raises(StopIteration, it.next)
+
+    def test_iterables_wrongargs(self):
+        import itertools
+        
+        raises(TypeError, itertools.tee, 0)
+        raises(ValueError, itertools.tee, [], -1)
+        raises(TypeError, itertools.tee, [], None)
+
+
     def test_iterables(self):
         import itertools
     
@@ -396,6 +427,8 @@
             itertools.repeat(None),
             itertools.starmap(bool, []),
             itertools.takewhile(bool, []),
+            itertools.tee([])[0],
+            itertools.tee([])[1],
             ]
     
         for it in iterables:
@@ -403,7 +436,7 @@
             assert iter(it) is it
             assert hasattr(it, 'next')
             assert callable(it.next)
-    
+
     def test_docstrings(self):
         import itertools
         
@@ -421,6 +454,7 @@
             itertools.repeat,
             itertools.starmap,
             itertools.takewhile,
+            itertools.tee,
             ]
         for method in methods:
             assert method.__doc__



More information about the Pypy-commit mailing list