[pypy-commit] pypy list-strategies: Implemented setslice

l.diekmann noreply at buildbot.pypy.org
Fri Sep 23 13:11:32 CEST 2011


Author: Lukas Diekmann <lukas.diekmann at uni-duesseldorf.de>
Branch: list-strategies
Changeset: r47431:37b25c13f634
Date: 2011-02-23 16:00 +0100
http://bitbucket.org/pypy/pypy/changeset/37b25c13f634/

Log:	Implemented setslice

diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -99,6 +99,9 @@
     def setitem(self, index, w_item):
         self.strategy.setitem(self, index, w_item)
 
+    def setslice(self, start, step, slicelength, sequence_w):
+        self.strategy.setslice(self, start, step, slicelength, sequence_w)
+
     def insert(self, index, w_item):
         self.strategy.insert(self, index, w_item)
 
@@ -130,9 +133,15 @@
     def deleteitem(self, w_list, index):
         raise NotImplementedError
 
+    def deleteslice(self, w_list, start, step, slicelength):
+        raise NotImplementedError
+
     def setitem(self, w_list, index, w_item):
         raise NotImplementedError
 
+    def setslice(self, w_list, start, step, slicelength, sequence_w):
+        raise NotImplementedError
+
     def insert(self, w_list, index, w_item):
         raise NotImplementedError
 
@@ -172,9 +181,16 @@
     def deleteitem(self, w_list, index):
         raise IndexError
 
+    def deleteslice(self, w_list, start, step, slicelength):
+        raise IndexError
+
     def setitem(self, w_list, index, w_item):
         raise IndexError
 
+    def setslice(self, w_list, start, step, slicelength, sequence_w):
+        w_list.strategy = get_strategy_from_list_objects(sequence_w)
+        w_list.strategy.init_from_list_w(w_list, sequence_w)
+
     def insert(self, w_list, index, w_item):
         assert index == 0
         self.append(w_list, w_item)
@@ -247,6 +263,52 @@
         w_list.strategy.init_from_list_w(w_list, list_w)
         w_list.setitem(index, w_item)
 
+    def setslice(self, w_list, start, step, slicelength, sequence_w):
+        assert slicelength >= 0
+        items = self.cast_from_void_star(w_list.storage)
+        oldsize = len(items)
+        len2 = len(sequence_w)
+        if step == 1:  # Support list resizing for non-extended slices
+            delta = slicelength - len2
+            if delta < 0:
+                delta = -delta
+                newsize = oldsize + delta
+                # XXX support this in rlist!
+                items += [None] * delta
+                lim = start+len2
+                i = newsize - 1
+                while i >= lim:
+                    items[i] = items[i-delta]
+                    i -= 1
+            elif start >= 0:
+                del items[start:start+delta]
+            else:
+                assert delta==0   # start<0 is only possible with slicelength==0
+        elif len2 != slicelength:  # No resize for extended slices
+            raise operationerrfmt(space.w_ValueError, "attempt to "
+                  "assign sequence of size %d to extended slice of size %d",
+                  len2, slicelength)
+
+        if sequence_w is items:
+            if step > 0:
+                # Always copy starting from the right to avoid
+                # having to make a shallow copy in the case where
+                # the source and destination lists are the same list.
+                i = len2 - 1
+                start += i*step
+                while i >= 0:
+                    items[start] = sequence_w[i]
+                    start -= step
+                    i -= 1
+                return
+            else:
+                # Make a shallow copy to more easily handle the reversal case
+                sequence_w = list(sequence_w)
+        for i in range(len2):
+            items[start] = sequence_w[i]
+            start += step
+
+
     def deleteitem(self, w_list, index):
         list_w = self.cast_from_void_star(w_list.storage)
         del list_w[index]
@@ -373,10 +435,11 @@
     start, stop = normalize_simple_slice(space, length, w_start, w_stop)
     return w_list.getslice(start, stop, 1, stop - start)
 
-def setslice__List_ANY_ANY_ANY(space, w_list, w_start, w_stop, w_sequence):
+def setslice__List_ANY_ANY_ANY(space, w_list, w_start, w_stop, w_iterable):
     length = w_list.length()
     start, stop = normalize_simple_slice(space, length, w_start, w_stop)
-    _setitem_slice_helper(space, w_list, start, 1, stop-start, w_sequence)
+    sequence_w = space.listview(w_iterable)
+    w_list.setslice(start, 1, stop-start, sequence_w)
 
 def delslice__List_ANY_ANY(space, w_list, w_start, w_stop):
     length = w_list.length()
@@ -507,55 +570,10 @@
     return space.w_None
 
 def setitem__List_Slice_ANY(space, w_list, w_slice, w_iterable):
-    oldsize = len(w_list.wrappeditems)
+    oldsize = w_list.length()
     start, stop, step, slicelength = w_slice.indices4(space, oldsize)
-    _setitem_slice_helper(space, w_list, start, step, slicelength, w_iterable)
-
-def _setitem_slice_helper(space, w_list, start, step, slicelength, w_iterable):
-    sequence2 = space.listview(w_iterable)
-    assert slicelength >= 0
-    items = w_list.wrappeditems
-    oldsize = len(items)
-    len2 = len(sequence2)
-    if step == 1:  # Support list resizing for non-extended slices
-        delta = slicelength - len2
-        if delta < 0:
-            delta = -delta
-            newsize = oldsize + delta
-            # XXX support this in rlist!
-            items += [None] * delta
-            lim = start+len2
-            i = newsize - 1
-            while i >= lim:
-                items[i] = items[i-delta]
-                i -= 1
-        elif start >= 0:
-            del items[start:start+delta]
-        else:
-            assert delta==0   # start<0 is only possible with slicelength==0
-    elif len2 != slicelength:  # No resize for extended slices
-        raise operationerrfmt(space.w_ValueError, "attempt to "
-              "assign sequence of size %d to extended slice of size %d",
-              len2, slicelength)
-
-    if sequence2 is items:
-        if step > 0:
-            # Always copy starting from the right to avoid
-            # having to make a shallow copy in the case where
-            # the source and destination lists are the same list.
-            i = len2 - 1
-            start += i*step
-            while i >= 0:
-                items[start] = sequence2[i]
-                start -= step
-                i -= 1
-            return
-        else:
-            # Make a shallow copy to more easily handle the reversal case
-            sequence2 = list(sequence2)
-    for i in range(len2):
-        items[start] = sequence2[i]
-        start += step
+    sequence_w = space.listview(w_iterable)
+    w_list.setslice(start, step, slicelength, sequence_w)
 
 app = gateway.applevel("""
     def listrepr(currently_in_repr, l):
diff --git a/pypy/objspace/std/test/test_liststrategies.py b/pypy/objspace/std/test/test_liststrategies.py
--- a/pypy/objspace/std/test/test_liststrategies.py
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -92,5 +92,10 @@
         l.insert(0, self.space.wrap(2))
         assert isinstance(l.strategy, IntegerListStrategy)
 
+    def test_setslice(self):
+        l = W_ListObject([])
+        assert isinstance(l.strategy, EmptyListStrategy)
+        l.setslice(0, 1, 2, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+        assert isinstance(l.strategy, IntegerListStrategy)
 
 


More information about the pypy-commit mailing list