[pypy-svn] r39769 - in pypy/dist/pypy/objspace/std: . test

gbrandl at codespeak.net gbrandl at codespeak.net
Sat Mar 3 11:40:23 CET 2007


Author: gbrandl
Date: Sat Mar  3 11:40:21 2007
New Revision: 39769

Modified:
   pypy/dist/pypy/objspace/std/listmultiobject.py
   pypy/dist/pypy/objspace/std/smartresizablelist.py
   pypy/dist/pypy/objspace/std/test/test_listmultiobject.py
   pypy/dist/pypy/objspace/std/test/test_listobject.py
Log:
Some more listmultiobject special cases for empty lists, some new tests,
use the freelist in the smartresizablelist.

more tests to follow.



Modified: pypy/dist/pypy/objspace/std/listmultiobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/listmultiobject.py	(original)
+++ pypy/dist/pypy/objspace/std/listmultiobject.py	Sat Mar  3 11:40:21 2007
@@ -9,12 +9,26 @@
 from pypy.rlib.listsort import TimSort
 
 
+# ListImplementations
+
+# An empty list always is an EmptyListImplementation.
+#
+# RDictImplementation -- standard implementation
+# StrListImplementation -- lists consisting only of strings
+# ChunkedListImplementation -- when having set the withchunklist option
+# SmartResizableListImplementation -- when having set the
+#                                     withsmartresizablelist option
+# RangeImplementation -- constructed by range()
+# SliceTrackingListImplementation -- when having set the withfastslice option
+# SliceListImplementation -- slices of a SliceTrackingListImplementation
+
+
 class ListImplementation(object):
 
     def __init__(self, space):
         self.space = space
 
-# A list implementation should implement the following methods:
+# A list implementation must implement the following methods:
 
 ##     def length(self):
 ##         pass
@@ -25,9 +39,12 @@
 ##     def getitem_slice(self, start, stop):
 ##         pass
 
+##     def get_list_w(self):
+##         pass
+
 
-# the following operations return the list implementation that should
-# be used after the call
+# The following operations return the list implementation that should
+# be used after the call.
 # If it turns out that the list implementation cannot really perform
 # the operation it can return None for the following ones:
 
@@ -49,16 +66,12 @@
     def extend(self, other):
         pass
 
-
-# special cases:
+    # special case
 
     def add(self, other):
         pass
 
-##     def get_list_w(self):
-##         pass
-
-# default implementations, can (but don't have to be) overridden:
+# Default implementations, can (but don't have to be) overridden:
 
     def reverse(self):
         l = self.length()
@@ -122,7 +135,7 @@
             list_w = self.get_list_w()
             assert i >= 0 and i < len(list_w)
             list_w[i] = w_item
-            return self.make_implementation(list_w)
+            return make_implementation(self.space, list_w)
         return impl
 
     def i_insert(self, i, w_item):
@@ -131,7 +144,7 @@
             list_w = self.get_list_w()
             assert i >= 0 and i <= len(list_w)
             list_w.insert(i, w_item)
-            return self.make_implementation(list_w)
+            return make_implementation(self.space, list_w)
         return impl
 
     def i_append(self, w_item):
@@ -139,7 +152,7 @@
         if impl is None: # failed to implement
             list_w = self.get_list_w()
             list_w.append(w_item)
-            return self.make_implementation(list_w)
+            return make_implementation(self.space, list_w)
         return impl
 
     def i_add(self, other):
@@ -147,7 +160,7 @@
         if impl is None:
             list_w1 = self.get_list_w()
             list_w2 = other.get_list_w()
-            return self.make_implementation(list_w1 + list_w2)
+            return make_implementation(self.space, list_w1 + list_w2)
         return impl
 
     def i_extend(self, other):
@@ -155,7 +168,7 @@
         if impl is None:
             list_w1 = self.get_list_w()
             list_w2 = other.get_list_w()
-            return self.make_implementation(list_w1 + list_w2)
+            return make_implementation(self.space, list_w1 + list_w2)
         return impl
 
     def i_delitem(self, i):
