[pypy-commit] pypy default: (lukas, carl) Merged list strategies. This allows the contents of a list to be unboxed. See the blog for more details on it.
alex_gaynor
noreply at buildbot.pypy.org
Thu Nov 24 08:54:45 CET 2011
Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch:
Changeset: r49717:03ac38ea2709
Date: 2011-11-24 01:54 -0600
http://bitbucket.org/pypy/pypy/changeset/03ac38ea2709/
Log: (lukas, carl) Merged list strategies. This allows the contents of a
list to be unboxed. See the blog for more details on it.
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -281,6 +281,9 @@
"actually create the full list until the resulting "
"list is mutated",
default=False),
+ BoolOption("withliststrategies",
+ "enable optimized ways to store lists of primitives ",
+ default=True),
BoolOption("withtypeversion",
"version type objects when changing them",
diff --git a/pypy/doc/config/objspace.std.withliststrategies.txt b/pypy/doc/config/objspace.std.withliststrategies.txt
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/objspace.std.withliststrategies.txt
@@ -0,0 +1,2 @@
+Enable list strategies: Use specialized representations for lists of primitive
+objects, such as ints.
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -262,6 +262,26 @@
documented as such (as e.g. for hasattr()), in most cases PyPy
lets the exception propagate instead.
+Object Identity of Primitive Values, ``is`` and ``id``
+-------------------------------------------------------
+
+Object identity of primitive values works by value equality, not by identity of
+the wrapper. This means that ``x + 1 is x + 1`` is always true, for arbitrary
+integers ``x``. The rule applies for the following types:
+
+ - ``int``
+
+ - ``float``
+
+ - ``long``
+
+ - ``complex``
+
+This change requires some changes to ``id`` as well. ``id`` fulfills the
+following condition: ``x is y <=> id(x) == id(y)``. Therefore ``id`` of the
+above types will return a value that is computed from the argument, and can
+thus be larger than ``sys.maxint`` (i.e. it can be an arbitrary long).
+
Miscellaneous
-------------
@@ -284,14 +304,5 @@
never a dictionary as it sometimes is in CPython. Assigning to
``__builtins__`` has no effect.
-* Do not compare immutable objects with ``is``. For example on CPython
- it is true that ``x is 0`` works, i.e. does the same as ``type(x) is
- int and x == 0``, but it is so by accident. If you do instead
- ``x is 1000``, then it stops working, because 1000 is too large and
- doesn't come from the internal cache. In PyPy it fails to work in
- both cases, because we have no need for a cache at all.
-
-* Also, object identity of immutable keys in dictionaries is not necessarily
- preserved.
.. include:: _ref.txt
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -879,6 +879,16 @@
"""
return self.unpackiterable(w_iterable, expected_length)
+ def listview_str(self, w_list):
+ """ Return a list of unwrapped strings out of a list of strings. If the
+ argument is not a list or does not contain only strings, return None.
+ May return None anyway.
+ """
+ return None
+
+ def newlist_str(self, list_s):
+ return self.newlist([self.wrap(s) for s in list_s])
+
@jit.unroll_safe
def exception_match(self, w_exc_type, w_check_class):
"""Checks if the given exception type matches 'w_check_class'."""
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -1,8 +1,9 @@
+from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.error import OperationError
-from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.gateway import NoneNotWrapped
+from pypy.interpreter.pyopcode import LoopBlock
from pypy.rlib import jit
-from pypy.interpreter.pyopcode import LoopBlock
+from pypy.rlib.objectmodel import specialize
class GeneratorIterator(Wrappable):
@@ -156,38 +157,43 @@
break
block = block.previous
- def unpack_into(self, results_w):
- """This is a hack for performance: runs the generator and collects
- all produced items in a list."""
- # XXX copied and simplified version of send_ex()
- space = self.space
- if self.running:
- raise OperationError(space.w_ValueError,
- space.wrap('generator already executing'))
- frame = self.frame
- if frame is None: # already finished
- return
- self.running = True
- try:
- pycode = self.pycode
- while True:
- jitdriver.jit_merge_point(self=self, frame=frame,
- results_w=results_w,
- pycode=pycode)
- try:
- w_result = frame.execute_frame(space.w_None)
- except OperationError, e:
- if not e.match(space, space.w_StopIteration):
- raise
- break
- # if the frame is now marked as finished, it was RETURNed from
- if frame.frame_finished_execution:
- break
- results_w.append(w_result) # YIELDed
- finally:
- frame.f_backref = jit.vref_None
- self.running = False
- self.frame = None
-
-jitdriver = jit.JitDriver(greens=['pycode'],
- reds=['self', 'frame', 'results_w'])
+ # Results can be either an RPython list of W_Root, or it can be an
+ # app-level W_ListObject, which also has an append() method, that's why we
+ # generate 2 versions of the function and 2 jit drivers.
+ def _create_unpack_into():
+ jitdriver = jit.JitDriver(greens=['pycode'],
+ reds=['self', 'frame', 'results'])
+ def unpack_into(self, results):
+ """This is a hack for performance: runs the generator and collects
+ all produced items in a list."""
+ # XXX copied and simplified version of send_ex()
+ space = self.space
+ if self.running:
+ raise OperationError(space.w_ValueError,
+ space.wrap('generator already executing'))
+ frame = self.frame
+ if frame is None: # already finished
+ return
+ self.running = True
+ try:
+ pycode = self.pycode
+ while True:
+ jitdriver.jit_merge_point(self=self, frame=frame,
+ results=results, pycode=pycode)
+ try:
+ w_result = frame.execute_frame(space.w_None)
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ break
+ # if the frame is now marked as finished, it was RETURNed from
+ if frame.frame_finished_execution:
+ break
+ results.append(w_result) # YIELDed
+ finally:
+ frame.f_backref = jit.vref_None
+ self.running = False
+ self.frame = None
+ return unpack_into
+ unpack_into = _create_unpack_into()
+ unpack_into_w = _create_unpack_into()
\ No newline at end of file
diff --git a/pypy/interpreter/test/test_function.py b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -587,7 +587,7 @@
assert isinstance(meth2, Method)
assert meth2.call_args(args) == obj1
# Check method returned from unbound_method.__get__()
- w_meth3 = descr_function_get(space, func, None, space.type(obj2))
+ w_meth3 = descr_function_get(space, func, space.w_None, space.type(obj2))
meth3 = space.unwrap(w_meth3)
w_meth4 = meth3.descr_method_get(obj2, space.w_None)
meth4 = space.unwrap(w_meth4)
diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -63,10 +63,13 @@
def test_unpackiterable(self):
space = self.space
w = space.wrap
- l = [w(1), w(2), w(3), w(4)]
+ l = [space.newlist([]) for l in range(4)]
w_l = space.newlist(l)
- assert space.unpackiterable(w_l) == l
- assert space.unpackiterable(w_l, 4) == l
+ l1 = space.unpackiterable(w_l)
+ l2 = space.unpackiterable(w_l, 4)
+ for i in range(4):
+ assert space.is_w(l1[i], l[i])
+ assert space.is_w(l2[i], l[i])
err = raises(OperationError, space.unpackiterable, w_l, 3)
assert err.value.match(space, space.w_ValueError)
err = raises(OperationError, space.unpackiterable, w_l, 5)
diff --git a/pypy/jit/metainterp/test/test_tracingopts.py b/pypy/jit/metainterp/test/test_tracingopts.py
--- a/pypy/jit/metainterp/test/test_tracingopts.py
+++ b/pypy/jit/metainterp/test/test_tracingopts.py
@@ -593,6 +593,32 @@
res = self.interp_operations(fn, [sys.maxint])
assert res == 12
+ def test_opaque_list(self):
+ from pypy.rlib.rerased import new_erasing_pair
+ erase, unerase = new_erasing_pair("test_opaque_list")
+ def fn(n, ca, cb):
+ l1 = [n]
+ l2 = [n]
+ a1 = erase(l1)
+ a2 = erase(l1)
+ a = a1
+ if ca:
+ a = a2
+ if n < -100:
+ unerase(a).append(5)
+ b = a1
+ if cb:
+ b = a
+ return unerase(a)[0] + unerase(b)[0]
+ res = self.interp_operations(fn, [7, 0, 1])
+ assert res == 7 * 2
+ self.check_operations_history(getarrayitem_gc=0,
+ getfield_gc=0)
+ res = self.interp_operations(fn, [-7, 1, 1])
+ assert res == -7 * 2
+ self.check_operations_history(getarrayitem_gc=0,
+ getfield_gc=0)
+
def test_copy_str_content(self):
def fn(n):
a = StringBuilder()
@@ -601,4 +627,4 @@
return x[0]
res = self.interp_operations(fn, [0])
assert res == 1
- self.check_operations_history(getarrayitem_gc=0, getarrayitem_gc_pure=0 )
\ No newline at end of file
+ self.check_operations_history(getarrayitem_gc=0, getarrayitem_gc_pure=0)
diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -95,17 +95,17 @@
return space.newlist(res_w)
-def range_withspecialized_implementation(space, start, step, howmany):
+def range_withspecialized_implementation(space, start, step, length):
assert space.config.objspace.std.withrangelist
- from pypy.objspace.std.rangeobject import W_RangeListObject
- return W_RangeListObject(start, step, howmany)
+ from pypy.objspace.std.listobject import make_range_list
+ return make_range_list(space, start, step, length)
bigint_one = rbigint.fromint(1)
def range_with_longs(space, w_start, w_stop, w_step):
start = lo = space.bigint_w(w_start)
- stop = hi = space.bigint_w(w_stop)
+ hi = space.bigint_w(w_stop)
step = st = space.bigint_w(w_step)
if not step.tobool():
diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py
--- a/pypy/module/cpyext/listobject.py
+++ b/pypy/module/cpyext/listobject.py
@@ -32,7 +32,7 @@
Py_DecRef(space, w_item)
if not isinstance(w_list, W_ListObject):
PyErr_BadInternalCall(space)
- wrappeditems = w_list.wrappeditems
+ wrappeditems = w_list.getitems()
if index < 0 or index >= len(wrappeditems):
raise OperationError(space.w_IndexError, space.wrap(
"list assignment index out of range"))
@@ -47,7 +47,7 @@
IndexError exception."""
if not isinstance(w_list, W_ListObject):
PyErr_BadInternalCall(space)
- wrappeditems = w_list.wrappeditems
+ wrappeditems = w_list.getitems()
if index < 0 or index >= len(wrappeditems):
raise OperationError(space.w_IndexError, space.wrap(
"list index out of range"))
@@ -74,7 +74,7 @@
"""Macro form of PyList_Size() without error checking.
"""
assert isinstance(w_list, W_ListObject)
- return len(w_list.wrappeditems)
+ return len(w_list.getitems())
@cpython_api([PyObject], Py_ssize_t, error=-1)
diff --git a/pypy/module/cpyext/sequence.py b/pypy/module/cpyext/sequence.py
--- a/pypy/module/cpyext/sequence.py
+++ b/pypy/module/cpyext/sequence.py
@@ -56,7 +56,7 @@
PySequence_Fast(), o is not NULL, and that i is within bounds.
"""
if isinstance(w_obj, listobject.W_ListObject):
- w_res = w_obj.wrappeditems[index]
+ w_res = w_obj.getitem(index)
else:
assert isinstance(w_obj, tupleobject.W_TupleObject)
w_res = w_obj.wrappeditems[index]
@@ -70,7 +70,7 @@
PySequence_Fast_GET_SIZE() is faster because it can assume o is a list
or tuple."""
if isinstance(w_obj, listobject.W_ListObject):
- return len(w_obj.wrappeditems)
+ return w_obj.length()
assert isinstance(w_obj, tupleobject.W_TupleObject)
return len(w_obj.wrappeditems)
diff --git a/pypy/module/gc/test/test_referents.py b/pypy/module/gc/test/test_referents.py
--- a/pypy/module/gc/test/test_referents.py
+++ b/pypy/module/gc/test/test_referents.py
@@ -7,9 +7,13 @@
from pypy.rlib import rgc
cls._backup = [rgc.get_rpy_roots]
w = cls.space.wrap
+ space = cls.space
class RandomRPythonObject(object):
pass
- cls.ALL_ROOTS = [w(4), w([2, 7]), RandomRPythonObject()]
+ l4 = space.newlist([w(4)])
+ l2 = space.newlist([w(2)])
+ l7 = space.newlist([w(7)])
+ cls.ALL_ROOTS = [l4, space.newlist([l2, l7]), RandomRPythonObject()]
cls.w_ALL_ROOTS = cls.space.newlist(cls.ALL_ROOTS)
rgc.get_rpy_roots = lambda: (
map(rgc._GcRef, cls.ALL_ROOTS) + [rgc.NULL_GCREF]*17)
@@ -41,14 +45,14 @@
if self.runappdirect:
pass # unsure what to test
else:
- assert lst[0] == 4
- assert lst[1] == [2, 7]
+ assert lst[0] == [4]
+ assert lst[1] == [[2], [7]]
assert type(lst[2]) is gc.GcRef
assert len(lst) == 3
def test_get_rpy_referents(self):
import gc
- y = 12345
+ y = [12345]
x = [y]
lst = gc.get_rpy_referents(x)
# After translation, 'lst' should contain the RPython-level list
@@ -88,8 +92,8 @@
def test_get_referents(self):
import gc
- y = 12345
- z = 23456
+ y = [12345]
+ z = [23456]
x = [y, z]
lst = gc.get_referents(x)
assert y in lst and z in lst
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -271,7 +271,7 @@
thread_ticker_check = """
guard_not_invalidated?
ticker0 = getfield_raw(ticker_address, descr=<SignedFieldDescr pypysig_long_struct.c_value .*>)
- ticker1 = int_sub(ticker0, 1)
+ ticker1 = int_sub(ticker0, _)
setfield_raw(ticker_address, ticker1, descr=<SignedFieldDescr pypysig_long_struct.c_value .*>)
ticker_cond0 = int_lt(ticker1, 0)
guard_false(ticker_cond0, descr=...)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -334,26 +334,27 @@
log = self.run(main, [1000])
assert log.result == (1000, 998)
loop, = log.loops_by_filename(self.filepath)
+ # the int strategy is used here
assert loop.match_by_id('append', """
i13 = getfield_gc(p8, descr=<SignedFieldDescr list.length .*>)
i15 = int_add(i13, 1)
# Will be killed by the backend
- i17 = arraylen_gc(p7, descr=<GcPtrArrayDescr>)
- call(ConstClass(_ll_list_resize_ge), p8, i15, descr=<VoidCallDescr>)
+ p15 = getfield_gc(p8, descr=<GcPtrFieldDescr list.items .*>)
+ i17 = arraylen_gc(p15, descr=<SignedArrayDescr>)
+ call(_, p8, i15, descr=<VoidCallDescr>) # this is a call to _ll_list_resize_ge_trampoline__...
guard_no_exception(descr=...)
p17 = getfield_gc(p8, descr=<GcPtrFieldDescr list.items .*>)
- p19 = new_with_vtable(ConstClass(W_IntObject))
- setfield_gc(p19, i12, descr=<SignedFieldDescr .*W_IntObject.inst_intval .*>)
- setarrayitem_gc(p17, i13, p19, descr=<GcPtrArrayDescr>)
+ setarrayitem_gc(p17, i13, i12, descr=<SignedArrayDescr>)
""")
def test_blockstack_virtualizable(self):
def main(n):
from pypyjit import residual_call
+ l = len
i = 0
while i < n:
try:
- residual_call(len, []) # ID: call
+ residual_call(l, []) # ID: call
except:
pass
i += 1
@@ -369,11 +370,8 @@
p22 = new_with_vtable(19511408)
p24 = new_array(1, descr=<GcPtrArrayDescr>)
p26 = new_with_vtable(ConstClass(W_ListObject))
- p27 = new(descr=<SizeDescr .*>)
- p29 = new_array(0, descr=<GcPtrArrayDescr>)
setfield_gc(p0, i20, descr=<SignedFieldDescr .*PyFrame.vable_token .*>)
- setfield_gc(p27, p29, descr=<GcPtrFieldDescr list.items .*>)
- setfield_gc(p26, p27, descr=<.* .*W_ListObject.inst_wrappeditems .*>)
+ setfield_gc(p26, ConstPtr(ptr22), descr=<GcPtrFieldDescr pypy.objspace.std.listobject.W_ListObject.inst_strategy .*>)
setarrayitem_gc(p24, 0, p26, descr=<GcPtrArrayDescr>)
setfield_gc(p22, p24, descr=<GcPtrFieldDescr .*Arguments.inst_arguments_w .*>)
p32 = call_may_force(11376960, p18, p22, descr=<GcPtrCallDescr>)
@@ -486,4 +484,4 @@
i4 = int_add(i0, 1)
--TICK--
jump(..., descr=...)
- """)
\ No newline at end of file
+ """)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_misc.py b/pypy/module/pypyjit/test_pypy_c/test_misc.py
--- a/pypy/module/pypyjit/test_pypy_c/test_misc.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_misc.py
@@ -201,9 +201,11 @@
assert log.result == 1000000
loop, = log.loops_by_filename(self.filepath)
assert loop.match("""
- i16 = int_ge(i12, i13)
+ i14 = getfield_gc(p12, descr=<SignedFieldDescr list.length .*>)
+ i16 = uint_ge(i12, i14)
guard_false(i16, descr=...)
- p17 = getarrayitem_gc(p15, i12, descr=<GcPtrArrayDescr>)
+ p16 = getfield_gc(p12, descr=<GcPtrFieldDescr list.items .*>)
+ p17 = getarrayitem_gc(p16, i12, descr=<GcPtrArrayDescr>)
i19 = int_add(i12, 1)
setfield_gc(p9, i19, descr=<SignedFieldDescr .*W_AbstractSeqIterObject.inst_index .*>)
guard_nonnull_class(p17, 146982464, descr=...)
@@ -217,7 +219,7 @@
i28 = int_add_ovf(i10, i25)
guard_no_overflow(descr=...)
--TICK--
- jump(p0, p1, p2, p3, p4, p5, p6, i28, i25, p9, p10, p11, i19, i13, p14, p15, descr=<Loop0>)
+ jump(p0, p1, p2, p3, p4, p5, p6, i28, i25, p9, p10, p11, p12, i19, descr=<Loop0>)
""")
@@ -337,7 +339,7 @@
a = compile('x+x+x+x+x+x', 'eval', 'eval')
b = {'x': 7}
while i < 1000:
- y = eval(a,b,b) # ID: eval
+ y = eval(a, b, b) # ID: eval
i += 1
return y
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
@@ -9,10 +9,7 @@
from pypy.rlib.debug import check_annotation
from pypy.objspace.std import stringobject
from pypy.objspace.std.intobject import W_IntObject
-from pypy.objspace.std.listobject import (
- _delitem_slice_helper, _setitem_slice_helper,
- get_positive_index
-)
+from pypy.objspace.std.listobject import get_positive_index
from pypy.objspace.std.listtype import get_list_index
from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
from pypy.objspace.std.stringobject import W_StringObject
@@ -600,7 +597,7 @@
oldsize = len(w_bytearray.data)
start, stop, step, slicelength = w_slice.indices4(space, oldsize)
sequence2 = makebytearraydata_w(space, w_other)
- setitem_slice_helper(space, w_bytearray.data, start, step, slicelength, sequence2, empty_elem='\x00')
+ _setitem_slice_helper(space, w_bytearray.data, start, step, slicelength, sequence2, empty_elem='\x00')
def delitem__Bytearray_ANY(space, w_bytearray, w_idx):
idx = get_list_index(space, w_idx)
@@ -614,13 +611,84 @@
def delitem__Bytearray_Slice(space, w_bytearray, w_slice):
start, stop, step, slicelength = w_slice.indices4(space,
len(w_bytearray.data))
- delitem_slice_helper(space, w_bytearray.data, start, step, slicelength)
+ _delitem_slice_helper(space, w_bytearray.data, start, step, slicelength)
-# create new helper functions with different list type specialisation
-delitem_slice_helper = func_with_new_name(_delitem_slice_helper,
- 'delitem_slice_helper')
-setitem_slice_helper = func_with_new_name(_setitem_slice_helper,
- 'setitem_slice_helper')
+#XXX share the code again with the stuff in listobject.py
+def _delitem_slice_helper(space, items, start, step, slicelength):
+ if slicelength==0:
+ return
+
+ if step < 0:
+ start = start + step * (slicelength-1)
+ step = -step
+
+ if step == 1:
+ assert start >= 0
+ assert slicelength >= 0
+ del items[start:start+slicelength]
+ else:
+ n = len(items)
+ i = start
+
+ for discard in range(1, slicelength):
+ j = i+1
+ i += step
+ while j < i:
+ items[j-discard] = items[j]
+ j += 1
+
+ j = i+1
+ while j < n:
+ items[j-slicelength] = items[j]
+ j += 1
+ start = n - slicelength
+ assert start >= 0 # annotator hint
+ del items[start:]
+
+def _setitem_slice_helper(space, items, start, step, slicelength, sequence2,
+ empty_elem):
+ assert slicelength >= 0
+ 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 += [empty_elem] * 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
def _strip(space, w_bytearray, u_chars, left, right):
# note: mostly copied from stringobject._strip
diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py
--- a/pypy/objspace/std/celldict.py
+++ b/pypy/objspace/std/celldict.py
@@ -65,11 +65,11 @@
if isinstance(cell, ModuleCell):
cell.w_value = w_value
return
- # If the new value and the current value are the same, don't create a
- # level of indirection, or mutate are version.
- if self.space.is_w(w_value, cell):
- return
if cell is not None:
+ # If the new value and the current value are the same, don't create a
+ # level of indirection, or mutate the version.
+ if self.space.is_w(w_value, cell):
+ return
w_value = ModuleCell(w_value)
self.mutated()
self.unerase(w_dict.dstorage)[key] = w_value
diff --git a/pypy/objspace/std/frame.py b/pypy/objspace/std/frame.py
--- a/pypy/objspace/std/frame.py
+++ b/pypy/objspace/std/frame.py
@@ -58,7 +58,7 @@
w_1 = f.popvalue()
if type(w_1) is W_ListObject and type(w_2) is intobject.W_IntObject:
try:
- w_result = w_1.wrappeditems[w_2.intval]
+ w_result = w_1.getitem(w_2.intval)
except IndexError:
raise OperationError(f.space.w_IndexError,
f.space.wrap("list index out of range"))
diff --git a/pypy/objspace/std/iterobject.py b/pypy/objspace/std/iterobject.py
--- a/pypy/objspace/std/iterobject.py
+++ b/pypy/objspace/std/iterobject.py
@@ -33,9 +33,9 @@
"""Sequence iterator specialized for lists, accessing
directly their RPython-level list of wrapped objects.
"""
- def __init__(w_self, w_seq, wrappeditems):
+ def __init__(w_self, w_seq):
W_AbstractSeqIterObject.__init__(w_self, w_seq)
- w_self.listitems = wrappeditems
+ w_self.w_seq = w_seq
class W_FastTupleIterObject(W_AbstractSeqIterObject):
"""Sequence iterator specialized for tuples, accessing
@@ -105,13 +105,15 @@
return w_seqiter
def next__FastListIter(space, w_seqiter):
- if w_seqiter.listitems is None:
+ from pypy.objspace.std.listobject import W_ListObject
+ w_seq = w_seqiter.w_seq
+ if w_seq is None:
raise OperationError(space.w_StopIteration, space.w_None)
+ assert isinstance(w_seq, W_ListObject)
index = w_seqiter.index
try:
- w_item = w_seqiter.listitems[index]
+ w_item = w_seq.getitem(index)
except IndexError:
- w_seqiter.listitems = None
w_seqiter.w_seq = None
raise OperationError(space.w_StopIteration, space.w_None)
w_seqiter.index = index + 1
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
@@ -5,35 +5,937 @@
from pypy.objspace.std.inttype import wrapint
from pypy.objspace.std.listtype import get_list_index
from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
-
from pypy.objspace.std import slicetype
from pypy.interpreter import gateway, baseobjspace
+from pypy.rlib.objectmodel import instantiate, specialize
from pypy.rlib.listsort import make_timsort_class
+from pypy.rlib import rerased, jit
from pypy.interpreter.argument import Signature
+UNROLL_CUTOFF = 5
+
class W_AbstractListObject(W_Object):
__slots__ = ()
+def make_range_list(space, start, step, length):
+ if length <= 0:
+ strategy = space.fromcache(EmptyListStrategy)
+ storage = strategy.erase(None)
+ else:
+ strategy = space.fromcache(RangeListStrategy)
+ storage = strategy.erase((start, step, length))
+ return W_ListObject.from_storage_and_strategy(space, storage, strategy)
+
+def make_empty_list(space):
+ strategy = space.fromcache(EmptyListStrategy)
+ storage = strategy.erase(None)
+ return W_ListObject.from_storage_and_strategy(space, storage, strategy)
+
+ at jit.look_inside_iff(lambda space, list_w: jit.isconstant(len(list_w)) and len(list_w) < UNROLL_CUTOFF)
+def get_strategy_from_list_objects(space, list_w):
+ if not list_w:
+ return space.fromcache(EmptyListStrategy)
+
+ # check for ints
+ for w_obj in list_w:
+ if not is_W_IntObject(w_obj):
+ break
+ else:
+ return space.fromcache(IntegerListStrategy)
+
+ # check for strings
+ for w_obj in list_w:
+ if not is_W_StringObject(w_obj):
+ break
+ else:
+ return space.fromcache(StringListStrategy)
+
+ return space.fromcache(ObjectListStrategy)
+
+def is_W_IntObject(w_object):
+ from pypy.objspace.std.intobject import W_IntObject
+ return type(w_object) is W_IntObject
+
+def is_W_StringObject(w_object):
+ from pypy.objspace.std.stringobject import W_StringObject
+ return type(w_object) is W_StringObject
+
+
+
class W_ListObject(W_AbstractListObject):
from pypy.objspace.std.listtype import list_typedef as typedef
- def __init__(w_self, wrappeditems):
- w_self.wrappeditems = wrappeditems
+ def __init__(w_self, space, wrappeditems):
+ assert isinstance(wrappeditems, list)
+ w_self.space = space
+ if space.config.objspace.std.withliststrategies:
+ w_self.strategy = get_strategy_from_list_objects(space, wrappeditems)
+ else:
+ w_self.strategy = space.fromcache(ObjectListStrategy)
+ w_self.init_from_list_w(wrappeditems)
+
+ @staticmethod
+ def from_storage_and_strategy(space, storage, strategy):
+ w_self = instantiate(W_ListObject)
+ w_self.space = space
+ w_self.strategy = strategy
+ w_self.lstorage = storage
+ if not space.config.objspace.std.withliststrategies:
+ w_self.switch_to_object_strategy()
+ return w_self
+
+ @staticmethod
+ def newlist_str(space, list_s):
+ strategy = space.fromcache(StringListStrategy)
+ storage = strategy.erase(list_s)
+ return W_ListObject.from_storage_and_strategy(space, storage, strategy)
def __repr__(w_self):
""" representation for debugging purposes """
- return "%s(%s)" % (w_self.__class__.__name__, w_self.wrappeditems)
+ return "%s(%s, %s)" % (w_self.__class__.__name__, w_self.strategy, w_self.lstorage._x)
def unwrap(w_list, space):
- items = [space.unwrap(w_item) for w_item in w_list.wrappeditems]# XXX generic mixed types unwrap
+ # for tests only!
+ items = [space.unwrap(w_item) for w_item in w_list.getitems()]
return list(items)
+ def switch_to_object_strategy(self):
+ list_w = self.getitems()
+ self.strategy = self.space.fromcache(ObjectListStrategy)
+ # XXX this is quite indirect
+ self.init_from_list_w(list_w)
+
+ def _temporarily_as_objects(self):
+ if self.strategy is self.space.fromcache(ObjectListStrategy):
+ return self
+ list_w = self.getitems()
+ strategy = self.space.fromcache(ObjectListStrategy)
+ storage = strategy.erase(list_w)
+ w_objectlist = W_ListObject.from_storage_and_strategy(self.space, storage, strategy)
+ return w_objectlist
+
+ # ___________________________________________________
+
+ def init_from_list_w(self, list_w):
+ """Initializes listobject by iterating through the given list of
+ wrapped items, unwrapping them if neccessary and creating a
+ new erased object as storage"""
+ self.strategy.init_from_list_w(self, list_w)
+
+ def clone(self):
+ """Returns a clone by creating a new listobject
+ with the same strategy and a copy of the storage"""
+ return self.strategy.clone(self)
+
+ def copy_into(self, other):
+ """Used only when extending an EmptyList. Sets the EmptyLists
+ strategy and storage according to the other W_List"""
+ self.strategy.copy_into(self, other)
+
+ def contains(self, w_obj):
+ """Returns unwrapped boolean, saying wether w_obj exists
+ in the list."""
+ return self.strategy.contains(self, w_obj)
+
def append(w_list, w_item):
- w_list.wrappeditems.append(w_item)
+ """Appends the wrapped item to the end of the list."""
+ w_list.strategy.append(w_list, w_item)
+
+ def length(self):
+ return self.strategy.length(self)
+
+ def getitem(self, index):
+ """Returns the wrapped object that is found in the
+ list at the given index. The index must be unwrapped.
+ May raise IndexError."""
+ return self.strategy.getitem(self, index)
+
+ def getslice(self, start, stop, step, length):
+ """Returns a slice of the list defined by the arguments. Arguments must be
+ normalized (i.e. using normalize_simple_slice or W_Slice.indices4).
+ May raise IndexError."""
+ return self.strategy.getslice(self, start, stop, step, length)
+
+ def getitems(self):
+ """Returns a list of all items after wrapping them. The result can
+ share with the storage, if possible."""
+ return self.strategy.getitems(self)
+
+ def getitems_copy(self):
+ """Returns a copy of all items in the list. Same as getitems except for
+ ObjectListStrategy."""
+ return self.strategy.getitems_copy(self)
+
+ def getitems_str(self):
+ """ Return the items in the list as unwrapped strings. If the list does
+ not use the list strategy, return None. """
+ return self.strategy.getitems_str(self)
+ # ___________________________________________________
+
+
+ def mul(self, times):
+ """Returns a copy of the list, multiplied by times.
+ Argument must be unwrapped."""
+ return self.strategy.mul(self, times)
+
+ def inplace_mul(self, times):
+ """Alters the list by multiplying its content by times."""
+ self.strategy.inplace_mul(self, times)
+
+ def deleteslice(self, start, step, length):
+ """Deletes a slice from the list. Used in delitem and delslice.
+ Arguments must be normalized (see getslice)."""
+ self.strategy.deleteslice(self, start, step, length)
+
+ def pop(self, index):
+ """Pops an item from the list. Index must be normalized.
+ May raise IndexError."""
+ return self.strategy.pop(self, index)
+
+ def pop_end(self):
+ """ Pop the last element from the list."""
+ return self.strategy.pop_end(self)
+
+ def setitem(self, index, w_item):
+ """Inserts a wrapped item at the given (unwrapped) index.
+ May raise IndexError."""
+ self.strategy.setitem(self, index, w_item)
+
+ def setslice(self, start, step, slicelength, sequence_w):
+ """Sets the slice of the list from start to start+step*slicelength to
+ the sequence sequence_w.
+ Used by setslice and setitem."""
+ self.strategy.setslice(self, start, step, slicelength, sequence_w)
+
+ def insert(self, index, w_item):
+ """Inserts an item at the given position. Item must be wrapped,
+ index not."""
+ self.strategy.insert(self, index, w_item)
+
+ def extend(self, items_w):
+ """Appends the given list of wrapped items."""
+ self.strategy.extend(self, items_w)
+
+ def reverse(self):
+ """Reverses the list."""
+ self.strategy.reverse(self)
+
+ def sort(self, reverse):
+ """Sorts the list ascending or descending depending on
+ argument reverse. Argument must be unwrapped."""
+ self.strategy.sort(self, reverse)
registerimplementation(W_ListObject)
+class ListStrategy(object):
+
+ def __init__(self, space):
+ self.space = space
+
+ def init_from_list_w(self, w_list, list_w):
+ raise NotImplementedError
+
+ def clone(self, w_list):
+ raise NotImplementedError
+
+ def copy_into(self, w_list, w_other):
+ raise NotImplementedError
+
+ def contains(self, w_list, w_obj):
+ # needs to be safe against eq_w() mutating the w_list behind our back
+ i = 0
+ while i < w_list.length(): # intentionally always calling len!
+ if self.space.eq_w(w_list.getitem(i), w_obj):
+ return True
+ i += 1
+ return False
+
+ def length(self, w_list):
+ raise NotImplementedError
+
+ def getitem(self, w_list, index):
+ raise NotImplementedError
+
+ def getslice(self, w_list, start, stop, step, length):
+ raise NotImplementedError
+
+ def getitems(self, w_list):
+ return self.getitems_copy(w_list)
+
+ def getitems_copy(self, w_list):
+ raise NotImplementedError
+
+ def getitems_str(self, w_list):
+ return None
+
+ def getstorage_copy(self, w_list):
+ raise NotImplementedError
+
+ def append(self, w_list, w_item):
+ raise NotImplementedError
+
+ def mul(self, w_list, times):
+ w_newlist = w_list.clone()
+ w_newlist.inplace_mul(times)
+ return w_newlist
+
+ def inplace_mul(self, w_list, times):
+ raise NotImplementedError
+
+ def deleteslice(self, w_list, start, step, slicelength):
+ raise NotImplementedError
+
+ def pop(self, w_list, index):
+ raise NotImplementedError
+
+ def pop_end(self, w_list):
+ return self.pop(w_list, self.length(w_list) - 1)
+
+ 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
+
+ def extend(self, w_list, items_w):
+ raise NotImplementedError
+
+ def reverse(self, w_list):
+ raise NotImplementedError
+
+ def sort(self, w_list, reverse):
+ raise NotImplementedError
+
+class EmptyListStrategy(ListStrategy):
+ """EmptyListStrategy is used when a W_List withouth elements is created.
+ The storage is None. When items are added to the W_List a new RPython list
+ is created and the strategy and storage of the W_List are changed depending
+ to the added item.
+ W_Lists do not switch back to EmptyListStrategy when becoming empty again."""
+
+ def __init__(self, space):
+ ListStrategy.__init__(self, space)
+ # cache an empty list that is used whenever getitems is called (i.e. sorting)
+ self.cached_emptylist_w = []
+
+ def init_from_list_w(self, w_list, list_w):
+ assert len(list_w) == 0
+ w_list.lstorage = self.erase(None)
+
+ erase, unerase = rerased.new_erasing_pair("empty")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def clone(self, w_list):
+ return W_ListObject.from_storage_and_strategy(self.space, w_list.lstorage, self)
+
+ def copy_into(self, w_list, w_other):
+ pass
+
+ def contains(self, w_list, w_obj):
+ return False
+
+ def length(self, w_list):
+ return 0
+
+ def getitem(self, w_list, index):
+ raise IndexError
+
+ def getslice(self, w_list, start, stop, step, length):
+ # will never be called because the empty list case is already caught in
+ # getslice__List_ANY_ANY and getitem__List_Slice
+ return W_ListObject(self.space, self.cached_emptylist_w)
+
+ def getitems(self, w_list):
+ return self.cached_emptylist_w
+
+ def getitems_copy(self, w_list):
+ return []
+
+ def getstorage_copy(self, w_list):
+ return self.erase(None)
+
+ def switch_to_correct_strategy(self, w_list, w_item):
+ if is_W_IntObject(w_item):
+ strategy = self.space.fromcache(IntegerListStrategy)
+ elif is_W_StringObject(w_item):
+ strategy = self.space.fromcache(StringListStrategy)
+ else:
+ strategy = self.space.fromcache(ObjectListStrategy)
+
+ storage = strategy.get_empty_storage()
+ w_list.strategy = strategy
+ w_list.lstorage = storage
+
+ def append(self, w_list, w_item):
+ self.switch_to_correct_strategy(w_list, w_item)
+ w_list.append(w_item)
+
+ def inplace_mul(self, w_list, times):
+ return
+
+ def deleteslice(self, w_list, start, step, slicelength):
+ pass
+
+ def pop(self, w_list, index):
+ # will not be called because IndexError was already raised in
+ # list_pop__List_ANY
+ raise IndexError
+
+ def setitem(self, w_list, index, w_item):
+ raise IndexError
+
+ def setslice(self, w_list, start, step, slicelength, w_other):
+ strategy = w_other.strategy
+ storage = strategy.getstorage_copy(w_other)
+ w_list.strategy = strategy
+ w_list.lstorage = storage
+
+ def sort(self, w_list, reverse):
+ return
+
+ def insert(self, w_list, index, w_item):
+ assert index == 0
+ self.append(w_list, w_item)
+
+ def extend(self, w_list, w_other):
+ w_other.copy_into(w_list)
+
+ def reverse(self, w_list):
+ pass
+
+class RangeListStrategy(ListStrategy):
+ """RangeListStrategy is used when a list is created using the range method.
+ The storage is a tuple containing only three integers start, step and length
+ and elements are calculated based on these values.
+ On any operation destroying the range (inserting, appending non-ints)
+ the strategy is switched to IntegerListStrategy."""
+
+ def switch_to_integer_strategy(self, w_list):
+ items = self._getitems_range(w_list, False)
+ strategy = w_list.strategy = self.space.fromcache(IntegerListStrategy)
+ w_list.lstorage = strategy.erase(items)
+
+ def wrap(self, intval):
+ return self.space.wrap(intval)
+
+ def unwrap(self, w_int):
+ return self.space.int_w(w_int)
+
+ def init_from_list_w(self, w_list, list_w):
+ raise NotImplementedError
+
+ erase, unerase = rerased.new_erasing_pair("range")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def clone(self, w_list):
+ storage = w_list.lstorage # lstorage is tuple, no need to clone
+ w_clone = W_ListObject.from_storage_and_strategy(self.space, storage, self)
+ return w_clone
+
+ def copy_into(self, w_list, w_other):
+ w_other.strategy = self
+ w_other.lstorage = w_list.lstorage
+
+ def contains(self, w_list, w_obj):
+ if is_W_IntObject(w_obj):
+ start, step, length = self.unerase(w_list.lstorage)
+ obj = self.unwrap(w_obj)
+ i = start
+ if step > 0 and start <= obj <= start + (length - 1) * step and (start - obj) % step == 0:
+ return True
+ elif step < 0 and start + (length -1) * step <= obj <= start and (start - obj) % step == 0:
+ return True
+ else:
+ return False
+ return ListStrategy.contains(self, w_list, w_obj)
+
+ def length(self, w_list):
+ return self.unerase(w_list.lstorage)[2]
+
+ def _getitem_unwrapped(self, w_list, i):
+ v = self.unerase(w_list.lstorage)
+ start = v[0]
+ step = v[1]
+ length = v[2]
+ if i < 0:
+ i += length
+ if i < 0:
+ raise IndexError
+ elif i >= length:
+ raise IndexError
+ return start + i * step
+
+ def getitem(self, w_list, i):
+ return self.wrap(self._getitem_unwrapped(w_list, i))
+
+ def getitems_copy(self, w_list):
+ return self._getitems_range(w_list, True)
+
+ def getstorage_copy(self, w_list):
+ # tuple is unmutable
+ return w_list.lstorage
+
+
+ @specialize.arg(2)
+ def _getitems_range(self, w_list, wrap_items):
+ l = self.unerase(w_list.lstorage)
+ start = l[0]
+ step = l[1]
+ length = l[2]
+ if wrap_items:
+ r = [None] * length
+ else:
+ r = [0] * length
+ i = start
+ n = 0
+ while n < length:
+ if wrap_items:
+ r[n] = self.wrap(i)
+ else:
+ r[n] = i
+ i += step
+ n += 1
+
+ return r
+
+ def getslice(self, w_list, start, stop, step, length):
+ v = self.unerase(w_list.lstorage)
+ old_start = v[0]
+ old_step = v[1]
+ old_length = v[2]
+
+ new_start = self._getitem_unwrapped(w_list, start)
+ new_step = old_step * step
+ return make_range_list(self.space, new_start, new_step, length)
+
+ def append(self, w_list, w_item):
+ if is_W_IntObject(w_item):
+ l = self.unerase(w_list.lstorage)
+ step = l[1]
+ last_in_range = self._getitem_unwrapped(w_list, -1)
+ if self.unwrap(w_item) - step == last_in_range:
+ new = self.erase((l[0],l[1],l[2]+1))
+ w_list.lstorage = new
+ return
+
+ self.switch_to_integer_strategy(w_list)
+ else:
+ w_list.switch_to_object_strategy()
+ w_list.append(w_item)
+
+ def inplace_mul(self, w_list, times):
+ self.switch_to_integer_strategy(w_list)
+ w_list.inplace_mul(times)
+
+ def deleteslice(self, w_list, start, step, slicelength):
+ self.switch_to_integer_strategy(w_list)
+ w_list.deleteslice(start, step, slicelength)
+
+ def pop_end(self, w_list):
+ start, step, length = self.unerase(w_list.lstorage)
+ w_result = self.wrap(start + (length - 1) * step)
+ new = self.erase((start, step, length - 1))
+ w_list.lstorage = new
+ return w_result
+
+ def pop(self, w_list, index):
+ l = self.unerase(w_list.lstorage)
+ start = l[0]
+ step = l[1]
+ length = l[2]
+ if index == 0:
+ w_result = self.wrap(start)
+ new = self.erase((start + step, step, length - 1))
+ w_list.lstorage = new
+ return w_result
+ elif index == length - 1:
+ return self.pop_end(w_list)
+ else:
+ self.switch_to_integer_strategy(w_list)
+ return w_list.pop(index)
+
+ def setitem(self, w_list, index, w_item):
+ self.switch_to_integer_strategy(w_list)
+ w_list.setitem(index, w_item)
+
+ def setslice(self, w_list, start, step, slicelength, sequence_w):
+ self.switch_to_integer_strategy(w_list)
+ w_list.setslice(start, step, slicelength, sequence_w)
+
+ def sort(self, w_list, reverse):
+ start, step, length = self.unerase(w_list.lstorage)
+ if step > 0 and reverse or step < 0 and not reverse:
+ start = start + step * (length - 1)
+ step = step * (-1)
+ else:
+ return
+ w_list.lstorage = self.erase((start, step, length))
+
+ def insert(self, w_list, index, w_item):
+ self.switch_to_integer_strategy(w_list)
+ w_list.insert(index, w_item)
+
+ def extend(self, w_list, items_w):
+ self.switch_to_integer_strategy(w_list)
+ w_list.extend(items_w)
+
+ def reverse(self, w_list):
+ v = self.unerase(w_list.lstorage)
+ last = self._getitem_unwrapped(w_list, -1)
+ length = v[2]
+ skip = v[1]
+ new = self.erase((last, -skip, length))
+ w_list.lstorage = new
+
+class AbstractUnwrappedStrategy(object):
+ _mixin_ = True
+
+ def wrap(self, unwrapped):
+ raise NotImplementedError
+
+ def unwrap(self, wrapped):
+ raise NotImplementedError
+
+ @staticmethod
+ def unerase(storage):
+ raise NotImplementedError("abstract base class")
+
+ @staticmethod
+ def erase(obj):
+ raise NotImplementedError("abstract base class")
+
+ def is_correct_type(self, w_obj):
+ raise NotImplementedError("abstract base class")
+
+ def list_is_correct_type(self, w_list):
+ raise NotImplementedError("abstract base class")
+
+ @jit.look_inside_iff(lambda space, w_list, list_w:
+ jit.isconstant(len(list_w)) and len(list_w) < UNROLL_CUTOFF)
+ def init_from_list_w(self, w_list, list_w):
+ l = [self.unwrap(w_item) for w_item in list_w]
+ w_list.lstorage = self.erase(l)
+
+ def get_empty_storage(self):
+ return self.erase([])
+
+ def clone(self, w_list):
+ l = self.unerase(w_list.lstorage)
+ storage = self.erase(l[:])
+ w_clone = W_ListObject.from_storage_and_strategy(self.space, storage, self)
+ return w_clone
+
+ def copy_into(self, w_list, w_other):
+ w_other.strategy = self
+ items = self.unerase(w_list.lstorage)[:]
+ w_other.lstorage = self.erase(items)
+
+ def contains(self, w_list, w_obj):
+ if self.is_correct_type(w_obj):
+ obj = self.unwrap(w_obj)
+ l = self.unerase(w_list.lstorage)
+ for i in l:
+ if i == obj:
+ return True
+ return ListStrategy.contains(self, w_list, w_obj)
+
+ def length(self, w_list):
+ return len(self.unerase(w_list.lstorage))
+
+ def getitem(self, w_list, index):
+ l = self.unerase(w_list.lstorage)
+ try:
+ r = l[index]
+ except IndexError: # make RPython raise the exception
+ raise
+ return self.wrap(r)
+
+ @jit.look_inside_iff(lambda self, w_list:
+ jit.isconstant(w_list.length()) and w_list.length() < UNROLL_CUTOFF)
+ def getitems_copy(self, w_list):
+ return [self.wrap(item) for item in self.unerase(w_list.lstorage)]
+
+ def getstorage_copy(self, w_list):
+ items = self.unerase(w_list.lstorage)[:]
+ return self.erase(items)
+
+
+ def getslice(self, w_list, start, stop, step, length):
+ if step == 1 and 0 <= start <= stop:
+ l = self.unerase(w_list.lstorage)
+ assert start >= 0
+ assert stop >= 0
+ sublist = l[start:stop]
+ storage = self.erase(sublist)
+ return W_ListObject.from_storage_and_strategy(self.space, storage, self)
+ else:
+ subitems_w = [self._none_value] * length
+ l = self.unerase(w_list.lstorage)
+ for i in range(length):
+ try:
+ subitems_w[i] = l[start]
+ start += step
+ except IndexError:
+ raise
+ storage = self.erase(subitems_w)
+ return W_ListObject.from_storage_and_strategy(self.space, storage, self)
+
+ def append(self, w_list, w_item):
+
+ if self.is_correct_type(w_item):
+ self.unerase(w_list.lstorage).append(self.unwrap(w_item))
+ return
+
+ w_list.switch_to_object_strategy()
+ w_list.append(w_item)
+
+ def insert(self, w_list, index, w_item):
+ l = self.unerase(w_list.lstorage)
+
+ if self.is_correct_type(w_item):
+ l.insert(index, self.unwrap(w_item))
+ return
+
+ w_list.switch_to_object_strategy()
+ w_list.insert(index, w_item)
+
+ def extend(self, w_list, w_other):
+ l = self.unerase(w_list.lstorage)
+ if self.list_is_correct_type(w_other):
+ l += self.unerase(w_other.lstorage)
+ return
+ elif w_other.strategy is self.space.fromcache(EmptyListStrategy):
+ return
+
+ w_other = w_other._temporarily_as_objects()
+ w_list.switch_to_object_strategy()
+ w_list.extend(w_other)
+
+ def setitem(self, w_list, index, w_item):
+ l = self.unerase(w_list.lstorage)
+
+ if self.is_correct_type(w_item):
+ try:
+ l[index] = self.unwrap(w_item)
+ except IndexError:
+ raise
+ return
+
+ w_list.switch_to_object_strategy()
+ w_list.setitem(index, w_item)
+
+ def setslice(self, w_list, start, step, slicelength, w_other):
+ assert slicelength >= 0
+ items = self.unerase(w_list.lstorage)
+
+ if self is self.space.fromcache(ObjectListStrategy):
+ w_other = w_other._temporarily_as_objects()
+ elif (not self.list_is_correct_type(w_other) and
+ w_other.length() != 0):
+ w_list.switch_to_object_strategy()
+ w_other_as_object = w_other._temporarily_as_objects()
+ assert w_other_as_object.strategy is self.space.fromcache(ObjectListStrategy)
+ w_list.setslice(start, step, slicelength, w_other_as_object)
+ return
+
+ oldsize = len(items)
+ len2 = w_other.length()
+ 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 += [self._none_value] * 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(self.space.w_ValueError, "attempt to "
+ "assign sequence of size %d to extended slice of size %d",
+ len2, slicelength)
+
+ if w_other.strategy is self.space.fromcache(EmptyListStrategy):
+ other_items = []
+ else:
+ # at this point both w_list and w_other have the same type, so
+ # self.unerase is valid for both of them
+ other_items = self.unerase(w_other.lstorage)
+ if other_items 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] = other_items[i]
+ start -= step
+ i -= 1
+ return
+ else:
+ # Make a shallow copy to more easily handle the reversal case
+ w_list.reverse()
+ return
+ #other_items = list(other_items)
+ for i in range(len2):
+ items[start] = other_items[i]
+ start += step
+
+ def deleteslice(self, w_list, start, step, slicelength):
+ items = self.unerase(w_list.lstorage)
+ if slicelength==0:
+ return
+
+ if step < 0:
+ start = start + step * (slicelength-1)
+ step = -step
+
+ if step == 1:
+ assert start >= 0
+ assert slicelength >= 0
+ del items[start:start+slicelength]
+ else:
+ n = len(items)
+ i = start
+
+ for discard in range(1, slicelength):
+ j = i+1
+ i += step
+ while j < i:
+ items[j-discard] = items[j]
+ j += 1
+
+ j = i+1
+ while j < n:
+ items[j-slicelength] = items[j]
+ j += 1
+ start = n - slicelength
+ assert start >= 0 # annotator hint
+ del items[start:]
+
+ def pop_end(self, w_list):
+ l = self.unerase(w_list.lstorage)
+ return self.wrap(l.pop())
+
+ def pop(self, w_list, index):
+ l = self.unerase(w_list.lstorage)
+ # not sure if RPython raises IndexError on pop
+ # so check again here
+ if index < 0:
+ raise IndexError
+ try:
+ item = l.pop(index)
+ except IndexError:
+ raise
+
+ w_item = self.wrap(item)
+ return w_item
+
+ def inplace_mul(self, w_list, times):
+ l = self.unerase(w_list.lstorage)
+ l *= times
+
+ def reverse(self, w_list):
+ self.unerase(w_list.lstorage).reverse()
+
+class ObjectListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+ _none_value = None
+
+ def unwrap(self, w_obj):
+ return w_obj
+
+ def wrap(self, item):
+ return item
+
+ erase, unerase = rerased.new_erasing_pair("object")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def is_correct_type(self, w_obj):
+ return True
+
+ def list_is_correct_type(self, w_list):
+ return w_list.strategy is self.space.fromcache(ObjectListStrategy)
+
+ def init_from_list_w(self, w_list, list_w):
+ w_list.lstorage = self.erase(list_w)
+
+ def contains(self, w_list, w_obj):
+ return ListStrategy.contains(self, w_list, w_obj)
+
+ def getitems(self, w_list):
+ return self.unerase(w_list.lstorage)
+
+class IntegerListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+ _none_value = 0
+
+ def wrap(self, intval):
+ return self.space.wrap(intval)
+
+ def unwrap(self, w_int):
+ return self.space.int_w(w_int)
+
+ erase, unerase = rerased.new_erasing_pair("integer")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def is_correct_type(self, w_obj):
+ return is_W_IntObject(w_obj)
+
+ def list_is_correct_type(self, w_list):
+ return w_list.strategy is self.space.fromcache(IntegerListStrategy)
+
+ def sort(self, w_list, reverse):
+ l = self.unerase(w_list.lstorage)
+ sorter = IntSort(l, len(l))
+ sorter.sort()
+ if reverse:
+ l.reverse()
+
+class StringListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+ _none_value = None
+
+ def wrap(self, stringval):
+ return self.space.wrap(stringval)
+
+ def unwrap(self, w_string):
+ return self.space.str_w(w_string)
+
+ erase, unerase = rerased.new_erasing_pair("string")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def is_correct_type(self, w_obj):
+ return is_W_StringObject(w_obj)
+
+ def list_is_correct_type(self, w_list):
+ return w_list.strategy is self.space.fromcache(StringListStrategy)
+
+ def sort(self, w_list, reverse):
+ l = self.unerase(w_list.lstorage)
+ sorter = StringSort(l, len(l))
+ sorter.sort()
+ if reverse:
+ l.reverse()
+
+ def getitems_str(self, w_list):
+ return self.unerase(w_list.lstorage)
+
+# _______________________________________________________
+
init_signature = Signature(['sequence'], None, None)
init_defaults = [None]
@@ -42,25 +944,24 @@
# this is on the silly side
w_iterable, = __args__.parse_obj(
None, 'list', init_signature, init_defaults)
- items_w = w_list.wrappeditems
- del items_w[:]
+ w_list.__init__(space, [])
if w_iterable is not None:
# unfortunately this is duplicating space.unpackiterable to avoid
# assigning a new RPython list to 'wrappeditems', which defeats the
# W_FastListIterObject optimization.
if isinstance(w_iterable, W_ListObject):
- items_w.extend(w_iterable.wrappeditems)
+ w_list.extend(w_iterable)
elif isinstance(w_iterable, W_TupleObject):
- items_w.extend(w_iterable.wrappeditems)
+ w_list.extend(W_ListObject(space, w_iterable.wrappeditems[:]))
else:
- _init_from_iterable(space, items_w, w_iterable)
+ _init_from_iterable(space, w_list, w_iterable)
-def _init_from_iterable(space, items_w, w_iterable):
+def _init_from_iterable(space, w_list, w_iterable):
# in its own function to make the JIT look into init__List
# xxx special hack for speed
from pypy.interpreter.generator import GeneratorIterator
if isinstance(w_iterable, GeneratorIterator):
- w_iterable.unpack_into(items_w)
+ w_iterable.unpack_into_w(w_list)
return
# /xxx
w_iterator = space.iter(w_iterable)
@@ -71,70 +972,65 @@
if not e.match(space, space.w_StopIteration):
raise
break # done
- items_w.append(w_item)
+ w_list.append(w_item)
def len__List(space, w_list):
- result = len(w_list.wrappeditems)
+ result = w_list.length()
return wrapint(space, result)
def getitem__List_ANY(space, w_list, w_index):
try:
- return w_list.wrappeditems[get_list_index(space, w_index)]
+ return w_list.getitem(get_list_index(space, w_index))
except IndexError:
raise OperationError(space.w_IndexError,
space.wrap("list index out of range"))
def getitem__List_Slice(space, w_list, w_slice):
# XXX consider to extend rlist's functionality?
- length = len(w_list.wrappeditems)
+ length = w_list.length()
start, stop, step, slicelength = w_slice.indices4(space, length)
assert slicelength >= 0
- if step == 1 and 0 <= start <= stop:
- return W_ListObject(w_list.wrappeditems[start:stop])
- w_res = W_ListObject([None] * slicelength)
- items_w = w_list.wrappeditems
- subitems_w = w_res.wrappeditems
- for i in range(slicelength):
- subitems_w[i] = items_w[start]
- start += step
- return w_res
+ if slicelength == 0:
+ return make_empty_list(space)
+ return w_list.getslice(start, stop, step, slicelength)
def getslice__List_ANY_ANY(space, w_list, w_start, w_stop):
- length = len(w_list.wrappeditems)
- start, stop = normalize_simple_slice(space, length, 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):
- length = len(w_list.wrappeditems)
+ length = w_list.length()
start, stop = normalize_simple_slice(space, length, w_start, w_stop)
- sequence2 = space.listview(w_sequence)
- items = w_list.wrappeditems
- _setitem_slice_helper(space, items, start, 1, stop-start, sequence2,
- empty_elem=None)
+ slicelength = stop - start
+ if slicelength == 0:
+ return make_empty_list(space)
+ return w_list.getslice(start, stop, 1, stop - start)
+
+def setslice__List_ANY_ANY_List(space, w_list, w_start, w_stop, w_other):
+ length = w_list.length()
+ start, stop = normalize_simple_slice(space, length, w_start, w_stop)
+ w_list.setslice(start, 1, stop-start, w_other)
+
+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)
+ sequence_w = space.listview(w_iterable)
+ w_other = W_ListObject(space, sequence_w)
+ w_list.setslice(start, 1, stop-start, w_other)
def delslice__List_ANY_ANY(space, w_list, w_start, w_stop):
- length = len(w_list.wrappeditems)
+ length = w_list.length()
start, stop = normalize_simple_slice(space, length, w_start, w_stop)
- _delitem_slice_helper(space, w_list.wrappeditems, start, 1, stop-start)
+ w_list.deleteslice(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
- items_w = w_list.wrappeditems
- while i < len(items_w): # intentionally always calling len!
- if space.eq_w(items_w[i], w_obj):
- return space.w_True
- i += 1
- return space.w_False
+ return space.wrap(w_list.contains(w_obj))
def iter__List(space, w_list):
from pypy.objspace.std import iterobject
- return iterobject.W_FastListIterObject(w_list, w_list.wrappeditems)
+ return iterobject.W_FastListIterObject(w_list)
def add__List_List(space, w_list1, w_list2):
- return W_ListObject(w_list1.wrappeditems + w_list2.wrappeditems)
-
+ w_clone = w_list1.clone()
+ w_clone.extend(w_list2)
+ return w_clone
def inplace_add__List_ANY(space, w_list1, w_iterable2):
try:
@@ -156,7 +1052,7 @@
if e.match(space, space.w_TypeError):
raise FailedToImplement
raise
- return W_ListObject(w_list.wrappeditems * times)
+ return w_list.mul(times)
def mul__List_ANY(space, w_list, w_times):
return mul_list_times(space, w_list, w_times)
@@ -171,63 +1067,65 @@
if e.match(space, space.w_TypeError):
raise FailedToImplement
raise
- w_list.wrappeditems *= times
+ w_list.inplace_mul(times)
return w_list
def eq__List_List(space, w_list1, w_list2):
# needs to be safe against eq_w() mutating the w_lists behind our back
- items1_w = w_list1.wrappeditems
- items2_w = w_list2.wrappeditems
- return equal_wrappeditems(space, items1_w, items2_w)
+ if w_list1.length() != w_list2.length():
+ return space.w_False
-def equal_wrappeditems(space, items1_w, items2_w):
- if len(items1_w) != len(items2_w):
- return space.w_False
+ # XXX in theory, this can be implemented more efficiently as well. let's
+ # not care for now
i = 0
- while i < len(items1_w) and i < len(items2_w):
- if not space.eq_w(items1_w[i], items2_w[i]):
+ while i < w_list1.length() and i < w_list2.length():
+ if not space.eq_w(w_list1.getitem(i), w_list2.getitem(i)):
return space.w_False
i += 1
return space.w_True
-def lessthan_unwrappeditems(space, items1_w, items2_w):
+def lessthan_unwrappeditems(space, w_list1, w_list2):
# needs to be safe against eq_w() mutating the w_lists behind our back
# Search for the first index where items are different
i = 0
- while i < len(items1_w) and i < len(items2_w):
- w_item1 = items1_w[i]
- w_item2 = items2_w[i]
+ # XXX in theory, this can be implemented more efficiently as well. let's
+ # not care for now
+ while i < w_list1.length() and i < w_list2.length():
+ w_item1 = w_list1.getitem(i)
+ w_item2 = w_list2.getitem(i)
if not space.eq_w(w_item1, w_item2):
return space.lt(w_item1, w_item2)
i += 1
# No more items to compare -- compare sizes
- return space.newbool(len(items1_w) < len(items2_w))
+ return space.newbool(w_list1.length() < w_list2.length())
-def greaterthan_unwrappeditems(space, items1_w, items2_w):
+def greaterthan_unwrappeditems(space, w_list1, w_list2):
# needs to be safe against eq_w() mutating the w_lists behind our back
# Search for the first index where items are different
i = 0
- while i < len(items1_w) and i < len(items2_w):
- w_item1 = items1_w[i]
- w_item2 = items2_w[i]
+ # XXX in theory, this can be implemented more efficiently as well. let's
+ # not care for now
+ while i < w_list1.length() and i < w_list2.length():
+ w_item1 = w_list1.getitem(i)
+ w_item2 = w_list2.getitem(i)
if not space.eq_w(w_item1, w_item2):
return space.gt(w_item1, w_item2)
i += 1
# No more items to compare -- compare sizes
- return space.newbool(len(items1_w) > len(items2_w))
+ return space.newbool(w_list1.length() > w_list2.length())
def lt__List_List(space, w_list1, w_list2):
- return lessthan_unwrappeditems(space, w_list1.wrappeditems,
- w_list2.wrappeditems)
+ return lessthan_unwrappeditems(space, w_list1, w_list2)
def gt__List_List(space, w_list1, w_list2):
- return greaterthan_unwrappeditems(space, w_list1.wrappeditems,
- w_list2.wrappeditems)
+ return greaterthan_unwrappeditems(space, w_list1, w_list2)
def delitem__List_ANY(space, w_list, w_idx):
idx = get_list_index(space, w_idx)
+ if idx < 0:
+ idx += w_list.length()
try:
- del w_list.wrappeditems[idx]
+ w_list.pop(idx)
except IndexError:
raise OperationError(space.w_IndexError,
space.wrap("list deletion index out of range"))
@@ -235,103 +1133,29 @@
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.wrappeditems, start, step, slicelength)
-
-def _delitem_slice_helper(space, items, start, step, slicelength):
- if slicelength==0:
- return
-
- if step < 0:
- start = start + step * (slicelength-1)
- step = -step
-
- if step == 1:
- assert start >= 0
- assert slicelength >= 0
- del items[start:start+slicelength]
- else:
- n = len(items)
- i = start
-
- for discard in range(1, slicelength):
- j = i+1
- i += step
- while j < i:
- items[j-discard] = items[j]
- j += 1
-
- j = i+1
- while j < n:
- items[j-slicelength] = items[j]
- j += 1
- start = n - slicelength
- assert start >= 0 # annotator hint
- del items[start:]
+ start, stop, step, slicelength = w_slice.indices4(space, w_list.length())
+ w_list.deleteslice(start, step, slicelength)
def setitem__List_ANY_ANY(space, w_list, w_index, w_any):
idx = get_list_index(space, w_index)
try:
- w_list.wrappeditems[idx] = w_any
+ w_list.setitem(idx, w_any)
except IndexError:
raise OperationError(space.w_IndexError,
space.wrap("list index out of range"))
return space.w_None
+def setitem__List_Slice_List(space, w_list, w_slice, w_other):
+ oldsize = w_list.length()
+ start, stop, step, slicelength = w_slice.indices4(space, oldsize)
+ w_list.setslice(start, step, slicelength, w_other)
+
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)
-
- sequence2 = space.listview(w_iterable)
- items = w_list.wrappeditems
- _setitem_slice_helper(space, items, start, step, slicelength, sequence2,
- empty_elem=None)
-
-def _setitem_slice_helper(space, items, start, step, slicelength, sequence2,
- empty_elem):
- assert slicelength >= 0
- 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 += [empty_elem] * 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_other = W_ListObject(space, sequence_w)
+ w_list.setslice(start, step, slicelength, w_other)
app = gateway.applevel("""
def listrepr(currently_in_repr, l):
@@ -352,7 +1176,7 @@
listrepr = app.interphook("listrepr")
def repr__List(space, w_list):
- if len(w_list.wrappeditems) == 0:
+ if w_list.length() == 0:
return space.wrap('[]')
ec = space.getexecutioncontext()
w_currently_in_repr = ec._py_repr
@@ -362,9 +1186,9 @@
def list_insert__List_ANY_ANY(space, w_list, w_where, w_any):
where = space.int_w(w_where)
- length = len(w_list.wrappeditems)
+ length = w_list.length()
index = get_positive_index(where, length)
- w_list.wrappeditems.insert(index, w_any)
+ w_list.insert(index, w_any)
return space.w_None
def get_positive_index(where, length):
@@ -374,45 +1198,51 @@
where = 0
elif where > length:
where = length
+ assert where >= 0
return where
def list_append__List_ANY(space, w_list, w_any):
- w_list.wrappeditems.append(w_any)
+ w_list.append(w_any)
return space.w_None
def list_extend__List_List(space, w_list, w_other):
- w_list.wrappeditems += w_other.wrappeditems
+ w_list.extend(w_other)
return space.w_None
def list_extend__List_ANY(space, w_list, w_any):
- w_list.wrappeditems += space.listview(w_any)
+ w_other = W_ListObject(space, space.listview(w_any))
+ w_list.extend(w_other)
return space.w_None
-# note that the default value will come back wrapped!!!
-def list_pop__List_ANY(space, w_list, w_idx=-1):
- items = w_list.wrappeditems
- if len(items)== 0:
+# default of w_idx is space.w_None (see listtype.py)
+def list_pop__List_ANY(space, w_list, w_idx):
+ length = w_list.length()
+ if length == 0:
raise OperationError(space.w_IndexError,
space.wrap("pop from empty list"))
+ # clearly differentiate between list.pop() and list.pop(index)
+ if space.is_w(w_idx, space.w_None):
+ return w_list.pop_end() # cannot raise because list is not empty
if space.isinstance_w(w_idx, space.w_float):
raise OperationError(space.w_TypeError,
space.wrap("integer argument expected, got float")
)
idx = space.int_w(space.int(w_idx))
+ if idx < 0:
+ idx += length
try:
- return items.pop(idx)
+ return w_list.pop(idx)
except IndexError:
raise OperationError(space.w_IndexError,
space.wrap("pop index out of range"))
def list_remove__List_ANY(space, w_list, w_any):
# needs to be safe against eq_w() mutating the w_list behind our back
- items = w_list.wrappeditems
i = 0
- while i < len(items):
- if space.eq_w(items[i], w_any):
- if i < len(items): # if this is wrong the list was changed
- del items[i]
+ while i < w_list.length():
+ if space.eq_w(w_list.getitem(i), w_any):
+ if i < w_list.length(): # if this is wrong the list was changed
+ w_list.pop(i)
return space.w_None
i += 1
raise OperationError(space.w_ValueError,
@@ -420,12 +1250,11 @@
def list_index__List_ANY_ANY_ANY(space, w_list, w_any, w_start, w_stop):
# needs to be safe against eq_w() mutating the w_list behind our back
- items = w_list.wrappeditems
- size = len(items)
+ size = w_list.length()
i, stop = slicetype.unwrap_start_stop(
space, size, w_start, w_stop, True)
- while i < stop and i < len(items):
- if space.eq_w(items[i], w_any):
+ while i < stop and i < w_list.length():
+ if space.eq_w(w_list.getitem(i), w_any):
return space.wrap(i)
i += 1
raise OperationError(space.w_ValueError,
@@ -435,15 +1264,14 @@
# needs to be safe against eq_w() mutating the w_list behind our back
count = 0
i = 0
- items = w_list.wrappeditems
- while i < len(items):
- if space.eq_w(items[i], w_any):
+ while i < w_list.length():
+ if space.eq_w(w_list.getitem(i), w_any):
count += 1
i += 1
return space.wrap(count)
def list_reverse__List(space, w_list):
- w_list.wrappeditems.reverse()
+ w_list.reverse()
return space.w_None
# ____________________________________________________________
@@ -452,12 +1280,15 @@
# Reverse a slice of a list in place, from lo up to (exclusive) hi.
# (used in sort)
+TimSort = make_timsort_class()
+IntBaseTimSort = make_timsort_class()
+StringBaseTimSort = make_timsort_class()
+
class KeyContainer(baseobjspace.W_Root):
def __init__(self, w_key, w_item):
self.w_key = w_key
self.w_item = w_item
-TimSort = make_timsort_class()
# NOTE: all the subclasses of TimSort should inherit from a common subclass,
# so make sure that only SimpleSort inherits directly from TimSort.
# This is necessary to hide the parent method TimSort.lt() from the
@@ -467,6 +1298,14 @@
space = self.space
return space.is_true(space.lt(a, b))
+class IntSort(IntBaseTimSort):
+ def lt(self, a, b):
+ return a < b
+
+class StringSort(StringBaseTimSort):
+ def lt(self, a, b):
+ return a < b
+
class CustomCompareSort(SimpleSort):
def lt(self, a, b):
space = self.space
@@ -495,6 +1334,7 @@
return CustomCompareSort.lt(self, a.w_key, b.w_key)
def list_sort__List_ANY_ANY_ANY(space, w_list, w_cmp, w_keyfunc, w_reverse):
+
has_cmp = not space.is_w(w_cmp, space.w_None)
has_key = not space.is_w(w_keyfunc, space.w_None)
has_reverse = space.is_true(w_reverse)
@@ -509,9 +1349,13 @@
if has_key:
sorterclass = CustomKeySort
else:
- sorterclass = SimpleSort
- items = w_list.wrappeditems
- sorter = sorterclass(items, len(items))
+ if w_list.strategy is space.fromcache(ObjectListStrategy):
+ sorterclass = SimpleSort
+ else:
+ w_list.sort(has_reverse)
+ return space.w_None
+
+ sorter = sorterclass(w_list.getitems(), w_list.length())
sorter.space = space
sorter.w_cmp = w_cmp
@@ -519,8 +1363,8 @@
# The list is temporarily made empty, so that mutations performed
# by comparison functions can't affect the slice of memory we're
# sorting (allowing mutations during sorting is an IndexError or
- # core-dump factory, since wrappeditems may change).
- w_list.wrappeditems = []
+ # core-dump factory, since the storage may change).
+ w_list.__init__(space, [])
# wrap each item in a KeyContainer if needed
if has_key:
@@ -550,10 +1394,10 @@
sorter.list[i] = w_obj.w_item
# check if the user mucked with the list during the sort
- mucked = len(w_list.wrappeditems) > 0
+ mucked = w_list.length() > 0
# put the items back into the list
- w_list.wrappeditems = sorter.list
+ w_list.__init__(space, sorter.list)
if mucked:
raise OperationError(space.w_ValueError,
diff --git a/pypy/objspace/std/listtype.py b/pypy/objspace/std/listtype.py
--- a/pypy/objspace/std/listtype.py
+++ b/pypy/objspace/std/listtype.py
@@ -11,7 +11,7 @@
list_extend = SMM('extend', 2,
doc='L.extend(iterable) -- extend list by appending'
' elements from the iterable')
-list_pop = SMM('pop', 2, defaults=(-1,),
+list_pop = SMM('pop', 2, defaults=(None,),
doc='L.pop([index]) -> item -- remove and return item at'
' index (default last)')
list_remove = SMM('remove', 2,
@@ -43,7 +43,7 @@
def descr__new__(space, w_listtype, __args__):
from pypy.objspace.std.listobject import W_ListObject
w_obj = space.allocate_instance(W_ListObject, w_listtype)
- W_ListObject.__init__(w_obj, [])
+ W_ListObject.__init__(w_obj, space, [])
return w_obj
# ____________________________________________________________
diff --git a/pypy/objspace/std/marshal_impl.py b/pypy/objspace/std/marshal_impl.py
--- a/pypy/objspace/std/marshal_impl.py
+++ b/pypy/objspace/std/marshal_impl.py
@@ -300,7 +300,7 @@
register(TYPE_TUPLE, unmarshal_Tuple)
def marshal_w__List(space, w_list, m):
- items = w_list.wrappeditems[:]
+ items = w_list.getitems()[:]
m.put_tuple_w(TYPE_LIST, items)
def unmarshal_List(space, u, tc):
diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py
--- a/pypy/objspace/std/model.py
+++ b/pypy/objspace/std/model.py
@@ -25,8 +25,6 @@
"ropeobject.W_RopeIterObject"],
"withropeunicode": ["ropeunicodeobject.W_RopeUnicodeObject",
"ropeunicodeobject.W_RopeUnicodeIterObject"],
- "withrangelist" : ["rangeobject.W_RangeListObject",
- "rangeobject.W_RangeIterObject"],
"withtproxy" : ["proxyobject.W_TransparentList",
"proxyobject.W_TransparentDict"],
}
@@ -253,12 +251,6 @@
(unicodeobject.W_UnicodeObject,
strbufobject.delegate_buf2unicode)
]
- if config.objspace.std.withrangelist:
- from pypy.objspace.std import rangeobject
- self.typeorder[rangeobject.W_RangeListObject] += [
- (listobject.W_ListObject,
- rangeobject.delegate_range2list),
- ]
if config.objspace.std.withsmalltuple:
from pypy.objspace.std import smalltupleobject
self.typeorder[smalltupleobject.W_SmallTupleObject] += [
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -301,7 +301,10 @@
return wraptuple(self, list_w)
def newlist(self, list_w):
- return W_ListObject(list_w)
+ return W_ListObject(self, list_w)
+
+ def newlist_str(self, list_s):
+ return W_ListObject.newlist_str(self, list_s)
def newdict(self, module=False, instance=False, classofinstance=None,
strdict=False):
@@ -391,7 +394,7 @@
if isinstance(w_obj, W_TupleObject):
t = w_obj.wrappeditems[:]
elif isinstance(w_obj, W_ListObject):
- t = w_obj.wrappeditems[:]
+ t = w_obj.getitems_copy()
else:
return ObjSpace.unpackiterable(self, w_obj, expected_length)
if expected_length != -1 and len(t) != expected_length:
@@ -405,7 +408,8 @@
if isinstance(w_obj, W_TupleObject):
t = w_obj.wrappeditems
elif isinstance(w_obj, W_ListObject):
- t = w_obj.wrappeditems[:]
+ # XXX this can copy twice
+ t = w_obj.getitems()[:]
else:
if unroll:
return make_sure_not_resized(ObjSpace.unpackiterable_unroll(
@@ -423,7 +427,7 @@
def listview(self, w_obj, expected_length=-1):
if isinstance(w_obj, W_ListObject):
- t = w_obj.wrappeditems
+ t = w_obj.getitems()
elif isinstance(w_obj, W_TupleObject):
t = w_obj.wrappeditems[:]
else:
@@ -432,6 +436,11 @@
raise self._wrap_expected_length(expected_length, len(t))
return t
+ def listview_str(self, w_obj):
+ if isinstance(w_obj, W_ListObject):
+ return w_obj.getitems_str()
+ return None
+
def sliceindices(self, w_slice, w_length):
if isinstance(w_slice, W_SliceObject):
a, b, c = w_slice.indices3(self, self.int_w(w_length))
@@ -445,14 +454,76 @@
return self.int_w(l_w[0]), self.int_w(l_w[1]), self.int_w(l_w[2])
def is_(self, w_one, w_two):
- if w_one is w_two:
- return self.w_True
- return self.w_False
+ return self.newbool(self.is_w(w_one, w_two))
- # short-cut
def is_w(self, w_one, w_two):
+ from pypy.rlib.longlong2float import float2longlong
+ w_typeone = self.type(w_one)
+ # cannot use self.is_w here to not get infinite recursion
+ if w_typeone is self.w_int:
+ return (self.type(w_two) is self.w_int and
+ self.int_w(w_one) == self.int_w(w_two))
+ elif w_typeone is self.w_float:
+ if self.type(w_two) is not self.w_float:
+ return False
+ one = float2longlong(self.float_w(w_one))
+ two = float2longlong(self.float_w(w_two))
+ return one == two
+ elif w_typeone is self.w_long:
+ return (self.type(w_two) is self.w_long and
+ self.bigint_w(w_one).eq(self.bigint_w(w_two)))
+ elif w_typeone is self.w_complex:
+ if self.type(w_two) is not self.w_complex:
+ return False
+ real1 = self.float_w(self.getattr(w_one, self.wrap("real")))
+ real2 = self.float_w(self.getattr(w_two, self.wrap("real")))
+ imag1 = self.float_w(self.getattr(w_one, self.wrap("imag")))
+ imag2 = self.float_w(self.getattr(w_two, self.wrap("imag")))
+ real1 = float2longlong(real1)
+ real2 = float2longlong(real2)
+ imag1 = float2longlong(imag1)
+ imag2 = float2longlong(imag2)
+ return real1 == real2 and imag1 == imag2
+ elif w_typeone is self.w_str:
+ return (self.type(w_two) is self.w_str and
+ self.str_w(w_one) is self.str_w(w_two))
+ elif w_typeone is self.w_unicode:
+ return (self.type(w_two) is self.w_unicode and
+ self.unicode_w(w_one) is self.unicode_w(w_two))
return w_one is w_two
+ def id(self, w_obj):
+ from pypy.rlib.rbigint import rbigint
+ from pypy.rlib import objectmodel
+ from pypy.rlib.longlong2float import float2longlong
+ w_type = self.type(w_obj)
+ if w_type is self.w_int:
+ tag = 1
+ return self.or_(self.lshift(w_obj, self.wrap(3)), self.wrap(tag))
+ elif w_type is self.w_long:
+ tag = 3
+ return self.or_(self.lshift(w_obj, self.wrap(3)), self.wrap(tag))
+ elif w_type is self.w_float:
+ tag = 5
+ val = float2longlong(self.float_w(w_obj))
+ w_obj = self.newlong_from_rbigint(rbigint.fromrarith_int(val))
+ return self.or_(self.lshift(w_obj, self.wrap(3)), self.wrap(tag))
+ elif w_type is self.w_complex:
+ real = self.float_w(self.getattr(w_obj, self.wrap("real")))
+ imag = self.float_w(self.getattr(w_obj, self.wrap("imag")))
+ tag = 5
+ real_b = rbigint.fromrarith_int(float2longlong(real))
+ imag_b = rbigint.fromrarith_int(float2longlong(imag))
+ val = real_b.lshift(8 * 8).or_(imag_b).lshift(3).or_(rbigint.fromint(3))
+ return self.newlong_from_rbigint(val)
+ elif w_type is self.w_str:
+ res = objectmodel.compute_unique_id(self.str_w(w_obj))
+ elif w_type is self.w_unicode:
+ res = objectmodel.compute_unique_id(self.unicode_w(w_obj))
+ else:
+ res = objectmodel.compute_unique_id(w_obj)
+ return self.wrap(res)
+
def is_true(self, w_obj):
# a shortcut for performance
# NOTE! this method is typically overridden by builtinshortcut.py.
diff --git a/pypy/objspace/std/rangeobject.py b/pypy/objspace/std/rangeobject.py
deleted file mode 100644
--- a/pypy/objspace/std/rangeobject.py
+++ /dev/null
@@ -1,237 +0,0 @@
-from pypy.interpreter.error import OperationError
-from pypy.objspace.std.model import registerimplementation, W_Object
-from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.multimethod import FailedToImplement
-from pypy.objspace.std.noneobject import W_NoneObject
-from pypy.objspace.std.inttype import wrapint
-from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
-from pypy.objspace.std.listobject import W_AbstractListObject, W_ListObject
-from pypy.objspace.std import listtype, iterobject, slicetype
-from pypy.interpreter import gateway, baseobjspace
-
-def length(start, stop, step):
- if step > 0:
- if stop <= start:
- return 0
- return (stop - start + step - 1)/step
-
- else: # step must be < 0
- if stop >= start:
- return 0
- return (start - stop - step - 1)/-step
-
-
-class W_RangeListObject(W_AbstractListObject):
- typedef = listtype.list_typedef
-
- def __init__(w_self, start, step, length):
- assert step != 0
- w_self.start = start
- w_self.step = step
- w_self.length = length
- w_self.w_list = None
-
- def force(w_self, space):
- if w_self.w_list is not None:
- return w_self.w_list
- start = w_self.start
- step = w_self.step
- length = w_self.length
- if not length:
- w_self.w_list = space.newlist([])
- return w_self.w_list
-
- arr = [None] * length # this is to avoid using append.
-
- i = start
- n = 0
- while n < length:
- arr[n] = wrapint(space, i)
- i += step
- n += 1
-
- w_self.w_list = space.newlist(arr)
- return w_self.w_list
-
- def getitem(w_self, i):
- if i < 0:
- i += w_self.length
- if i < 0:
- raise IndexError
- elif i >= w_self.length:
- raise IndexError
- return w_self.start + i * w_self.step
-
- def getitem_unchecked(w_self, i):
- # bounds not checked, on purpose
- return w_self.start + i * w_self.step
-
- def __repr__(w_self):
- if w_self.w_list is None:
- return "W_RangeListObject(%s, %s, %s)" % (
- w_self.start, w_self.step, w_self.length)
- else:
- return "W_RangeListObject(%r)" % (w_self.w_list, )
-
-def delegate_range2list(space, w_rangelist):
- return w_rangelist.force(space)
-
-def len__RangeList(space, w_rangelist):
- if w_rangelist.w_list is not None:
- return space.len(w_rangelist.w_list)
- return wrapint(space, w_rangelist.length)
-
-
-def getitem__RangeList_ANY(space, w_rangelist, w_index):
- if w_rangelist.w_list is not None:
- return space.getitem(w_rangelist.w_list, w_index)
- idx = space.getindex_w(w_index, space.w_IndexError, "list index")
- try:
- return wrapint(space, w_rangelist.getitem(idx))
- except IndexError:
- raise OperationError(space.w_IndexError,
- space.wrap("list index out of range"))
-
-def getitem__RangeList_Slice(space, w_rangelist, w_slice):
- if w_rangelist.w_list is not None:
- return space.getitem(w_rangelist.w_list, w_slice)
- length = w_rangelist.length
- start, stop, step, slicelength = w_slice.indices4(space, length)
- assert slicelength >= 0
- rangestart = w_rangelist.getitem_unchecked(start)
- rangestep = w_rangelist.step * step
- return W_RangeListObject(rangestart, rangestep, slicelength)
-
-def getslice__RangeList_ANY_ANY(space, w_rangelist, w_start, w_stop):
- if w_rangelist.w_list is not None:
- return space.getslice(w_rangelist.w_list, w_start, w_stop)
- length = w_rangelist.length
- start, stop = normalize_simple_slice(space, length, w_start, w_stop)
- slicelength = stop - start
- assert slicelength >= 0
- rangestart = w_rangelist.getitem_unchecked(start)
- rangestep = w_rangelist.step
- return W_RangeListObject(rangestart, rangestep, slicelength)
-
-def iter__RangeList(space, w_rangelist):
- return W_RangeIterObject(w_rangelist)
-
-def repr__RangeList(space, w_rangelist):
- if w_rangelist.w_list is not None:
- return space.repr(w_rangelist.w_list)
- if w_rangelist.length == 0:
- return space.wrap('[]')
- result = [''] * w_rangelist.length
- i = w_rangelist.start
- n = 0
- while n < w_rangelist.length:
- result[n] = str(i)
- i += w_rangelist.step
- n += 1
- return space.wrap("[" + ", ".join(result) + "]")
-
-def inplace_add__RangeList_ANY(space, w_rangelist, w_iterable2):
- space.inplace_add(w_rangelist.force(space), w_iterable2)
- return w_rangelist
-
-def inplace_mul__RangeList_ANY(space, w_rangelist, w_number):
- space.inplace_mul(w_rangelist.force(space), w_number)
- return w_rangelist
-
-
-def list_pop__RangeList_ANY(space, w_rangelist, w_idx=-1):
- if w_rangelist.w_list is not None:
- raise FailedToImplement
- length = w_rangelist.length
- if length == 0:
- raise OperationError(space.w_IndexError,
- space.wrap("pop from empty list"))
- if space.isinstance_w(w_idx, space.w_float):
- raise OperationError(space.w_TypeError,
- space.wrap("integer argument expected, got float")
- )
- idx = space.int_w(space.int(w_idx))
- if idx == 0:
- result = w_rangelist.start
- w_rangelist.start += w_rangelist.step
- w_rangelist.length -= 1
- return wrapint(space, result)
- if idx == -1 or idx == length - 1:
- w_rangelist.length -= 1
- return wrapint(
- space, w_rangelist.start + (length - 1) * w_rangelist.step)
- if idx >= w_rangelist.length:
- raise OperationError(space.w_IndexError,
- space.wrap("pop index out of range"))
- raise FailedToImplement
-
-def list_reverse__RangeList(space, w_rangelist):
- # probably somewhat useless, but well...
- if w_rangelist.w_list is not None:
- raise FailedToImplement
- w_rangelist.start = w_rangelist.getitem_unchecked(w_rangelist.length-1)
- w_rangelist.step = -w_rangelist.step
-
-def list_sort__RangeList_None_None_ANY(space, w_rangelist, w_cmp,
- w_keyfunc, w_reverse):
- # even more useless but fun
- has_reverse = space.is_true(w_reverse)
- if w_rangelist.w_list is not None:
- raise FailedToImplement
- if has_reverse:
- factor = -1
- else:
- factor = 1
- reverse = w_rangelist.step * factor < 0
- if reverse:
- w_rangelist.start = w_rangelist.getitem_unchecked(w_rangelist.length-1)
- w_rangelist.step = -w_rangelist.step
- return space.w_None
-
-
-class W_RangeIterObject(iterobject.W_AbstractSeqIterObject):
- pass
-
-def iter__RangeIter(space, w_rangeiter):
- return w_rangeiter
-
-def next__RangeIter(space, w_rangeiter):
- w_rangelist = w_rangeiter.w_seq
- if w_rangelist is None:
- raise OperationError(space.w_StopIteration, space.w_None)
- assert isinstance(w_rangelist, W_RangeListObject)
- index = w_rangeiter.index
- if w_rangelist.w_list is not None:
- try:
- w_item = space.getitem(w_rangelist.w_list,
- wrapint(space, index))
- except OperationError, e:
- w_rangeiter.w_seq = None
- if not e.match(space, space.w_IndexError):
- raise
- raise OperationError(space.w_StopIteration, space.w_None)
- else:
- if index >= w_rangelist.length:
- w_rangeiter.w_seq = None
- raise OperationError(space.w_StopIteration, space.w_None)
- w_item = wrapint(
- space,
- w_rangelist.getitem_unchecked(index))
- w_rangeiter.index = index + 1
- return w_item
-
-# XXX __length_hint__()
-##def len__RangeIter(space, w_rangeiter):
-## if w_rangeiter.w_seq is None:
-## return wrapint(space, 0)
-## index = w_rangeiter.index
-## w_length = space.len(w_rangeiter.w_seq)
-## w_len = space.sub(w_length, wrapint(space, index))
-## if space.is_true(space.lt(w_len, wrapint(space, 0))):
-## w_len = wrapint(space, 0)
-## return w_len
-
-registerimplementation(W_RangeListObject)
-registerimplementation(W_RangeIterObject)
-
-register_all(vars(), listtype)
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -11,7 +11,7 @@
from pypy.objspace.std.listobject import W_ListObject
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.objspace.std.tupleobject import W_TupleObject
-from pypy.rlib.rstring import StringBuilder
+from pypy.rlib.rstring import StringBuilder, split
from pypy.interpreter.buffer import StringBuffer
from pypy.objspace.std.stringtype import sliced, wrapstr, wrapchar, \
@@ -220,7 +220,7 @@
def str_split__String_None_ANY(space, w_self, w_none, w_maxsplit=-1):
maxsplit = space.int_w(w_maxsplit)
- res_w = []
+ res = []
value = w_self._value
length = len(value)
i = 0
@@ -243,12 +243,12 @@
maxsplit -= 1 # NB. if it's already < 0, it stays < 0
# the word is value[i:j]
- res_w.append(sliced(space, value, i, j, w_self))
+ res.append(value[i:j])
# continue to look from the character following the space after the word
i = j + 1
- return space.newlist(res_w)
+ return space.newlist_str(res)
def str_split__String_String_ANY(space, w_self, w_by, w_maxsplit=-1):
maxsplit = space.int_w(w_maxsplit)
@@ -258,33 +258,26 @@
if bylen == 0:
raise OperationError(space.w_ValueError, space.wrap("empty separator"))
- res_w = []
- start = 0
if bylen == 1 and maxsplit < 0:
+ res = []
+ start = 0
# fast path: uses str.rfind(character) and str.count(character)
by = by[0] # annotator hack: string -> char
count = value.count(by)
- res_w = [None] * (count + 1)
+ res = [None] * (count + 1)
end = len(value)
while count >= 0:
assert end >= 0
prev = value.rfind(by, 0, end)
start = prev + 1
assert start >= 0
- res_w[count] = sliced(space, value, start, end, w_self)
+ res[count] = value[start:end]
count -= 1
end = prev
else:
- while maxsplit != 0:
- next = value.find(by, start)
- if next < 0:
- break
- res_w.append(sliced(space, value, start, next, w_self))
- start = next + bylen
- maxsplit -= 1 # NB. if it's already < 0, it stays < 0
- res_w.append(sliced(space, value, start, len(value), w_self))
+ res = split(value, by, maxsplit)
- return space.newlist(res_w)
+ return space.newlist_str(res)
def str_rsplit__String_None_ANY(space, w_self, w_none, w_maxsplit=-1):
maxsplit = space.int_w(w_maxsplit)
@@ -352,6 +345,11 @@
sliced)
def str_join__String_ANY(space, w_self, w_list):
+ l = space.listview_str(w_list)
+ if l is not None:
+ if len(l) == 1:
+ return space.wrap(l[0])
+ return space.wrap(w_self._value.join(l))
list_w = space.listview(w_list)
size = len(list_w)
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -577,15 +577,17 @@
assert getattr(a, s) == 42
def test_setattr_string_identify(self):
- attrs = []
+ class StrHolder(object):
+ pass
+ holder = StrHolder()
class A(object):
def __setattr__(self, attr, value):
- attrs.append(attr)
+ holder.seen = attr
a = A()
s = "abc"
setattr(a, s, 123)
- assert attrs[0] is s
+ assert holder.seen is s
class AppTestDictViews:
def test_dictview(self):
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -1,3 +1,4 @@
+# coding: iso-8859-15
import random
from pypy.objspace.std.listobject import W_ListObject
from pypy.interpreter.error import OperationError
@@ -8,25 +9,25 @@
class TestW_ListObject(object):
def test_is_true(self):
w = self.space.wrap
- w_list = W_ListObject([])
+ w_list = W_ListObject(self.space, [])
assert self.space.is_true(w_list) == False
- w_list = W_ListObject([w(5)])
+ w_list = W_ListObject(self.space, [w(5)])
assert self.space.is_true(w_list) == True
- w_list = W_ListObject([w(5), w(3)])
+ w_list = W_ListObject(self.space, [w(5), w(3)])
assert self.space.is_true(w_list) == True
def test_len(self):
w = self.space.wrap
- w_list = W_ListObject([])
+ w_list = W_ListObject(self.space, [])
assert self.space.eq_w(self.space.len(w_list), w(0))
- w_list = W_ListObject([w(5)])
+ w_list = W_ListObject(self.space, [w(5)])
assert self.space.eq_w(self.space.len(w_list), w(1))
- w_list = W_ListObject([w(5), w(3), w(99)]*111)
+ w_list = W_ListObject(self.space, [w(5), w(3), w(99)]*111)
assert self.space.eq_w(self.space.len(w_list), w(333))
-
+
def test_getitem(self):
w = self.space.wrap
- w_list = W_ListObject([w(5), w(3)])
+ w_list = W_ListObject(self.space, [w(5), w(3)])
assert self.space.eq_w(self.space.getitem(w_list, w(0)), w(5))
assert self.space.eq_w(self.space.getitem(w_list, w(1)), w(3))
assert self.space.eq_w(self.space.getitem(w_list, w(-2)), w(5))
@@ -38,10 +39,19 @@
self.space.raises_w(self.space.w_IndexError,
self.space.getitem, w_list, w(-3))
+ def test_getitems(self):
+ w = self.space.wrap
+ from pypy.objspace.std.listobject import make_range_list
+ r = make_range_list(self.space, 1,1,7)
+ l = [w(1),w(2),w(3),w(4),w(5),w(6),w(7)]
+ l2 = r.getitems()
+ for i in range(7):
+ assert self.space.eq_w(l[i], l2[i])
+
def test_random_getitem(self):
w = self.space.wrap
s = list('qedx387tn3uixhvt 7fh387fymh3dh238 dwd-wq.dwq9')
- w_list = W_ListObject(map(w, s))
+ w_list = W_ListObject(self.space, map(w, s))
keys = range(-len(s)-5, len(s)+5)
choices = keys + [None]*12
stepchoices = [None, None, None, 1, 1, -1, -1, 2, -2,
@@ -64,7 +74,7 @@
def test_iter(self):
w = self.space.wrap
- w_list = W_ListObject([w(5), w(3), w(99)])
+ w_list = W_ListObject(self.space, [w(5), w(3), w(99)])
w_iter = self.space.iter(w_list)
assert self.space.eq_w(self.space.next(w_iter), w(5))
assert self.space.eq_w(self.space.next(w_iter), w(3))
@@ -74,7 +84,7 @@
def test_contains(self):
w = self.space.wrap
- w_list = W_ListObject([w(5), w(3), w(99)])
+ w_list = W_ListObject(self.space, [w(5), w(3), w(99)])
assert self.space.eq_w(self.space.contains(w_list, w(5)),
self.space.w_True)
assert self.space.eq_w(self.space.contains(w_list, w(99)),
@@ -89,10 +99,10 @@
def test1(testlist, start, stop, step, expected):
w_slice = self.space.newslice(w(start), w(stop), w(step))
- w_list = W_ListObject([w(i) for i in testlist])
+ w_list = W_ListObject(self.space, [w(i) for i in testlist])
w_result = self.space.getitem(w_list, w_slice)
assert self.space.unwrap(w_result) == expected
-
+
for testlist in [[], [5,3,99]]:
for start in [-2, 0, 1, 10]:
for end in [-1, 2, 999]:
@@ -110,11 +120,11 @@
def test1(lhslist, start, stop, rhslist, expected):
w_slice = self.space.newslice(w(start), w(stop), w(1))
- w_lhslist = W_ListObject([w(i) for i in lhslist])
- w_rhslist = W_ListObject([w(i) for i in rhslist])
+ w_lhslist = W_ListObject(self.space, [w(i) for i in lhslist])
+ w_rhslist = W_ListObject(self.space, [w(i) for i in rhslist])
self.space.setitem(w_lhslist, w_slice, w_rhslist)
assert self.space.unwrap(w_lhslist) == expected
-
+
test1([5,7,1,4], 1, 3, [9,8], [5,9,8,4])
test1([5,7,1,4], 1, 3, [9], [5,9,4])
@@ -125,14 +135,14 @@
def test_add(self):
w = self.space.wrap
- w_list0 = W_ListObject([])
- w_list1 = W_ListObject([w(5), w(3), w(99)])
- w_list2 = W_ListObject([w(-7)] * 111)
+ w_list0 = W_ListObject(self.space, [])
+ w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list2 = W_ListObject(self.space, [w(-7)] * 111)
assert self.space.eq_w(self.space.add(w_list1, w_list1),
- W_ListObject([w(5), w(3), w(99),
+ W_ListObject(self.space, [w(5), w(3), w(99),
w(5), w(3), w(99)]))
assert self.space.eq_w(self.space.add(w_list1, w_list2),
- W_ListObject([w(5), w(3), w(99)] +
+ W_ListObject(self.space, [w(5), w(3), w(99)] +
[w(-7)] * 111))
assert self.space.eq_w(self.space.add(w_list1, w_list0), w_list1)
assert self.space.eq_w(self.space.add(w_list0, w_list2), w_list2)
@@ -142,8 +152,8 @@
w = self.space.wrap
arg = w(2)
n = 3
- w_lis = W_ListObject([arg])
- w_lis3 = W_ListObject([arg]*n)
+ w_lis = W_ListObject(self.space, [arg])
+ w_lis3 = W_ListObject(self.space, [arg]*n)
w_res = self.space.mul(w_lis, w(n))
assert self.space.eq_w(w_lis3, w_res)
# commute
@@ -152,9 +162,9 @@
def test_setitem(self):
w = self.space.wrap
- w_list = W_ListObject([w(5), w(3)])
- w_exp1 = W_ListObject([w(5), w(7)])
- w_exp2 = W_ListObject([w(8), w(7)])
+ w_list = W_ListObject(self.space, [w(5), w(3)])
+ w_exp1 = W_ListObject(self.space, [w(5), w(7)])
+ w_exp2 = W_ListObject(self.space, [w(8), w(7)])
self.space.setitem(w_list, w(1), w(7))
assert self.space.eq_w(w_exp1, w_list)
self.space.setitem(w_list, w(-2), w(8))
@@ -167,7 +177,7 @@
def test_random_setitem_delitem(self):
w = self.space.wrap
s = range(39)
- w_list = W_ListObject(map(w, s))
+ w_list = W_ListObject(self.space, map(w, s))
expected = list(s)
keys = range(-len(s)-5, len(s)+5)
choices = keys + [None]*12
@@ -183,7 +193,7 @@
for key in keys:
if random.random() < 0.15:
random.shuffle(s)
- w_list = W_ListObject(map(w, s))
+ w_list = W_ListObject(self.space, map(w, s))
expected = list(s)
try:
value = expected[key]
@@ -218,11 +228,11 @@
def test_eq(self):
w = self.space.wrap
-
- w_list0 = W_ListObject([])
- w_list1 = W_ListObject([w(5), w(3), w(99)])
- w_list2 = W_ListObject([w(5), w(3), w(99)])
- w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)])
+
+ w_list0 = W_ListObject(self.space, [])
+ w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)])
assert self.space.eq_w(self.space.eq(w_list0, w_list1),
self.space.w_False)
@@ -236,11 +246,11 @@
self.space.w_False)
def test_ne(self):
w = self.space.wrap
-
- w_list0 = W_ListObject([])
- w_list1 = W_ListObject([w(5), w(3), w(99)])
- w_list2 = W_ListObject([w(5), w(3), w(99)])
- w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)])
+
+ w_list0 = W_ListObject(self.space, [])
+ w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)])
assert self.space.eq_w(self.space.ne(w_list0, w_list1),
self.space.w_True)
@@ -254,12 +264,12 @@
self.space.w_True)
def test_lt(self):
w = self.space.wrap
-
- w_list0 = W_ListObject([])
- w_list1 = W_ListObject([w(5), w(3), w(99)])
- w_list2 = W_ListObject([w(5), w(3), w(99)])
- w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)])
- w_list4 = W_ListObject([w(5), w(3), w(9), w(-1)])
+
+ w_list0 = W_ListObject(self.space, [])
+ w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)])
+ w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)])
assert self.space.eq_w(self.space.lt(w_list0, w_list1),
self.space.w_True)
@@ -273,15 +283,15 @@
self.space.w_True)
assert self.space.eq_w(self.space.lt(w_list4, w_list3),
self.space.w_True)
-
+
def test_ge(self):
w = self.space.wrap
-
- w_list0 = W_ListObject([])
- w_list1 = W_ListObject([w(5), w(3), w(99)])
- w_list2 = W_ListObject([w(5), w(3), w(99)])
- w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)])
- w_list4 = W_ListObject([w(5), w(3), w(9), w(-1)])
+
+ w_list0 = W_ListObject(self.space, [])
+ w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)])
+ w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)])
assert self.space.eq_w(self.space.ge(w_list0, w_list1),
self.space.w_False)
@@ -295,15 +305,15 @@
self.space.w_False)
assert self.space.eq_w(self.space.ge(w_list4, w_list3),
self.space.w_False)
-
+
def test_gt(self):
w = self.space.wrap
-
- w_list0 = W_ListObject([])
- w_list1 = W_ListObject([w(5), w(3), w(99)])
- w_list2 = W_ListObject([w(5), w(3), w(99)])
- w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)])
- w_list4 = W_ListObject([w(5), w(3), w(9), w(-1)])
+
+ w_list0 = W_ListObject(self.space, [])
+ w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)])
+ w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)])
assert self.space.eq_w(self.space.gt(w_list0, w_list1),
self.space.w_False)
@@ -317,15 +327,15 @@
self.space.w_False)
assert self.space.eq_w(self.space.gt(w_list4, w_list3),
self.space.w_False)
-
+
def test_le(self):
w = self.space.wrap
-
- w_list0 = W_ListObject([])
- w_list1 = W_ListObject([w(5), w(3), w(99)])
- w_list2 = W_ListObject([w(5), w(3), w(99)])
- w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)])
- w_list4 = W_ListObject([w(5), w(3), w(9), w(-1)])
+
+ w_list0 = W_ListObject(self.space, [])
+ w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)])
+ w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)])
+ w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)])
assert self.space.eq_w(self.space.le(w_list0, w_list1),
self.space.w_True)
@@ -346,8 +356,62 @@
import sys
on_cpython = (option.runappdirect and
not hasattr(sys, 'pypy_translation_info'))
+ cls.w_on_cpython = cls.space.wrap(on_cpython)
- cls.w_on_cpython = cls.space.wrap(on_cpython)
+ def test_getstrategyfromlist_w(self):
+ l0 = ["a", "2", "a", True]
+ # this raised TypeError on ListStrategies
+ l1 = ["a", "2", True, "a"]
+ l2 = [1, "2", "a", "a"]
+ assert sorted(l1) == sorted(l2)
+
+ def test_notequals(self):
+ assert [1,2,3,4] != [1,2,5,4]
+
+ def test_contains(self):
+ l = []
+ assert not l.__contains__(2)
+
+ l = [1,2,3]
+ assert l.__contains__(2)
+ assert not l.__contains__("2")
+ assert l.__contains__(1.0)
+
+ l = ["1","2","3"]
+ assert l.__contains__("2")
+ assert not l.__contains__(2)
+
+ l = range(4)
+ assert l.__contains__(2)
+ assert not l.__contains__("2")
+
+ l = [1,2,"3"]
+ assert l.__contains__(2)
+ assert not l.__contains__("2")
+
+ l = range(2, 20, 3) # = [2, 5, 8, 11, 14, 17]
+ assert l.__contains__(2)
+ assert l.__contains__(5)
+ assert l.__contains__(8)
+ assert l.__contains__(11)
+ assert l.__contains__(14)
+ assert l.__contains__(17)
+ assert not l.__contains__(3)
+ assert not l.__contains__(4)
+ assert not l.__contains__(7)
+ assert not l.__contains__(13)
+ assert not l.__contains__(20)
+
+ l = range(2, -20, -3) # [2, -1, -4, -7, -10, -13, -16, -19]
+ assert l.__contains__(2)
+ assert l.__contains__(-4)
+ assert l.__contains__(-13)
+ assert l.__contains__(-16)
+ assert l.__contains__(-19)
+ assert not l.__contains__(-17)
+ assert not l.__contains__(-3)
+ assert not l.__contains__(-20)
+ assert not l.__contains__(-21)
def test_call_list(self):
assert list('') == []
@@ -385,6 +449,13 @@
l.extend([10])
assert l == range(11)
+ l = []
+ m = [1,2,3]
+ l.extend(m)
+ m[0] = 5
+ assert m == [5,2,3]
+ assert l == [1,2,3]
+
def test_extend_tuple(self):
l = l0 = [1]
l.extend((2,))
@@ -418,6 +489,10 @@
assert l is l0
assert l == [1]
+ l = ["c", "a", "d", "b"]
+ l.sort(reverse=True)
+ assert l == ["d", "c", "b", "a"]
+
def test_sort_cmp(self):
def lencmp(a,b): return cmp(len(a), len(b))
l = [ 'a', 'fiver', 'tre', '' ]
@@ -459,6 +534,11 @@
l.sort(reverse = True, key = lower)
assert l == ['C', 'b', 'a']
+ def test_sort_simple_string(self):
+ l = ["a", "d", "c", "b"]
+ l.sort()
+ assert l == ["a", "b", "c", "d"]
+
def test_getitem(self):
l = [1, 2, 3, 4, 5, 6, 9]
assert l[0] == 1
@@ -471,6 +551,21 @@
assert l[-1] == 'c'
assert l[-2] == 'b'
raises(IndexError, "l[len(l)]")
+ l = []
+ raises(IndexError, "l[1]")
+
+ def test_setitem(self):
+
+ l = []
+ raises(IndexError, "l[1] = 2")
+
+ l = [5,3]
+ l[0] = 2
+ assert l == [2,3]
+
+ l = [5,3]
+ l[0] = "2"
+ assert l == ["2",3]
def test_delitem(self):
l = [1, 2, 3, 4, 5, 6, 9]
@@ -482,7 +577,7 @@
assert l == [2, 3, 4, 6]
raises(IndexError, "del l[len(l)]")
raises(IndexError, "del l[-len(l)-1]")
-
+
l = l0 = ['a', 'b', 'c']
del l[0]
assert l == ['b', 'c']
@@ -513,7 +608,7 @@
assert l[::] == l
assert l[0::-2] == l
assert l[-1::-5] == l
-
+
l = ['']
assert l[1:] == []
assert l[1::2] == []
@@ -523,6 +618,10 @@
l.extend(['a', 'b'])
assert l[::-1] == ['b', 'a', '']
+ l = [1,2,3,4,5]
+ assert l[1:0:None] == []
+ assert l[1:0] == []
+
def test_delall(self):
l = l0 = [1,2,3]
del l[:]
@@ -564,6 +663,16 @@
l1 += bar
assert l1 == ('radd', bar, [1,2,3])
+ def test_add_lists(self):
+ l1 = [1,2,3]
+ l2 = [4,5,6]
+ l3 = l1 + l2
+ assert l3 == [1,2,3,4,5,6]
+
+ l4 = range(3)
+ l5 = l4 + l2
+ assert l5 == [0,1,2,4,5,6]
+
def test_imul(self):
l = l0 = [4,3]
l *= 2
@@ -576,7 +685,7 @@
l *= (-1)
assert l is l0
assert l == []
-
+
l = l0 = ['a', 'b']
l *= 2
assert l is l0
@@ -602,7 +711,7 @@
c = range(10)
assert c.index(0) == 0
raises(ValueError, c.index, 10)
-
+
c = list('hello world')
assert c.index('l') == 2
raises(ValueError, c.index, '!')
@@ -650,7 +759,7 @@
assert l == []
assert l is l0
- def test_ass_extended_slice(self):
+ def test_assign_extended_slice(self):
l = l0 = ['a', 'b', 'c']
l[::-1] = ['a', 'b', 'c']
assert l == ['c', 'b', 'a']
@@ -662,6 +771,41 @@
assert l == [0, 'b', 2]
assert l is l0
+ l = [1,2,3]
+ raises(ValueError, "l[0:2:2] = [1,2,3,4]")
+ raises(ValueError, "l[::2] = []")
+
+ l = range(6)
+ l[::3] = ('a', 'b')
+ assert l == ['a', 1, 2, 'b', 4, 5]
+
+ def test_setslice_with_self(self):
+ l = [1,2,3,4]
+ l[:] = l
+ assert l == [1,2,3,4]
+
+ l = [1,2,3,4]
+ l[0:2] = l
+ assert l == [1,2,3,4,3,4]
+
+ l = [1,2,3,4]
+ l[0:2] = l
+ assert l == [1,2,3,4,3,4]
+
+ l = [1,2,3,4,5,6,7,8,9,10]
+ raises(ValueError, "l[5::-1] = l")
+
+ l = [1,2,3,4,5,6,7,8,9,10]
+ raises(ValueError, "l[::2] = l")
+
+ l = [1,2,3,4,5,6,7,8,9,10]
+ l[5:] = l
+ assert l == [1,2,3,4,5,1,2,3,4,5,6,7,8,9,10]
+
+ l = [1,2,3,4,5,6]
+ l[::-1] = l
+ assert l == [6,5,4,3,2,1]
+
def test_recursive_repr(self):
l = []
assert repr(l) == '[]'
@@ -687,6 +831,10 @@
l.append(4)
assert l == range(5)
+ l = [1,2,3]
+ l.append("a")
+ assert l == [1,2,3,"a"]
+
def test_count(self):
c = list('hello')
assert c.count('l') == 2
@@ -706,6 +854,14 @@
ls.insert(0, i)
assert len(ls) == 12
+ l = []
+ l.insert(4,2)
+ assert l == [2]
+
+ l = [1,2,3]
+ l.insert(0,"a")
+ assert l == ["a", 1, 2, 3]
+
def test_pop(self):
c = list('hello world')
s = ''
@@ -719,6 +875,9 @@
l.pop()
assert l == range(9)
+ l = []
+ raises(IndexError, l.pop, 0)
+
def test_pop_custom_int(self):
class A(object):
def __init__(self, x):
@@ -733,6 +892,22 @@
assert l == range(9)
raises(TypeError, range(10).pop, 1.0)
+ def test_pop_negative(self):
+ l1 = [1,2,3,4]
+ l2 = ["1", "2", "3", "4"]
+ l3 = range(5)
+ l4 = [1, 2, 3, "4"]
+
+ raises(IndexError, l1.pop, -5)
+ raises(IndexError, l2.pop, -5)
+ raises(IndexError, l3.pop, -6)
+ raises(IndexError, l4.pop, -5)
+
+ assert l1.pop(-2) == 3
+ assert l2.pop(-2) == "3"
+ assert l3.pop(-2) == 3
+ assert l4.pop(-2) == 3
+
def test_remove(self):
c = list('hello world')
c.remove('l')
@@ -783,6 +958,20 @@
l.remove(5)
assert l[10:] == [0, 1, 2, 3, 4, 6, 7, 8, 9]
+ def test_mutate_while_contains(self):
+ class Mean(object):
+ def __init__(self, i):
+ self.i = i
+ def __eq__(self, other):
+ if self.i == 9 == other:
+ del l[0]
+ return True
+ else:
+ return False
+ l = [Mean(i) for i in range(10)]
+ assert l.__contains__(9)
+ assert not l.__contains__(2)
+
def test_mutate_while_extend(self):
# this used to segfault pypy-c (with py.test -A)
import sys
@@ -805,16 +994,36 @@
res = l.__getslice__(0, 2)
assert res == [1, 2]
+ l = []
+ assert l.__getslice__(0,2) == []
+
def test___setslice__(self):
l = [1,2,3,4]
l.__setslice__(0, 2, [5, 6])
assert l == [5, 6, 3, 4]
+ l = []
+ l.__setslice__(0,0,[3,4,5])
+ assert l == [3,4,5]
+
def test___delslice__(self):
l = [1,2,3,4]
l.__delslice__(0, 2)
assert l == [3, 4]
+ def test_unicode(self):
+ s = u"\ufffd\ufffd\ufffd"
+ assert s.encode("ascii", "replace") == "???"
+ assert s.encode("ascii", "ignore") == ""
+ l1 = [s.encode("ascii", "replace")]
+ assert l1[0] == "???"
+
+ l2 = [s.encode("ascii", "ignore")]
+ assert l2[0] == ""
+
+ l3 = [s]
+ assert l1[0].encode("ascii", "replace") == "???"
+
def test_list_from_set(self):
l = ['a']
l.__init__(set('b'))
@@ -829,6 +1038,96 @@
assert l == []
assert list(g) == []
+class AppTestForRangeLists(AppTestW_ListObject):
+
+ def setup_class(cls):
+ cls.space = gettestobjspace(**{"objspace.std.withrangelist" :
+ True})
+
+ def test_range_simple_backwards(self):
+ x = range(5,1)
+ assert x == []
+
+ def test_range_big_start(self):
+ x = range(1,10)
+ x[22:0:-1] == range(1,10)
+
+ def test_range_list_invalid_slice(self):
+ x = [1,2,3,4]
+ assert x[10:0] == []
+ assert x[10:0:None] == []
+
+ x = range(1,5)
+ assert x[10:0] == []
+ assert x[10:0:None] == []
+
+ assert x[0:22] == [1,2,3,4]
+ assert x[-1:10] == [4]
+
+ assert x[0:22:None] == [1,2,3,4]
+ assert x[-1:10:None] == [4]
+
+ def test_range_backwards(self):
+ x = range(1,10)
+ assert x[22:-10] == []
+ assert x[22:-10:-1] == [9,8,7,6,5,4,3,2,1]
+ assert x[10:3:-1] == [9,8,7,6,5]
+ assert x[10:3:-2] == [9,7,5]
+ assert x[1:5:-1] == []
+
+ def test_sort_range(self):
+ l = range(3,10,3)
+ l.sort()
+ assert l == [3, 6, 9]
+ l.sort(reverse = True)
+ assert l == [9, 6, 3]
+ l.sort(reverse = True)
+ assert l == [9, 6, 3]
+ l.sort()
+ assert l == [3, 6, 9]
+
+ def test_slice(self):
+ l = []
+ l2 = range(3)
+ l.__setslice__(0,3,l2)
+ assert l == [0,1,2]
+
+ def test_getitem(self):
+ l = range(5)
+ raises(IndexError, "l[-10]")
+
+ def test_append(self):
+ l = range(5)
+ l.append(26)
+ assert l == [0,1,2,3,4,26]
+
+ l = range(5)
+ l.append("a")
+ assert l == [0,1,2,3,4,"a"]
+
+ l = range(5)
+ l.append(5)
+ assert l == [0,1,2,3,4,5]
+
+ def test_pop(self):
+ l = range(3)
+ assert l.pop(0) == 0
+
+ def test_setitem(self):
+ l = range(3)
+ l[0] = 1
+ assert l == [1,1,2]
+
+ def test_inset(self):
+ l = range(3)
+ l.insert(1,5)
+ assert l == [0,5,1,2]
+
+ def test_reverse(self):
+ l = range(3)
+ l.reverse()
+ assert l == [2,1,0]
+
class AppTestListFastSubscr:
diff --git a/pypy/objspace/std/test/test_liststrategies.py b/pypy/objspace/std/test/test_liststrategies.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -0,0 +1,419 @@
+from pypy.objspace.std.listobject import W_ListObject, EmptyListStrategy, ObjectListStrategy, IntegerListStrategy, StringListStrategy, RangeListStrategy, make_range_list
+from pypy.objspace.std import listobject
+from pypy.objspace.std.test.test_listobject import TestW_ListObject
+
+from pypy.conftest import gettestobjspace
+
+class TestW_ListStrategies(TestW_ListObject):
+
+ def test_check_strategy(self):
+ assert isinstance(W_ListObject(self.space, []).strategy, EmptyListStrategy)
+ assert isinstance(W_ListObject(self.space, [self.space.wrap(1),self.space.wrap('a')]).strategy, ObjectListStrategy)
+ assert isinstance(W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)]).strategy, IntegerListStrategy)
+ assert isinstance(W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap('b')]).strategy, StringListStrategy)
+
+ def test_empty_to_any(self):
+ l = W_ListObject(self.space, [])
+ assert isinstance(l.strategy, EmptyListStrategy)
+ l.append(self.space.wrap(1.))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ l = W_ListObject(self.space, [])
+ assert isinstance(l.strategy, EmptyListStrategy)
+ l.append(self.space.wrap(1))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+ l = W_ListObject(self.space, [])
+ assert isinstance(l.strategy, EmptyListStrategy)
+ l.append(self.space.wrap('a'))
+ assert isinstance(l.strategy, StringListStrategy)
+
+ def test_int_to_any(self):
+ l = W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.append(self.space.wrap(4))
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.append(self.space.wrap('a'))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ def test_string_to_any(self):
+ l = W_ListObject(self.space, [self.space.wrap('a'),self.space.wrap('b'),self.space.wrap('c')])
+ assert isinstance(l.strategy, StringListStrategy)
+ l.append(self.space.wrap('d'))
+ assert isinstance(l.strategy, StringListStrategy)
+ l.append(self.space.wrap(3))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ def test_setitem(self):
+ # This should work if test_listobject.py passes
+ l = W_ListObject(self.space, [self.space.wrap('a'),self.space.wrap('b'),self.space.wrap('c')])
+ assert self.space.eq_w(l.getitem(0), self.space.wrap('a'))
+ l.setitem(0, self.space.wrap('d'))
+ assert self.space.eq_w(l.getitem(0), self.space.wrap('d'))
+
+ assert isinstance(l.strategy, StringListStrategy)
+
+ # IntStrategy to ObjectStrategy
+ l = W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.setitem(0, self.space.wrap('d'))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ # StringStrategy to ObjectStrategy
+ l = W_ListObject(self.space, [self.space.wrap('a'),self.space.wrap('b'),self.space.wrap('c')])
+ assert isinstance(l.strategy, StringListStrategy)
+ l.setitem(0, self.space.wrap(2))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ def test_insert(self):
+ # no change
+ l = W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.insert(3, self.space.wrap(4))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+ # StringStrategy
+ l = W_ListObject(self.space, [self.space.wrap('a'),self.space.wrap('b'),self.space.wrap('c')])
+ assert isinstance(l.strategy, StringListStrategy)
+ l.insert(3, self.space.wrap(2))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ # IntegerStrategy
+ l = W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.insert(3, self.space.wrap('d'))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ # EmptyStrategy
+ l = W_ListObject(self.space, [])
+ assert isinstance(l.strategy, EmptyListStrategy)
+ l.insert(0, self.space.wrap('a'))
+ assert isinstance(l.strategy, StringListStrategy)
+
+ l = W_ListObject(self.space, [])
+ assert isinstance(l.strategy, EmptyListStrategy)
+ l.insert(0, self.space.wrap(2))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+ def notest_list_empty_after_delete(self):
+ l = W_ListObject(self.space, [self.space.wrap(3)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.deleteitem(0)
+ assert isinstance(l.strategy, EmptyListStrategy)
+
+ l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.deleteslice(0, 1, 2)
+ assert isinstance(l.strategy, EmptyListStrategy)
+
+ l = W_ListObject(self.space, [self.space.wrap(1)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.pop(-1)
+ assert isinstance(l.strategy, EmptyListStrategy)
+
+ def test_setslice(self):
+ l = W_ListObject(self.space, [])
+ assert isinstance(l.strategy, EmptyListStrategy)
+ l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+ l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5), self.space.wrap(6)]))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+ l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap('b'), self.space.wrap(3)])
+ assert isinstance(l.strategy, ObjectListStrategy)
+ l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.setslice(0, 1, 2, W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap('b'), self.space.wrap('c')]))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ def test_setslice_List(self):
+
+ def wrapitems(items):
+ items_w = []
+ for i in items:
+ items_w.append(self.space.wrap(i))
+ return items_w
+
+ def keep_other_strategy(w_list, start, step, length, w_other):
+ other_strategy = w_other.strategy
+ w_list.setslice(start, step, length, w_other)
+ assert w_other.strategy is other_strategy
+
+ l = W_ListObject(self.space, wrapitems([1,2,3,4,5]))
+ other = W_ListObject(self.space, wrapitems(["a", "b", "c"]))
+ keep_other_strategy(l, 0, 2, other.length(), other)
+ assert l.strategy is self.space.fromcache(ObjectListStrategy)
+
+ l = W_ListObject(self.space, wrapitems([1,2,3,4,5]))
+ other = W_ListObject(self.space, wrapitems([6, 6, 6]))
+ keep_other_strategy(l, 0, 2, other.length(), other)
+ assert l.strategy is self.space.fromcache(IntegerListStrategy)
+
+ l = W_ListObject(self.space, wrapitems(["a","b","c","d","e"]))
+ other = W_ListObject(self.space, wrapitems(["a", "b", "c"]))
+ keep_other_strategy(l, 0, 2, other.length(), other)
+ assert l.strategy is self.space.fromcache(StringListStrategy)
+
+ l = W_ListObject(self.space, wrapitems(["a",3,"c",4,"e"]))
+ other = W_ListObject(self.space, wrapitems(["a", "b", "c"]))
+ keep_other_strategy(l, 0, 2, other.length(), other)
+ assert l.strategy is self.space.fromcache(ObjectListStrategy)
+
+ l = W_ListObject(self.space, wrapitems(["a",3,"c",4,"e"]))
+ other = W_ListObject(self.space, [])
+ keep_other_strategy(l, 0, 1, l.length(), other)
+ assert l.strategy is self.space.fromcache(ObjectListStrategy)
+
+ def test_empty_setslice_with_objectlist(self):
+ l = W_ListObject(self.space, [])
+ o = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap("2"), self.space.wrap(3)])
+ l.setslice(0, 1, o.length(), o)
+ assert l.getitems() == o.getitems()
+ l.append(self.space.wrap(17))
+ assert l.getitems() != o.getitems()
+
+ def test_extend(self):
+ l = W_ListObject(self.space, [])
+ assert isinstance(l.strategy, EmptyListStrategy)
+ l.extend(W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+ l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.extend(W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap('b'), self.space.wrap('c')]))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.extend(W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5), self.space.wrap(6)]))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+ def test_empty_extend_with_any(self):
+ empty = W_ListObject(self.space, [])
+ assert isinstance(empty.strategy, EmptyListStrategy)
+ empty.extend(W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
+ assert isinstance(empty.strategy, IntegerListStrategy)
+
+ empty = W_ListObject(self.space, [])
+ assert isinstance(empty.strategy, EmptyListStrategy)
+ empty.extend(W_ListObject(self.space, [self.space.wrap("a"), self.space.wrap("b"), self.space.wrap("c")]))
+ assert isinstance(empty.strategy, StringListStrategy)
+
+ empty = W_ListObject(self.space, [])
+ assert isinstance(empty.strategy, EmptyListStrategy)
+ r = make_range_list(self.space, 1,3,7)
+ empty.extend(r)
+ assert isinstance(empty.strategy, RangeListStrategy)
+ print empty.getitem(6)
+ assert self.space.is_true(self.space.eq(empty.getitem(1), self.space.wrap(4)))
+
+ empty = W_ListObject(self.space, [])
+ assert isinstance(empty.strategy, EmptyListStrategy)
+ empty.extend(W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
+ assert isinstance(empty.strategy, IntegerListStrategy)
+
+ empty = W_ListObject(self.space, [])
+ assert isinstance(empty.strategy, EmptyListStrategy)
+ empty.extend(W_ListObject(self.space, []))
+ assert isinstance(empty.strategy, EmptyListStrategy)
+
+ def test_extend_other_with_empty(self):
+ l = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.extend(W_ListObject(self.space, []))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+ def test_rangelist(self):
+ l = make_range_list(self.space, 1,3,7)
+ assert isinstance(l.strategy, RangeListStrategy)
+ v = l.pop(5)
+ assert self.space.eq_w(v, self.space.wrap(16))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+ l = make_range_list(self.space, 1,3,7)
+ assert isinstance(l.strategy, RangeListStrategy)
+ v = l.pop(0)
+ assert self.space.eq_w(v, self.space.wrap(1))
+ assert isinstance(l.strategy, RangeListStrategy)
+ v = l.pop(l.length() - 1)
+ assert self.space.eq_w(v, self.space.wrap(19))
+ assert isinstance(l.strategy, RangeListStrategy)
+ v = l.pop_end()
+ assert self.space.eq_w(v, self.space.wrap(16))
+ assert isinstance(l.strategy, RangeListStrategy)
+
+ l = make_range_list(self.space, 1,3,7)
+ assert isinstance(l.strategy, RangeListStrategy)
+ l.append(self.space.wrap("string"))
+ assert isinstance(l.strategy, ObjectListStrategy)
+
+ l = make_range_list(self.space, 1,1,5)
+ assert isinstance(l.strategy, RangeListStrategy)
+ l.append(self.space.wrap(19))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+ def test_keep_range(self):
+ # simple list
+ l = make_range_list(self.space, 1,1,5)
+ assert isinstance(l.strategy, RangeListStrategy)
+ x = l.pop(0)
+ assert self.space.eq_w(x, self.space.wrap(1))
+ assert isinstance(l.strategy, RangeListStrategy)
+ l.pop(l.length()-1)
+ assert isinstance(l.strategy, RangeListStrategy)
+ l.append(self.space.wrap(5))
+ assert isinstance(l.strategy, RangeListStrategy)
+
+ # complex list
+ l = make_range_list(self.space, 1,3,5)
+ assert isinstance(l.strategy, RangeListStrategy)
+ l.append(self.space.wrap(16))
+ assert isinstance(l.strategy, RangeListStrategy)
+
+ def test_empty_range(self):
+ l = make_range_list(self.space, 0, 0, 0)
+ assert isinstance(l.strategy, EmptyListStrategy)
+
+ l = make_range_list(self.space, 1, 1, 10)
+ for i in l.getitems():
+ assert isinstance(l.strategy, RangeListStrategy)
+ l.pop(l.length()-1)
+
+ assert isinstance(l.strategy, RangeListStrategy)
+
+ def test_range_setslice(self):
+ l = make_range_list(self.space, 1, 3, 5)
+ assert isinstance(l.strategy, RangeListStrategy)
+ l.setslice(0, 1, 3, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)]))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+ def test_get_items_copy(self):
+ l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ l2 = l1.getitems()
+ l2.append(self.space.wrap(4))
+ assert not l2 == l1.getitems()
+
+ l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap("two"), self.space.wrap(3)])
+ l2 = l1.getitems()
+ l2.append(self.space.wrap("four"))
+ assert l2 == l1.getitems()
+
+ def test_clone(self):
+ l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ clone = l1.clone()
+ assert isinstance(clone.strategy, IntegerListStrategy)
+ clone.append(self.space.wrap(7))
+ assert not self.space.eq_w(l1, clone)
+
+ def test_add_does_not_use_getitems(self):
+ l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ l1.getitems = None
+ l2 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ l2.getitems = None
+ l3 = self.space.add(l1, l2)
+ l4 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3), self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ assert self.space.eq_w(l3, l4)
+
+ def test_mul(self):
+ l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ l2 = l1.mul(2)
+ l3 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3), self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ assert self.space.eq_w(l2, l3)
+
+ l4 = make_range_list(self.space, 1, 1, 3)
+ assert self.space.eq_w(l4, l1)
+
+ l5 = l4.mul(2)
+ assert self.space.eq_w(l5, l3)
+
+ def test_mul_same_strategy_but_different_object(self):
+ l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ l2 = l1.mul(1)
+ assert self.space.eq_w(l1, l2)
+ l1.setitem(0, self.space.wrap(5))
+ assert not self.space.eq_w(l1, l2)
+
+ def test_weird_rangelist_bug(self):
+ l = make_range_list(self.space, 1, 1, 3)
+ from pypy.objspace.std.listobject import getslice__List_ANY_ANY
+ # should not raise
+ assert getslice__List_ANY_ANY(self.space, l, self.space.wrap(15), self.space.wrap(2222)).strategy == self.space.fromcache(EmptyListStrategy)
+
+
+ def test_add_to_rangelist(self):
+ l1 = make_range_list(self.space, 1, 1, 3)
+ l2 = W_ListObject(self.space, [self.space.wrap(4), self.space.wrap(5)])
+ from pypy.objspace.std.listobject import add__List_List
+ l3 = add__List_List(self.space, l1, l2)
+ assert self.space.eq_w(l3, W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3), self.space.wrap(4), self.space.wrap(5)]))
+
+ def test_unicode(self):
+ l1 = W_ListObject(self.space, [self.space.wrap("eins"), self.space.wrap("zwei")])
+ assert isinstance(l1.strategy, StringListStrategy)
+ l2 = W_ListObject(self.space, [self.space.wrap(u"eins"), self.space.wrap(u"zwei")])
+ assert isinstance(l2.strategy, ObjectListStrategy)
+ l3 = W_ListObject(self.space, [self.space.wrap("eins"), self.space.wrap(u"zwei")])
+ assert isinstance(l3.strategy, ObjectListStrategy)
+
+ def test_listview_str(self):
+ space = self.space
+ assert space.listview_str(space.wrap("a")) is None
+ w_l = self.space.newlist([self.space.wrap('a'), self.space.wrap('b')])
+ assert space.listview_str(w_l) == ["a", "b"]
+
+ def test_string_join_uses_listview_str(self):
+ space = self.space
+ w_l = self.space.newlist([self.space.wrap('a'), self.space.wrap('b')])
+ w_l.getitems = None
+ assert space.str_w(space.call_method(space.wrap("c"), "join", w_l)) == "acb"
+
+ def test_string_join_returns_same_instance(self):
+ space = self.space
+ w_text = space.wrap("text")
+ w_l = self.space.newlist([w_text])
+ w_l.getitems = None
+ assert space.is_w(space.call_method(space.wrap(" -- "), "join", w_l), w_text)
+
+ def test_newlist_str(self):
+ space = self.space
+ l = ['a', 'b']
+ w_l = self.space.newlist_str(l)
+ assert isinstance(w_l.strategy, StringListStrategy)
+ assert space.listview_str(w_l) is l
+
+ def test_string_uses_newlist_str(self):
+ space = self.space
+ w_s = space.wrap("a b c")
+ space.newlist = None
+ try:
+ w_l = space.call_method(w_s, "split")
+ w_l2 = space.call_method(w_s, "split", space.wrap(" "))
+ finally:
+ del space.newlist
+ assert space.listview_str(w_l) == ["a", "b", "c"]
+ assert space.listview_str(w_l2) == ["a", "b", "c"]
+
+ def test_pop_without_argument_is_fast(self):
+ space = self.space
+ w_l = W_ListObject(space, [space.wrap(1), space.wrap(2), space.wrap(3)])
+ w_l.pop = None
+ w_res = listobject.list_pop__List_ANY(space, w_l, space.w_None) # does not crash
+ assert space.unwrap(w_res) == 3
+
+
+class TestW_ListStrategiesDisabled:
+ def setup_class(cls):
+ cls.space = gettestobjspace(**{"objspace.std.withliststrategies" :
+ False})
+
+ def test_check_strategy(self):
+ assert isinstance(W_ListObject(self.space, []).strategy, ObjectListStrategy)
+ assert isinstance(W_ListObject(self.space, [self.space.wrap(1),self.space.wrap('a')]).strategy, ObjectListStrategy)
+ assert isinstance(W_ListObject(self.space, [self.space.wrap(1),self.space.wrap(2),self.space.wrap(3)]).strategy, ObjectListStrategy)
+ assert isinstance(W_ListObject(self.space, [self.space.wrap('a'), self.space.wrap('b')]).strategy, ObjectListStrategy)
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -4,12 +4,24 @@
class AppTestObject:
def setup_class(cls):
+ from pypy.interpreter import gateway
import sys
+
cpython_behavior = (not option.runappdirect
or not hasattr(sys, 'pypy_translation_info'))
- cls.w_cpython_behavior = cls.space.wrap(cpython_behavior)
- cls.w_cpython_version = cls.space.wrap(tuple(sys.version_info))
+ space = cls.space
+ cls.w_cpython_behavior = space.wrap(cpython_behavior)
+ cls.w_cpython_version = space.wrap(tuple(sys.version_info))
+ cls.w_appdirect = space.wrap(option.runappdirect)
+ cls.w_cpython_apptest = space.wrap(option.runappdirect and not hasattr(sys, 'pypy_translation_info'))
+
+ def w_unwrap_wrap_unicode(space, w_obj):
+ return space.wrap(space.unicode_w(w_obj))
+ cls.w_unwrap_wrap_unicode = space.wrap(gateway.interp2app(w_unwrap_wrap_unicode))
+ def w_unwrap_wrap_str(space, w_obj):
+ return space.wrap(space.str_w(w_obj))
+ cls.w_unwrap_wrap_str = space.wrap(gateway.interp2app(w_unwrap_wrap_str))
def test_hash_builtin(self):
if not self.cpython_behavior:
@@ -103,10 +115,120 @@
return 123456
assert A().__str__() == 123456
+
+ def test_is_on_primitives(self):
+ if self.cpython_apptest:
+ skip("cpython behaves differently")
+ assert 1 is 1
+ x = 1000000
+ assert x + 1 is int(str(x + 1))
+ assert 1 is not 1.0
+ assert 1 is not 1l
+ assert 1l is not 1.0
+ assert 1.1 is 1.1
+ assert 0.0 is not -0.0
+ for x in range(10):
+ assert x + 0.1 is x + 0.1
+ for x in range(10):
+ assert x + 1L is x + 1L
+ for x in range(10):
+ assert x+1j is x+1j
+ assert 1+x*1j is 1+x*1j
+ l = [1]
+ assert l[0] is l[0]
+
+ def test_is_on_strs(self):
+ if self.appdirect:
+ skip("cannot run this test as apptest")
+ l = ["a"]
+ assert l[0] is l[0]
+ u = u"a"
+ assert self.unwrap_wrap_unicode(u) is u
+ s = "a"
+ assert self.unwrap_wrap_str(s) is s
+
+ def test_id_on_primitives(self):
+ if self.cpython_apptest:
+ skip("cpython behaves differently")
+ assert id(1) == (1 << 3) + 1
+ assert id(1l) == (1 << 3) + 3
+ class myint(int):
+ pass
+ assert id(myint(1)) != id(1)
+
+ assert id(1.0) & 7 == 5
+ assert id(-0.0) != id(0.0)
+ assert hex(id(2.0)) == '0x20000000000000005L'
+ assert id(0.0) == 5
+
+ def test_id_on_strs(self):
+ if self.appdirect:
+ skip("cannot run this test as apptest")
+ u = u"a"
+ assert id(self.unwrap_wrap_unicode(u)) == id(u)
+ s = "a"
+ assert id(self.unwrap_wrap_str(s)) == id(s)
+
+ def test_identity_vs_id_primitives(self):
+ if self.cpython_apptest:
+ skip("cpython behaves differently")
+ import sys
+ l = range(-10, 10)
+ for i in range(10):
+ l.append(float(i))
+ l.append(i + 0.1)
+ l.append(long(i))
+ l.append(i + sys.maxint)
+ l.append(i - sys.maxint)
+ l.append(i + 1j)
+ l.append(1 + i * 1j)
+ s = str(i)
+ l.append(s)
+ u = unicode(s)
+ l.append(u)
+ l.append(-0.0)
+ l.append(None)
+ l.append(True)
+ l.append(False)
+ s = "s"
+ l.append(s)
+ s = u"s"
+ l.append(s)
+
+ for i, a in enumerate(l):
+ for b in l[i:]:
+ assert (a is b) == (id(a) == id(b))
+ if a is b:
+ assert a == b
+
+ def test_identity_vs_id_str(self):
+ if self.appdirect:
+ skip("cannot run this test as apptest")
+ import sys
+ l = range(-10, 10)
+ for i in range(10):
+ s = str(i)
+ l.append(s)
+ l.append(self.unwrap_wrap_str(s))
+ u = unicode(s)
+ l.append(u)
+ l.append(self.unwrap_wrap_unicode(u))
+ s = "s"
+ l.append(s)
+ l.append(self.unwrap_wrap_str(s))
+ s = u"s"
+ l.append(s)
+ l.append(self.unwrap_wrap_unicode(s))
+
+ for i, a in enumerate(l):
+ for b in l[i:]:
+ assert (a is b) == (id(a) == id(b))
+ if a is b:
+ assert a == b
+
def test_isinstance_shortcut():
from pypy.objspace.std import objspace
space = objspace.StdObjSpace()
w_a = space.wrap("a")
space.type = None
space.isinstance_w(w_a, space.w_str) # does not crash
-
diff --git a/pypy/objspace/std/test/test_rangeobject.py b/pypy/objspace/std/test/test_rangeobject.py
--- a/pypy/objspace/std/test/test_rangeobject.py
+++ b/pypy/objspace/std/test/test_rangeobject.py
@@ -13,7 +13,7 @@
import __pypy__
def f(r):
return (isinstance(r, list) and
- "W_ListObject" not in __pypy__.internal_repr(r))
+ "RangeListStrategy" in __pypy__.internal_repr(r))
return f
""")
cls.w_SORT_FORCES_LISTS = cls.space.wrap(False)
@@ -44,12 +44,9 @@
def test_empty_range(self):
r = range(10, 10)
- if not self.SORT_FORCES_LISTS:
- r.sort(reverse=True)
assert len(r) == 0
assert list(reversed(r)) == []
assert r[:] == []
- assert self.not_forced(r)
def test_repr(self):
r = range(5)
@@ -73,26 +70,9 @@
r.reverse()
assert r == [2, 1, 1]
- def test_sort(self):
- if self.SORT_FORCES_LISTS:
- skip("sort() forces these lists")
- r = range(10, -1, -1)
- r.sort()
- assert self.not_forced(r)
- assert r == range(11)
- r = range(11)
- r.sort(reverse=True)
- assert self.not_forced(r)
- assert r == range(10, -1, -1)
- r = range(100)
- r[0] = 999
- assert not self.not_forced(r)
- r.sort()
- assert r == range(1, 100) + [999]
r = range(10)
r.sort(key=lambda x: -x)
assert r == range(9, -1, -1)
-
def test_pop(self):
r = range(10)
res = r.pop()
diff --git a/pypy/objspace/std/test/test_stringobject.py b/pypy/objspace/std/test/test_stringobject.py
--- a/pypy/objspace/std/test/test_stringobject.py
+++ b/pypy/objspace/std/test/test_stringobject.py
@@ -495,7 +495,8 @@
assert "".join([]) == ""
assert "-".join(['a', 'b']) == 'a-b'
text = 'text'
- assert "".join([text]) is text
+ assert "".join([text]) == text
+ assert " -- ".join([text]) is text
raises(TypeError, ''.join, 1)
raises(TypeError, ''.join, [1])
raises(TypeError, ''.join, [[1]])
diff --git a/pypy/objspace/std/test/test_strsliceobject.py b/pypy/objspace/std/test/test_strsliceobject.py
--- a/pypy/objspace/std/test/test_strsliceobject.py
+++ b/pypy/objspace/std/test/test_strsliceobject.py
@@ -110,12 +110,6 @@
assert 'W_StringSliceObject' in __pypy__.internal_repr(s)
assert hash(s) & 0x7fffffff == 0x7e0bce58
- def test_split_produces_strslices(self):
- import __pypy__
- l = ("X" * 100 + "," + "Y" * 100).split(",")
- assert "W_StringSliceObject" in __pypy__.internal_repr(l[0])
- assert "W_StringSliceObject" in __pypy__.internal_repr(l[1])
-
def test_strip_produces_strslices(self):
import __pypy__
s = ("abc" + "X" * 100 + "," + "Y" * 100 + "abc").strip("abc")
diff --git a/pypy/rlib/listsort.py b/pypy/rlib/listsort.py
--- a/pypy/rlib/listsort.py
+++ b/pypy/rlib/listsort.py
@@ -10,6 +10,7 @@
def make_timsort_class():
class TimSort:
+
"""TimSort(list).sort()
Sorts the list in-place, using the overridable method lt() for comparison.
@@ -551,7 +552,6 @@
assert self.pending[0].base == 0
assert self.pending[0].len == self.listlength
-
class ListSlice:
"A sublist of a list."
More information about the pypy-commit
mailing list