[pypy-svn] pypy collections-module: getitem(), setitem(), and maybe delitem() if we already had rotate()

arigo commits-noreply at bitbucket.org
Tue Feb 15 16:42:58 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: collections-module
Changeset: r41972:95ee17576483
Date: 2011-02-15 16:30 +0100
http://bitbucket.org/pypy/pypy/changeset/95ee17576483/

Log:	getitem(), setitem(), and maybe delitem() if we already had rotate()

diff --git a/pypy/module/_collections/test/test_deque.py b/pypy/module/_collections/test/test_deque.py
--- a/pypy/module/_collections/test/test_deque.py
+++ b/pypy/module/_collections/test/test_deque.py
@@ -139,49 +139,31 @@
     def test_getitem(self):
         from _collections import deque
         n = 200
-        d = deque(xrange(n))
-        l = range(n)
-        for i in xrange(n):
-            d.popleft()
-            l.pop(0)
-            if i & 1:
-                d.append(i)
-                l.append(i)
-            for j in xrange(-len(l), len(l)):
-                assert d[j] == l[j]
-
-        d = deque('superman')
-        self.assertEqual(d[0], 's')
-        self.assertEqual(d[-1], 'n')
-        d = deque()
-        self.assertRaises(IndexError, d.__getitem__, 0)
-        self.assertRaises(IndexError, d.__getitem__, -1)
+        l = xrange(1000, 1000 + n)
+        d = deque(l)
+        for j in xrange(-n, n):
+            assert d[j] == l[j]
+        raises(IndexError, "d[-n-1]")
+        raises(IndexError, "d[n]")
 
     def test_setitem(self):
+        from _collections import deque
         n = 200
         d = deque(xrange(n))
         for i in xrange(n):
             d[i] = 10 * i
-        self.assertEqual(list(d), [10*i for i in xrange(n)])
+        assert list(d) == [10*i for i in xrange(n)]
         l = list(d)
-        for i in xrange(1-n, 0, -1):
+        for i in xrange(1-n, 0, -3):
             d[i] = 7*i
             l[i] = 7*i
-        self.assertEqual(list(d), l)
+        assert list(d) == l
 
     def test_delitem(self):
-        n = 500         # O(n**2) test, don't make this too big
-        d = deque(xrange(n))
-        self.assertRaises(IndexError, d.__delitem__, -n-1)
-        self.assertRaises(IndexError, d.__delitem__, n)
-        for i in xrange(n):
-            self.assertEqual(len(d), n-i)
-            j = random.randrange(-len(d), len(d))
-            val = d[j]
-            self.assertIn(val, d)
-            del d[j]
-            self.assertNotIn(val, d)
-        self.assertEqual(len(d), 0)
+        from _collections import deque
+        d = deque("abcdef")
+        del d[-2]
+        assert list(d) == list("abcdf")
 
     def test_reverse(self):
         n = 500         # O(n**2) test, don't make this too big

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
@@ -289,14 +289,58 @@
     def ge(self, w_other):
         return self.compare(w_other, 'ge')
 
+    def locate(self, i):
+        if i < (self.len >> 1):
+            i += self.leftindex
+            b = self.leftblock
+            while i >= BLOCKLEN:
+                b = b.rightlink
+                i -= BLOCKLEN
+        else:
+            i = i - self.len + 1     # then i <= 0
+            i += self.rightindex
+            b = self.rightblock
+            while i < 0:
+                b = b.leftlink
+                i += BLOCKLEN
+        assert i >= 0
+        return b, i
+
     @unwrap_spec('self', W_Root)
     def getitem(self, w_index):
         space = self.space
         start, stop, step = space.decode_index(w_index, self.len)
         if step == 0:  # index only
-            return space.wrap(self.mmap.getitem(start))
+            b, i = self.locate(start)
+            return b.data[i]
         else:
-            xxx
+            raise OperationError(self.w_TypeError,
+                                 self.wrap("deque[:] is not supported"))
+
+    @unwrap_spec('self', W_Root, W_Root)
+    def setitem(self, w_index, w_newobj):
+        space = self.space
+        start, stop, step = space.decode_index(w_index, self.len)
+        if step == 0:  # index only
+            b, i = self.locate(start)
+            b.data[i] = w_newobj
+        else:
+            raise OperationError(self.w_TypeError,
+                                 self.wrap("deque[:] is not supported"))
+
+    @unwrap_spec('self', W_Root)
+    def delitem(self, w_index):
+        space = self.space
+        start, stop, step = space.decode_index(w_index, self.len)
+        if step == 0:  # index only
+            # delitem() implemented in terms of rotate for simplicity and
+            # reasonable performance near the end points.
+            self.rotate(-i)
+            self.popleft()
+            self.rotate(i)
+        else:
+            raise OperationError(self.w_TypeError,
+                                 self.wrap("deque[:] is not supported"))
 
     def get_maxlen(space, self):
         if self.maxlen == sys.maxint:
@@ -359,6 +403,8 @@
     __ge__ = interp2app(W_Deque.ge),
     __iadd__ = interp2app(W_Deque.iadd),
     __getitem__ = interp2app(W_Deque.getitem),
+    __setitem__ = interp2app(W_Deque.setitem),
+    __delitem__ = interp2app(W_Deque.delitem),
     maxlen = GetSetProperty(W_Deque.get_maxlen),
 )
 


More information about the Pypy-commit mailing list