@@ -163,7 +176,7 @@
         if impl is None:
             list_w = self.get_list_w()
             del list_w[i]
-            return self.make_implementation(list_w)
+            return make_implementation(self.space, list_w)
         return impl
 
     def i_delitem_slice(self, start, stop):
@@ -173,24 +186,9 @@
             assert 0 <= start < len(list_w)
             assert 0 <= stop <= len(list_w)
             del list_w[start:stop]
-            return self.make_implementation(list_w)
+            return make_implementation(self.space, list_w)
         return impl
 
-    def make_implementation(self, list_w):
-        space = self.space
-        if space.config.objspace.std.withsmartresizablelist:
-            from pypy.objspace.std.smartresizablelist import \
-                SmartResizableListImplementation
-            impl = SmartResizableListImplementation(space)
-            impl.extend(RListImplementation(space, list_w))
-            return impl
-        if space.config.objspace.std.withchunklist:
-            return ChunkedListImplementation(space, list_w)
-        if space.config.objspace.std.withfastslice:
-            return SliceTrackingListImplementation(space, list_w)
-        else:
-            return RListImplementation(space, list_w)
-
 
 class RListImplementation(ListImplementation):
     def __init__(self, space, list_w):
@@ -474,7 +472,7 @@
 
     def getitem_slice_step(self, start, stop, step, slicelength):
         assert 0 <= start < len(self.strlist)
-        assert 0 <= stop < len(self.strlist)
+        assert 0 <= stop <= len(self.strlist)
         assert slicelength > 0
         res = [""] * slicelength
         for i in range(slicelength):
@@ -810,31 +808,33 @@
     return True
 
 def make_implementation(space, list_w):
-    if list_w:
-        if space.config.objspace.std.withsmartresizablelist:
-            from pypy.objspace.std.smartresizablelist import \
-                SmartResizableListImplementation
-            impl = SmartResizableListImplementation(space)
-            impl.extend(RListImplementation(space, list_w))
-            return impl
-        if space.config.objspace.std.withchunklist:
-            return ChunkedListImplementation(space, list_w)
-        elif space.config.objspace.std.withfastslice:
-            impl = SliceTrackingListImplementation(space, list_w)
-        else:
-            w_type = space.type(list_w[0])
-            if (space.is_w(w_type, space.w_str) and
-                is_homogeneous(space, list_w, w_type)):
-                strlist = [space.str_w(w_i) for w_i in list_w]
-                impl = StrListImplementation(space, strlist)
-            else:
-                impl = RListImplementation(space, list_w)
+    if not list_w:
+        return space.fromcache(State).empty_impl
+    if space.config.objspace.std.withsmartresizablelist:
+        from pypy.objspace.std.smartresizablelist import \
+            SmartResizableListImplementation
+        impl = SmartResizableListImplementation(space)
+        impl.extend(RListImplementation(space, list_w))
+        return impl
+    if space.config.objspace.std.withchunklist:
+        return ChunkedListImplementation(space, list_w)
+    elif space.config.objspace.std.withfastslice:
+        return SliceTrackingListImplementation(space, list_w)
     else:
-        impl = space.fromcache(State).empty_impl
-    return impl
+        # check if it's strings only
+        w_type = space.type(list_w[0])
+        if (space.is_w(w_type, space.w_str) and
+            is_homogeneous(space, list_w, w_type)):
+            strlist = [space.str_w(w_i) for w_i in list_w]
+            return StrListImplementation(space, strlist)
+        else:
+            return RListImplementation(space, list_w)
 
 def convert_list_w(space, list_w):
-    impl = make_implementation(space, list_w)
+    if not list_w:
+        impl = space.fromcache(State).empty_impl
+    else:
+        impl = make_implementation(space, list_w)
     return W_ListMultiObject(space, impl)
 
 
@@ -898,6 +898,8 @@
     length = w_list.implementation.length()
     start, stop, step, slicelength = w_slice.indices4(space, length)
     assert slicelength >= 0
