Author: Brian Kearns <[email protected]>
Branch:
Changeset: r68514:4cc2e74ada93
Date: 2013-12-20 14:54 -0500
http://bitbucket.org/pypy/pypy/changeset/4cc2e74ada93/
Log: merge heads
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -51,6 +51,13 @@
return w_iter
list_iter._annspecialcase_ = 'specialize:memo'
+def tuple_iter(space):
+ "Utility that returns the app-level descriptor tuple.__iter__."
+ w_src, w_iter = space.lookup_in_type_where(space.w_tuple,
+ '__iter__')
+ return w_iter
+tuple_iter._annspecialcase_ = 'specialize:memo'
+
def raiseattrerror(space, w_obj, name, w_descr=None):
if w_descr is None:
raise operationerrfmt(space.w_AttributeError,
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
@@ -945,7 +945,8 @@
def _extend_from_iterable(self, w_list, w_iterable):
space = self.space
- if isinstance(w_iterable, W_AbstractTupleObject):
+ if (isinstance(w_iterable, W_AbstractTupleObject)
+ and space._uses_tuple_iter(w_iterable)):
w_list.__init__(space, w_iterable.getitems_copy())
return
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
@@ -382,7 +382,7 @@
self.wrap("expected length %d, got %d" % (expected, got)))
def unpackiterable(self, w_obj, expected_length=-1):
- if isinstance(w_obj, W_AbstractTupleObject):
+ if isinstance(w_obj, W_AbstractTupleObject) and
self._uses_tuple_iter(w_obj):
t = w_obj.getitems_copy()
elif type(w_obj) is W_ListObject:
t = w_obj.getitems_copy()
@@ -396,7 +396,7 @@
def fixedview(self, w_obj, expected_length=-1, unroll=False):
""" Fast paths
"""
- if isinstance(w_obj, W_AbstractTupleObject):
+ if isinstance(w_obj, W_AbstractTupleObject) and
self._uses_tuple_iter(w_obj):
t = w_obj.tolist()
elif type(w_obj) is W_ListObject:
if unroll:
@@ -421,7 +421,7 @@
def listview(self, w_obj, expected_length=-1):
if type(w_obj) is W_ListObject:
t = w_obj.getitems()
- elif isinstance(w_obj, W_AbstractTupleObject):
+ elif isinstance(w_obj, W_AbstractTupleObject) and
self._uses_tuple_iter(w_obj):
t = w_obj.getitems_copy()
elif isinstance(w_obj, W_ListObject) and self._uses_list_iter(w_obj):
t = w_obj.getitems()
@@ -440,7 +440,7 @@
return w_obj.listview_str()
if type(w_obj) is W_SetObject or type(w_obj) is W_FrozensetObject:
return w_obj.listview_str()
- if isinstance(w_obj, W_StringObject):
+ if isinstance(w_obj, W_StringObject) and self._uses_no_iter(w_obj):
return w_obj.listview_str()
if isinstance(w_obj, W_ListObject) and self._uses_list_iter(w_obj):
return w_obj.getitems_str()
@@ -455,7 +455,7 @@
return w_obj.listview_unicode()
if type(w_obj) is W_SetObject or type(w_obj) is W_FrozensetObject:
return w_obj.listview_unicode()
- if isinstance(w_obj, W_UnicodeObject):
+ if isinstance(w_obj, W_UnicodeObject) and self._uses_no_iter(w_obj):
return w_obj.listview_unicode()
if isinstance(w_obj, W_ListObject) and self._uses_list_iter(w_obj):
return w_obj.getitems_unicode()
@@ -490,6 +490,13 @@
from pypy.objspace.descroperation import list_iter
return self.lookup(w_obj, '__iter__') is list_iter(self)
+ def _uses_tuple_iter(self, w_obj):
+ from pypy.objspace.descroperation import tuple_iter
+ return self.lookup(w_obj, '__iter__') is tuple_iter(self)
+
+ def _uses_no_iter(self, w_obj):
+ return self.lookup(w_obj, '__iter__') is 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))
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
@@ -1314,6 +1314,57 @@
non_list = NonList()
assert [] != non_list
+ def test_extend_from_empty_list_with_subclasses(self):
+ # some of these tests used to fail by ignoring the
+ # custom __iter__() --- but only if the list has so
+ # far the empty strategy, as opposed to .extend()ing
+ # a non-empty list.
+ class T(tuple):
+ def __iter__(self):
+ yield "ok"
+ assert list(T([5, 6])) == ["ok"]
+ #
+ class L(list):
+ def __iter__(self):
+ yield "ok"
+ assert list(L([5, 6])) == ["ok"]
+ assert list(L([5.2, 6.3])) == ["ok"]
+ #
+ class S(str):
+ def __iter__(self):
+ yield "ok"
+ assert list(S("don't see me")) == ["ok"]
+ #
+ class U(unicode):
+ def __iter__(self):
+ yield "ok"
+ assert list(U(u"don't see me")) == ["ok"]
+
+ def test_extend_from_nonempty_list_with_subclasses(self):
+ l = ["hi!"]
+ class T(tuple):
+ def __iter__(self):
+ yield "okT"
+ l.extend(T([5, 6]))
+ #
+ class L(list):
+ def __iter__(self):
+ yield "okL"
+ l.extend(L([5, 6]))
+ l.extend(L([5.2, 6.3]))
+ #
+ class S(str):
+ def __iter__(self):
+ yield "okS"
+ l.extend(S("don't see me"))
+ #
+ class U(unicode):
+ def __iter__(self):
+ yield "okU"
+ l.extend(U(u"don't see me"))
+ #
+ assert l == ["hi!", "okT", "okL", "okL", "okS", "okU"]
+
class AppTestForRangeLists(AppTestW_ListObject):
spaceconfig = {"objspace.std.withrangelist": True}
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit