[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