+    if slicelength == 0:
+        return W_ListMultiObject(space)
     if step == 1 and 0 <= start <= stop:
         return W_ListMultiObject(
             space,
@@ -940,6 +942,8 @@
         if e.match(space, space.w_TypeError):
             raise FailedToImplement
         raise
+    if times <= 0:
+        return W_ListMultiObject(space)
     return W_ListMultiObject(space, w_list.implementation.mul(times))
 
 def mul__ListMulti_ANY(space, w_list, w_times):
@@ -955,8 +959,11 @@
         if e.match(space, space.w_TypeError):
             raise FailedToImplement
         raise
-    # XXX could be more efficient?
-    w_list.implementation = w_list.implementation.mul(times)
+    if times <= 0:
+        w_list.implementation = space.fromcache(State).empty_impl
+    else:
+        # XXX could be more efficient?
+        w_list.implementation = w_list.implementation.mul(times)
     return w_list
 
 def eq__ListMulti_ListMulti(space, w_list1, w_list2):
@@ -1018,16 +1025,23 @@
     idx = space.int_w(w_idx)
     length = w_list.implementation.length()
     idx = _adjust_index(space, idx, length, "list deletion index out of range")
-    w_list.implementation = w_list.implementation.i_delitem(idx)
+    if length == 1:
+        w_list.implementation = space.fromcache(State).empty_impl
+    else:
+        w_list.implementation = w_list.implementation.i_delitem(idx)
     return space.w_None
 
 def delitem__ListMulti_Slice(space, w_list, w_slice):
-    start, stop, step, slicelength = w_slice.indices4(
-        space, w_list.implementation.length())
+    length = w_list.implementation.length()
+    start, stop, step, slicelength = w_slice.indices4(space, length)
 
     if slicelength == 0:
         return
 
+    if slicelength == length:
+        w_list.implementation = space.fromcache(State).empty_impl
+        return space.w_None
+
     if step < 0:
         start = start + step * (slicelength-1)
         step = -step

Modified: pypy/dist/pypy/objspace/std/smartresizablelist.py
==============================================================================
--- pypy/dist/pypy/objspace/std/smartresizablelist.py	(original)
+++ pypy/dist/pypy/objspace/std/smartresizablelist.py	Sat Mar  3 11:40:21 2007
@@ -45,7 +45,7 @@
         self.freelist = {}
 
     def alloc(self, size):
-        l = self.freelist.get(size)
+        l = self.freelist.get(size, None)
         if l is not None and l:
             return l.pop()
         return [None] * size
@@ -59,6 +59,8 @@
         else:
             self.freelist[size] = [l]
 
+freelist = FreeList()
+
 class SmartResizableListImplementation(ListImplementation):
     def __init__(self, space):
         self._length = 0
@@ -96,7 +98,7 @@
                 self.size_datablock *= 2
             self.last_superblock_filled = 0
         if len(data_blocks) == self.num_datablocks:
-            data_blocks.append([None] * self.size_datablock)
+            data_blocks.append(freelist.alloc(self.size_datablock))
         self.last_superblock_filled += 1
         self.num_datablocks += 1
         self.index_last = 0
@@ -124,7 +126,7 @@
         data_blocks = self.data_blocks
         if len(data_blocks) > self.num_datablocks:
             assert len(data_blocks) - self.num_datablocks == 1
-            data_blocks.pop()
+            freelist.dealloc(data_blocks.pop())
         for i in range(self.index_last): #XXX consider when not to do this
             idx = self.num_datablocks - 1
             assert idx >= 0

Modified: pypy/dist/pypy/objspace/std/test/test_listmultiobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_listmultiobject.py	(original)
+++ pypy/dist/pypy/objspace/std/test/test_listmultiobject.py	Sat Mar  3 11:40:21 2007
@@ -124,12 +124,6 @@
         cls.space = gettestobjspace(**{
             "objspace.std.withsmartresizablelist": True})
 
-    def test_insert_some(self):
-        ls = [1,2,3,4,5,6,7]
-        for i in range(5):
-            ls.insert(0, i)
-        assert len(ls) == 12
-
 class AppTest_ChunkListObject(test_listobject.AppTestW_ListObject):
     def setup_class(cls):
         cls.space = gettestobjspace(**{"objspace.std.withchunklist": True})

Modified: pypy/dist/pypy/objspace/std/test/test_listobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_listobject.py	(original)
+++ pypy/dist/pypy/objspace/std/test/test_listobject.py	Sat Mar  3 11:40:21 2007
@@ -340,6 +340,7 @@
         assert self.space.eq_w(self.space.le(w_list4, w_list3),
                            self.space.w_True)
 
+
 class AppTestW_ListObject:
     def test_call_list(self):
         assert list('') == []
@@ -347,27 +348,41 @@
         assert list((1, 2)) == [1, 2]
         l = []
         assert list(l) is not l
+        assert list(range(10)) == range(10)
 
     def test_explicit_new_init(self):
         l = l0 = list.__new__(list)
         l.__init__([1,2])
         assert l is l0
-        assert l ==[1,2]
-        list.__init__(l,[1,2,3])
+        assert l == [1,2]
+        list.__init__(l, [1,2,3])
+        assert l is l0
+        assert l == [1,2,3]
+        list.__init__(l, ['a', 'b', 'c'])
         assert l is l0
-        assert l ==[1,2,3]
-        
+        assert l == ['a', 'b', 'c']
+
     def test_extend_list(self):
         l = l0 = [1]
         l.extend([2])
         assert l is l0
         assert l == [1,2]
+        l = ['a']
+        l.extend('b')
+        assert l == ['a', 'b']
+        l = ['a']
+        l.extend([0])
+        assert l == ['a', 0]
+        l = range(10)
+        l.extend([10])
+        assert l == range(11)
 
     def test_extend_tuple(self):
         l = l0 = [1]
         l.extend((2,))
         assert l is l0
         assert l == [1,2]
+        l = ['a']
 
     def test_extend_iterable(self):
         l = l0 = [1]
@@ -412,7 +427,7 @@
         l = [ 'a' ]
         l.sort(key = lower)
         assert l == [ 'a' ]
-        
+
     def test_sort_reversed(self):
         l = range(10)
         l.sort(reverse = True)
@@ -429,7 +444,7 @@
         l = ['a', 'C', 'b']
         l.sort(reverse = True, key = lower)
         assert l == ['C', 'b', 'a']
-    
+
     def test_getitem(self):
         l = [1, 2, 3, 4, 5, 6, 9]
         assert l[0] == 1
@@ -449,16 +464,23 @@
         raises(IndexError, "del l[len(l)]")
         raises(IndexError, "del l[-len(l)-1]")
 
-    def test_extended_slice(self):
+    def test_getitem_slice(self):
         l = range(10)
         del l[::2]
-        assert l ==[1,3,5,7,9]
+        assert l == [1,3,5,7,9]
         l[-2::-1] = l[:-1]
-        assert l ==[7,5,3,1,9]
+        assert l == [7,5,3,1,9]
         del l[-1:2:-1]
-        assert l ==[7,5,3]
+        assert l == [7,5,3]
         del l[:2]
-        assert l ==[3]
+        assert l == [3]
+
+        l = [0]
+        assert l[1:] == []
+        assert l[1::2] == []
+        l = ['']
+        assert l[1:] == []
+        assert l[1::2] == []
 
     def test_delall(self):
         l = l0 = [1,2,3]
@@ -546,6 +568,11 @@
         c.insert(-2, 'Z')
         assert ''.join(c) == 'XhYello worZld'
 
+        ls = [1,2,3,4,5,6,7]
+        for i in range(5):
+            ls.insert(0, i)
+        assert len(ls) == 12
+
     def test_pop(self):
         c = list('hello world')
         s = ''



More information about the Pypy-commit mailing list