[pypy-commit] pypy py3.5-bytearray: a test to check explicitly for non-forced cases

arigo pypy.commits at gmail.com
Sat Dec 3 06:40:34 EST 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5-bytearray
Changeset: r88844:9d0fb0aff02d
Date: 2016-12-03 12:20 +0100
http://bitbucket.org/pypy/pypy/changeset/9d0fb0aff02d/

Log:	a test to check explicitly for non-forced cases

diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -20,6 +20,7 @@
 from pypy.interpreter.typedef import TypeDef
 from pypy.objspace.std.sliceobject import W_SliceObject, unwrap_start_stop
 from pypy.objspace.std.stringmethods import StringMethods, _get_buffer
+from pypy.objspace.std.stringmethods import _descr_getslice_slowpath
 from pypy.objspace.std.bytesobject import W_BytesObject
 from pypy.objspace.std.util import get_positive_index
 from pypy.objspace.std.formatting import mod_format, FORMAT_BYTEARRAY
@@ -93,8 +94,6 @@
         return space.wrap(ord(character))
 
     def _val(self, space):
-        # XXX review the calls of _val and think if some of them should
-        # XXX not force a copy of self._data if _offset > 0
         return self.getdata()
 
     @staticmethod
@@ -377,7 +376,7 @@
 
     def descr_setitem(self, space, w_index, w_other):
         if isinstance(w_index, W_SliceObject):
-            sequence2 = [c for c in makebytesdata_w(space, w_other)]
+            sequence2 = makebytesdata_w(space, w_other)
             oldsize = self._len()
             start, stop, step, slicelength = w_index.indices4(space, oldsize)
             if start == 0 and step == 1 and len(sequence2) <= slicelength:
@@ -385,11 +384,8 @@
                 slicelength = len(sequence2)
                 if slicelength == 0:
                     return
-                data = self._data
-                start += self._offset
-                #stop += self._offset---not used
-            else:
-                data = self.getdata()
+            data = self._data
+            start += self._offset
             _setitem_slice_helper(space, data, start, step,
                                   slicelength, sequence2, empty_elem='\x00')
         else:
@@ -506,6 +502,24 @@
         ofs = self._offset
         return (self._data, start + ofs, end + ofs, ofs)
 
+    def descr_getitem(self, space, w_index):
+        # optimization: this version doesn't force getdata()
+        if isinstance(w_index, W_SliceObject):
+            start, stop, step, sl = w_index.indices4(space, self._len())
+            if sl == 0:
+                return self._empty()
+            elif step == 1:
+                assert start >= 0 and stop >= 0
+                ofs = self._offset
+                return self._new(self._data[start + ofs : stop + ofs])
+            else:
+                start += self._offset
+                ret = _descr_getslice_slowpath(self._data, start, step, sl)
+                return self._new_from_list(ret)
+
+        index = space.getindex_w(w_index, space.w_IndexError, self._KIND1)
+        return self._getitem_result(space, index)
+
 
 # ____________________________________________________________
 # helpers for slow paths, moved out because they contain loops
@@ -1247,21 +1261,6 @@
                     "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
diff --git a/pypy/objspace/std/test/test_bytearrayobject.py b/pypy/objspace/std/test/test_bytearrayobject.py
--- a/pypy/objspace/std/test/test_bytearrayobject.py
+++ b/pypy/objspace/std/test/test_bytearrayobject.py
@@ -85,6 +85,7 @@
         raises(IndexError, b.__getitem__, 4)
         assert b[1:5] == bytearray(b'est')
         assert b[slice(1,5)] == bytearray(b'est')
+        assert b[1:5:2] == bytearray(b'et')
 
     def test_arithmetic(self):
         b1 = bytearray(b'hello ')
@@ -627,3 +628,52 @@
     def test_constructor_typeerror(self):
         raises(TypeError, bytearray, b'', 'ascii')
         raises(TypeError, bytearray, '')
+
+    def test_dont_force_offset(self):
+        def make(x=b'abcdefghij', shift=3):
+            b = bytearray(b'?'*shift + x)
+            repr(b)                       # force 'b'
+            del b[:shift]                 # add shift to b._offset
+            return b
+        assert make(shift=0).__alloc__() == 11
+        #
+        x = make(shift=3)
+        assert x.__alloc__() == 14
+        repr(x) 
+        assert x.__alloc__() == 11
+        #
+        x = make(shift=3)
+        assert memoryview(x)[1] == ord('b')
+        assert x.__alloc__() == 14
+        assert len(x) == 10
+        assert x.__alloc__() == 14
+        assert x[3] == ord('d')
+        assert x[-3] == ord('h')
+        assert x.__alloc__() == 14
+        assert x[3:-3] == b'defg'
+        assert x[-3:3:-1] == b'hgfe'
+        assert x.__alloc__() == 14
+        #
+        x = make(shift=3)
+        x[3] = ord('D')
+        assert x.__alloc__() == 14
+        x[4:6] = b'EF'
+        assert x.__alloc__() == 14
+        x[6:8] = b'G'
+        assert x.__alloc__() == 13
+        x[-2:4:-2] = b'*/'
+        assert x.__alloc__() == 13
+        assert x == bytearray(b'abcDE/G*j')
+        #
+        x = make(shift=3)
+        assert x.__alloc__() == 14
+        del x[:1]
+        assert x.__alloc__() == 13
+        del x[0:5]
+        assert x.__alloc__() == 8
+        del x[0]
+        assert len(x) == 4
+        assert x.__alloc__() == 7
+        del x[1]
+        assert x.__alloc__() == 4      # forced
+        assert x == bytearray(b'gij')


More information about the pypy-commit mailing list