[pypy-svn] r58914 - in pypy/branch/2.5-merge/pypy: interpreter objspace objspace/std objspace/std/test
antocuni at codespeak.net
antocuni at codespeak.net
Fri Oct 10 16:53:15 CEST 2008
Author: antocuni
Date: Fri Oct 10 16:53:15 2008
New Revision: 58914
Modified:
pypy/branch/2.5-merge/pypy/interpreter/baseobjspace.py
pypy/branch/2.5-merge/pypy/objspace/descroperation.py
pypy/branch/2.5-merge/pypy/objspace/reflective.py
pypy/branch/2.5-merge/pypy/objspace/std/builtinshortcut.py
pypy/branch/2.5-merge/pypy/objspace/std/listobject.py
pypy/branch/2.5-merge/pypy/objspace/std/objspace.py
pypy/branch/2.5-merge/pypy/objspace/std/test/test_listmultiobject.py
pypy/branch/2.5-merge/pypy/objspace/std/test/test_listobject.py
pypy/branch/2.5-merge/pypy/objspace/thunk.py
Log:
(arigo, antocuni)
make {get,set,del}slice real multimethods, and implement
list.__{get,set,del}slice__
Modified: pypy/branch/2.5-merge/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/interpreter/baseobjspace.py (original)
+++ pypy/branch/2.5-merge/pypy/interpreter/baseobjspace.py Fri Oct 10 16:53:15 2008
@@ -588,17 +588,6 @@
w_s = self.interned_strings[s] = self.wrap(s)
return w_s
- # support for the deprecated __getslice__, __setslice__, __delslice__
- def getslice(self, w_obj, w_start, w_stop):
- w_slice = self.newslice(w_start, w_stop, self.w_None)
- return self.getitem(w_obj, w_slice)
- def setslice(self, w_obj, w_start, w_stop, w_sequence):
- w_slice = self.newslice(w_start, w_stop, self.w_None)
- self.setitem(w_obj, w_slice, w_sequence)
- def delslice(self, w_obj, w_start, w_stop):
- w_slice = self.newslice(w_start, w_stop, self.w_None)
- self.delitem(w_obj, w_slice)
-
def interpclass_w(space, w_obj):
"""
If w_obj is a wrapped internal interpreter class instance unwrap to it,
@@ -1011,6 +1000,9 @@
('getitem', 'getitem', 2, ['__getitem__']),
('setitem', 'setitem', 3, ['__setitem__']),
('delitem', 'delitem', 2, ['__delitem__']),
+ ('getslice', 'getslice', 3, ['__getslice__']),
+ ('setslice', 'setslice', 4, ['__setslice__']),
+ ('delslice', 'delslice', 3, ['__delslice__']),
('pos', 'pos', 1, ['__pos__']),
('neg', 'neg', 1, ['__neg__']),
('nonzero', 'truth', 1, ['__nonzero__']),
Modified: pypy/branch/2.5-merge/pypy/objspace/descroperation.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/descroperation.py (original)
+++ pypy/branch/2.5-merge/pypy/objspace/descroperation.py Fri Oct 10 16:53:15 2008
@@ -228,6 +228,30 @@
space.wrap("cannot delete items from object"))
return space.get_and_call_function(w_descr, w_obj, w_key)
+ def getslice(space, w_obj, w_start, w_stop):
+ w_descr = space.lookup(w_obj, '__getslice__')
+ if w_descr is None:
+ w_slice = space.newslice(w_start, w_stop, space.w_None)
+ return space.getitem(w_obj, w_slice)
+ w_start, w_stop = old_slice_range(space, w_obj, w_start, w_stop)
+ return space.get_and_call_function(w_descr, w_obj, w_start, w_stop)
+
+ def setslice(space, w_obj, w_start, w_stop, w_sequence):
+ w_descr = space.lookup(w_obj, '__setslice__')
+ if w_descr is None:
+ w_slice = space.newslice(w_start, w_stop, space.w_None)
+ return space.setitem(w_obj, w_slice, w_sequence)
+ w_start, w_stop = old_slice_range(space, w_obj, w_start, w_stop)
+ return space.get_and_call_function(w_descr, w_obj, w_start, w_stop, w_sequence)
+
+ def delslice(space, w_obj, w_start, w_stop):
+ w_descr = space.lookup(w_obj, '__delslice__')
+ if w_descr is None:
+ w_slice = space.newslice(w_start, w_stop, space.w_None)
+ return space.delitem(w_obj, w_slice)
+ w_start, w_stop = old_slice_range(space, w_obj, w_start, w_stop)
+ return space.get_and_call_function(w_descr, w_obj, w_start, w_stop)
+
def pow(space, w_obj1, w_obj2, w_obj3):
w_typ1 = space.type(w_obj1)
w_typ2 = space.type(w_obj2)
@@ -453,6 +477,35 @@
return (space.lookup(w_obj, '__int__') is not None or
space.lookup(w_obj, '__float__') is not None)
+
+
+# what is the maximum value slices can get on CPython?
+# we need to stick to that value, because fake.py etc.
+class Temp:
+ def __getslice__(self, i, j):
+ return j
+slice_max = Temp()[:]
+del Temp
+
+def old_slice_range(space, w_obj, w_start, w_stop):
+ """Only for backward compatibility for __getslice__()&co methods."""
+ if space.is_w(w_start, space.w_None):
+ w_start = space.wrap(0)
+ else:
+ w_start = space.wrap(space.getindex_w(w_start, None))
+ if space.is_true(space.lt(w_start, space.wrap(0))):
+ w_start = space.add(w_start, space.len(w_obj))
+ # NB. the language ref is inconsistent with the new-style class
+ # behavior when w_obj doesn't implement __len__(), so we just
+ # ignore this case.
+ if space.is_w(w_stop, space.w_None):
+ w_stop = space.wrap(slice_max)
+ else:
+ w_stop = space.wrap(space.getindex_w(w_stop, None))
+ if space.is_true(space.lt(w_stop, space.wrap(0))):
+ w_stop = space.add(w_stop, space.len(w_obj))
+ return w_start, w_stop
+
# regular methods def helpers
def _make_binop_impl(symbol, specialnames):
@@ -649,5 +702,3 @@
'ord', 'unichr', 'unicode']:
raise Exception, "missing def for operation %s" % _name
-
-
Modified: pypy/branch/2.5-merge/pypy/objspace/reflective.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/reflective.py (original)
+++ pypy/branch/2.5-merge/pypy/objspace/reflective.py Fri Oct 10 16:53:15 2008
@@ -89,6 +89,14 @@
return parentfn(w_arg1, w_arg2, w_arg3)
finally:
reset_reflective_space(space, w_old_reflectivespace)
+ elif args == 4:
+ def func(self, space, w_arg1, w_arg2, w_arg3, w_arg4):
+ w_old_reflectivespace = get_reflective_space(space)
+ set_reflectivespace(space, self.w_reflectivespace)
+ try:
+ return parentfn(w_arg1, w_arg2, w_arg3, w_arg4)
+ finally:
+ reset_reflective_space(space, w_old_reflectivespace)
else:
raise NotImplementedError
unwrap_spec = ["self", ObjSpace] + [W_Root] * args
Modified: pypy/branch/2.5-merge/pypy/objspace/std/builtinshortcut.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/std/builtinshortcut.py (original)
+++ pypy/branch/2.5-merge/pypy/objspace/std/builtinshortcut.py Fri Oct 10 16:53:15 2008
@@ -22,6 +22,7 @@
'len', 'nonzero', 'repr', 'str', 'hash',
'neg', 'invert', 'index', 'iter', 'next', 'buffer',
'getitem', 'setitem', 'int',
+ 'getslice', 'setslice',
# in-place
'inplace_add', 'inplace_sub', 'inplace_mul', 'inplace_truediv',
'inplace_floordiv', 'inplace_div', 'inplace_mod', 'inplace_pow',
@@ -32,7 +33,8 @@
KNOWN_MISSING = ['getattr', # mostly non-builtins or optimized by CALL_METHOD
'setattr', 'delattr', 'userdel', # mostly for non-builtins
'get', 'set', 'delete', # uncommon (except on functions)
- 'delitem', 'abs', 'hex', 'oct', # rare stuff?
+ 'delitem', 'delslice', # rare stuff?
+ 'abs', 'hex', 'oct', # rare stuff?
'pos', 'divmod', 'cmp', # rare stuff?
'float', 'long', 'coerce', # rare stuff?
]
Modified: pypy/branch/2.5-merge/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/std/listobject.py (original)
+++ pypy/branch/2.5-merge/pypy/objspace/std/listobject.py Fri Oct 10 16:53:15 2008
@@ -80,6 +80,30 @@
start += step
return w_res
+def normalize_slice(space, w_list, w_start, w_stop):
+ start = space.int_w(w_start)
+ stop = space.int_w(w_stop)
+ length = len(w_list.wrappeditems)
+ if start < 0:
+ start = 0
+ if stop > length:
+ stop = length
+ if stop < start:
+ stop = start
+ return start, stop
+
+def getslice__List_ANY_ANY(space, w_list, w_start, w_stop):
+ start, stop = normalize_slice(space, w_list, w_start, w_stop)
+ return W_ListObject(w_list.wrappeditems[start:stop])
+
+def setslice__List_ANY_ANY_ANY(space, w_list, w_start, w_stop, w_sequence):
+ start, stop = normalize_slice(space, w_list, w_start, w_stop)
+ _setitem_slice_helper(space, w_list, start, 1, stop-start, w_sequence)
+
+def delslice__List_ANY_ANY(space, w_list, w_start, w_stop):
+ start, stop = normalize_slice(space, w_list, w_start, w_stop)
+ _delitem_slice_helper(space, w_list, start, 1, stop-start)
+
def contains__List_ANY(space, w_list, w_obj):
# needs to be safe against eq_w() mutating the w_list behind our back
i = 0
@@ -190,38 +214,35 @@
space.wrap("list deletion index out of range"))
return space.w_None
+
def delitem__List_Slice(space, w_list, w_slice):
start, stop, step, slicelength = w_slice.indices4(space,
len(w_list.wrappeditems))
+ _delitem_slice_helper(space, w_list, start, step, slicelength)
+def _delitem_slice_helper(space, w_list, start, step, slicelength):
if slicelength==0:
return
if step < 0:
start = start + step * (slicelength-1)
step = -step
- # stop is invalid
if step == 1:
- _del_slice(w_list, start, start+slicelength)
+ assert start >= 0
+ assert slicelength >= 0
+ del w_list.wrappeditems[start:start+slicelength]
else:
items = w_list.wrappeditems
n = len(items)
-
- recycle = [None] * slicelength
i = start
- # keep a reference to the objects to be removed,
- # preventing side effects during destruction
- recycle[0] = items[i]
-
for discard in range(1, slicelength):
j = i+1
i += step
while j < i:
items[j-discard] = items[j]
j += 1
- recycle[discard] = items[i]
j = i+1
while j < n:
@@ -229,13 +250,7 @@
j += 1
start = n - slicelength
assert start >= 0 # annotator hint
- # XXX allow negative indices in rlist
del items[start:]
- # now we can destruct recycle safely, regardless of
- # side-effects to the list
- del recycle[:]
-
- return space.w_None
def setitem__List_ANY_ANY(space, w_list, w_index, w_any):
idx = get_list_index(space, w_index)
@@ -246,23 +261,25 @@
space.wrap("list index out of range"))
return space.w_None
-def setitem__List_Slice_List(space, w_list, w_slice, w_list2):
- l = w_list2.wrappeditems
- return _setitem_slice_helper(space, w_list, w_slice, l, len(l))
-
def setitem__List_Slice_ANY(space, w_list, w_slice, w_iterable):
- l = space.unpackiterable(w_iterable)
- return _setitem_slice_helper(space, w_list, w_slice, l, len(l))
-
-def _setitem_slice_helper(space, w_list, w_slice, sequence2, len2):
oldsize = len(w_list.wrappeditems)
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):
+ if isinstance(w_iterable, W_ListObject):
+ sequence2 = w_iterable.wrappeditems
+ else:
+ sequence2 = space.unpackiterable(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 = len2 - slicelength
- if delta >= 0:
+ delta = slicelength - len2
+ if delta < 0:
+ delta = -delta
newsize = oldsize + delta
# XXX support this in rlist!
items += [None] * delta
@@ -271,9 +288,10 @@
while i >= lim:
items[i] = items[i-delta]
i -= 1
+ elif start >= 0:
+ del items[start:start+delta]
else:
- # shrinking requires the careful memory management of _del_slice()
- _del_slice(w_list, start, start-delta)
+ assert delta==0
elif len2 != slicelength: # No resize for extended slices
raise OperationError(space.w_ValueError, space.wrap("attempt to "
"assign sequence of size %d to extended slice of size %d" %
@@ -290,14 +308,13 @@
items[start] = sequence2[i]
start -= step
i -= 1
- return space.w_None
+ 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
- return space.w_None
app = gateway.applevel("""
def listrepr(currently_in_repr, l):
@@ -350,26 +367,6 @@
w_list.wrappeditems += space.unpackiterable(w_any)
return space.w_None
-def _del_slice(w_list, ilow, ihigh):
- """ similar to the deletion part of list_ass_slice in CPython """
- items = w_list.wrappeditems
- n = len(items)
- if ilow < 0:
- ilow = 0
- elif ilow > n:
- ilow = n
- if ihigh < ilow:
- ihigh = ilow
- elif ihigh > n:
- ihigh = n
- # keep a reference to the objects to be removed,
- # preventing side effects during destruction
- recycle = items[ilow:ihigh]
- del items[ilow:ihigh]
- # now we can destruct recycle safely, regardless of
- # side-effects to the list
- del recycle[:]
-
# note that the default value will come back wrapped!!!
def list_pop__List_ANY(space, w_list, w_idx=-1):
items = w_list.wrappeditems
Modified: pypy/branch/2.5-merge/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/std/objspace.py (original)
+++ pypy/branch/2.5-merge/pypy/objspace/std/objspace.py Fri Oct 10 16:53:15 2008
@@ -764,33 +764,6 @@
else:
return ObjSpace.call_method(self, w_obj, methname, *arg_w)
- # support for the deprecated __getslice__, __setslice__, __delslice__
-
- def getslice(self, w_obj, w_start, w_stop):
- w_descr = self.lookup(w_obj, '__getslice__')
- if w_descr is not None:
- w_start, w_stop = old_slice_range(self, w_obj, w_start, w_stop)
- return self.get_and_call_function(w_descr, w_obj, w_start, w_stop)
- else:
- return ObjSpace.getslice(self, w_obj, w_start, w_stop)
-
- def setslice(self, w_obj, w_start, w_stop, w_sequence):
- w_descr = self.lookup(w_obj, '__setslice__')
- if w_descr is not None:
- w_start, w_stop = old_slice_range(self, w_obj, w_start, w_stop)
- self.get_and_call_function(w_descr, w_obj, w_start, w_stop,
- w_sequence)
- else:
- ObjSpace.setslice(self, w_obj, w_start, w_stop, w_sequence)
-
- def delslice(self, w_obj, w_start, w_stop):
- w_descr = self.lookup(w_obj, '__delslice__')
- if w_descr is not None:
- w_start, w_stop = old_slice_range(self, w_obj, w_start, w_stop)
- self.get_and_call_function(w_descr, w_obj, w_start, w_stop)
- else:
- ObjSpace.delslice(self, w_obj, w_start, w_stop)
-
def raise_key_error(self, w_key):
e = self.call_function(self.w_KeyError, w_key)
raise OperationError(self.w_KeyError, e)
@@ -820,32 +793,3 @@
del mm
pow.extras['defaults'] = (None,)
-
-
-# what is the maximum value slices can get on CPython?
-# we need to stick to that value, because fake.py etc.
-class Temp:
- def __getslice__(self, i, j):
- return j
-slice_max = Temp()[:]
-del Temp
-
-
-def old_slice_range(space, w_obj, w_start, w_stop):
- """Only for backward compatibility for __getslice__()&co methods."""
- if space.is_w(w_start, space.w_None):
- w_start = space.wrap(0)
- else:
- w_start = space.wrap(space.getindex_w(w_start, None))
- if space.is_true(space.lt(w_start, space.wrap(0))):
- w_start = space.add(w_start, space.len(w_obj))
- # NB. the language ref is inconsistent with the new-style class
- # behavior when w_obj doesn't implement __len__(), so we just
- # ignore this case.
- if space.is_w(w_stop, space.w_None):
- w_stop = space.wrap(slice_max)
- else:
- w_stop = space.wrap(space.getindex_w(w_stop, None))
- if space.is_true(space.lt(w_stop, space.wrap(0))):
- w_stop = space.add(w_stop, space.len(w_obj))
- return w_start, w_stop
Modified: pypy/branch/2.5-merge/pypy/objspace/std/test/test_listmultiobject.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/std/test/test_listmultiobject.py (original)
+++ pypy/branch/2.5-merge/pypy/objspace/std/test/test_listmultiobject.py Fri Oct 10 16:53:15 2008
@@ -39,6 +39,15 @@
# These few here ^ would have failed before, but for good coverage,
# all the list methods etc. should be tested also...
+ def test___getslice__(self):
+ skip("don't care for now")
+
+ def test___setslice__(self):
+ skip("don't care for now")
+
+ def test___delslice__(self):
+ skip("don't care for now")
+
class AppTest_ListMultiObject(BaseAppTest_ListMultiObject):
def setup_class(cls):
BaseAppTest_ListMultiObject.setup_class(cls)
Modified: pypy/branch/2.5-merge/pypy/objspace/std/test/test_listobject.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/std/test/test_listobject.py (original)
+++ pypy/branch/2.5-merge/pypy/objspace/std/test/test_listobject.py Fri Oct 10 16:53:15 2008
@@ -754,3 +754,18 @@
A()
while lst:
keepalive.append(lst[:])
+
+ def test___getslice__(self):
+ l = [1,2,3,4]
+ res = l.__getslice__(0, 2)
+ assert res == [1, 2]
+
+ def test___setslice__(self):
+ l = [1,2,3,4]
+ l.__setslice__(0, 2, [5, 6])
+ assert l == [5, 6, 3, 4]
+
+ def test___delslice__(self):
+ l = [1,2,3,4]
+ l.__delslice__(0, 2)
+ assert l == [3, 4]
Modified: pypy/branch/2.5-merge/pypy/objspace/thunk.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/thunk.py (original)
+++ pypy/branch/2.5-merge/pypy/objspace/thunk.py Fri Oct 10 16:53:15 2008
@@ -193,6 +193,13 @@
w2 = force(space, w2)
w3 = force(space, w3)
return parentfn(w1, w2, w3, *extra)
+ elif nb_args == 4:
+ def proxy(w1, w2, w3, w4, *extra):
+ w1 = force(space, w1)
+ w2 = force(space, w2)
+ w3 = force(space, w3)
+ w4 = force(space, w4)
+ return parentfn(w1, w2, w3, w4, *extra)
else:
raise NotImplementedError("operation %r has arity %d" %
(opname, nb_args))
More information about the Pypy-commit
mailing list