[pypy-svn] r77756 - in pypy/branch/fast-forward/lib_pypy: . pypy_test

afa at codespeak.net afa at codespeak.net
Sun Oct 10 13:32:25 CEST 2010


Author: afa
Date: Sun Oct 10 13:32:23 2010
New Revision: 77756

Modified:
   pypy/branch/fast-forward/lib_pypy/_collections.py
   pypy/branch/fast-forward/lib_pypy/pypy_test/test_collections.py
Log:
Add deque.maxlen


Modified: pypy/branch/fast-forward/lib_pypy/_collections.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/_collections.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/_collections.py	Sun Oct 10 13:32:23 2010
@@ -18,6 +18,12 @@
 RGTLNK = n+1
 BLOCKSIZ = n+2
 
+# The deque's size limit is d.maxlen.  The limit can be zero or positive, or
+# None.  After an item is added to a deque, we check to see if the size has
+# grown past the limit. If it has, we get the size back down to the limit by
+# popping an item off of the opposite end.  The methods that can trigger this
+# are append(), appendleft(), extend(), and extendleft().
+
 class deque(object):
 
     def __new__(cls, iterable=(), *args, **kw):
@@ -25,7 +31,11 @@
         self.clear()
         return self
 
-    def __init__(self, iterable=()):
+    def __init__(self, iterable=(), maxlen=None):
+        if maxlen is not None:
+            if maxlen < 0:
+                raise ValueError("maxlen must be non-negative")
+        self.maxlen = maxlen
         add = self.append
         for elem in iterable:
             add(elem)
@@ -48,6 +58,8 @@
             self.rightndx = 0
         self.length += 1
         self.right[self.rightndx] = x
+        if self.maxlen is not None and self.length > self.maxlen:
+            self.popleft()
 
     def appendleft(self, x):
         self.state += 1
@@ -60,6 +72,8 @@
             self.leftndx = n-1
         self.length += 1
         self.left[self.leftndx] = x
+        if self.maxlen is not None and self.length > self.maxlen:
+            self.pop()
 
     def extend(self, iterable):
         for elem in iterable:
@@ -144,7 +158,10 @@
         else:
             self.__dict__[threadlocalattr] = True
             try:
-                return 'deque(%r)' % (list(self),)
+                if self.maxlen is not None:
+                    return 'deque(%r, maxlen=%s)' % (list(self), self.maxlen)
+                else:
+                    return 'deque(%r)' % (list(self),)
             finally:
                 del self.__dict__[threadlocalattr]
 
@@ -249,13 +266,13 @@
             self.rotate(-index)
 
     def __reduce_ex__(self, proto):
-        return type(self), (), self.__dict__, iter(self), None
+        return type(self), (list(self), self.maxlen)
 
     def __hash__(self):
         raise TypeError, "deque objects are unhashable"
 
     def __copy__(self):
-        return self.__class__(self)
+        return self.__class__(self, self.maxlen)
 
     # XXX make comparison more efficient
     def __eq__(self, other):

Modified: pypy/branch/fast-forward/lib_pypy/pypy_test/test_collections.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/pypy_test/test_collections.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/pypy_test/test_collections.py	Sun Oct 10 13:32:23 2010
@@ -14,7 +14,21 @@
 
     d = collections.deque([MutatingCmp()])
     py.test.raises(IndexError, d.remove, 1)
-    
+
+def test_deque_maxlen():
+    d = collections.deque([], 3)
+    d.append(1); d.append(2); d.append(3); d.append(4)
+    assert list(d) == [2, 3, 4]
+    assert repr(d) == "deque([2, 3, 4], maxlen=3)"
+
+    import pickle
+    d2 = pickle.loads(pickle.dumps(d))
+    assert repr(d2) == "deque([2, 3, 4], maxlen=3)"
+
+    import copy
+    d3 = copy.copy(d)
+    assert repr(d3) == "deque([2, 3, 4], maxlen=3)"
+
 class SubclassWithKwargs(collections.deque):
     def __init__(self, newarg=1):
         collections.deque.__init__(self)



More information about the Pypy-commit mailing list