Author: Armin Rigo <ar...@tunes.org>
Branch: SpecialisedTuples
Changeset: r50317:5f96cb15c116
Date: 2011-12-08 20:40 +0100
http://bitbucket.org/pypy/pypy/changeset/5f96cb15c116/

Log:    - fix space.fixedlist/unpackiterable/listview to handle directly
        tuples of any kind

        - fix the test to raise an OperationError, printing nicer tracebacks

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
@@ -29,7 +29,7 @@
 from pypy.objspace.std.sliceobject import W_SliceObject
 from pypy.objspace.std.smallintobject import W_SmallIntObject
 from pypy.objspace.std.stringobject import W_StringObject
-from pypy.objspace.std.tupleobject import W_TupleObject
+from pypy.objspace.std.tupleobject import W_AbstractTupleObject
 from pypy.objspace.std.typeobject import W_TypeObject
 
 # types
@@ -391,8 +391,8 @@
                 self.wrap("expected length %d, got %d" % (expected, got)))
 
     def unpackiterable(self, w_obj, expected_length=-1):
-        if isinstance(w_obj, W_TupleObject):
-            t = w_obj.wrappeditems[:]
+        if isinstance(w_obj, W_AbstractTupleObject):
+            t = w_obj.getitems_copy()
         elif isinstance(w_obj, W_ListObject):
             t = w_obj.getitems_copy()
         else:
@@ -405,8 +405,8 @@
     def fixedview(self, w_obj, expected_length=-1, unroll=False):
         """ Fast paths
         """
-        if isinstance(w_obj, W_TupleObject):
-            t = w_obj.wrappeditems
+        if isinstance(w_obj, W_AbstractTupleObject):
+            t = w_obj.tolist()
         elif isinstance(w_obj, W_ListObject):
             # XXX this can copy twice
             t = w_obj.getitems()[:]
@@ -428,8 +428,8 @@
     def listview(self, w_obj, expected_length=-1):
         if isinstance(w_obj, W_ListObject):
             t = w_obj.getitems()
-        elif isinstance(w_obj, W_TupleObject):
-            t = w_obj.wrappeditems[:]
+        elif isinstance(w_obj, W_AbstractTupleObject):
+            t = w_obj.getitems_copy()
         else:
             return ObjSpace.unpackiterable(self, w_obj, expected_length)
         if expected_length != -1 and len(t) != expected_length:
diff --git a/pypy/objspace/std/smalltupleobject.py 
b/pypy/objspace/std/smalltupleobject.py
--- a/pypy/objspace/std/smalltupleobject.py
+++ b/pypy/objspace/std/smalltupleobject.py
@@ -9,13 +9,14 @@
 from pypy.interpreter import gateway
 from pypy.rlib.debug import make_sure_not_resized
 from pypy.rlib.unroll import unrolling_iterable
+from pypy.tool.sourcetools import func_with_new_name
 from pypy.objspace.std.tupleobject import W_AbstractTupleObject, W_TupleObject
 
 class W_SmallTupleObject(W_AbstractTupleObject):
     from pypy.objspace.std.tupletype import tuple_typedef as typedef
 
-    def tolist(self):
-        raise NotImplementedError
+    #def tolist(self):   --- inherited from W_AbstractTupleObject
+    #    raise NotImplementedError
 
     def length(self):
         raise NotImplementedError
@@ -51,6 +52,9 @@
                 l[i] = getattr(self, 'w_value%s' % i)
             return l
 
+        # same source code, but builds and returns a resizable list
+        getitems_copy = func_with_new_name(tolist, 'getitems_copy')
+
         def length(self):
             return n
 
diff --git a/pypy/objspace/std/specialisedtupleobject.py 
b/pypy/objspace/std/specialisedtupleobject.py
--- a/pypy/objspace/std/specialisedtupleobject.py
+++ b/pypy/objspace/std/specialisedtupleobject.py
@@ -8,6 +8,7 @@
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.objectmodel import compute_hash
 from pypy.rlib.unroll import unrolling_iterable
+from pypy.tool.sourcetools import func_with_new_name
 
 class NotSpecialised(Exception):
     pass
@@ -21,8 +22,8 @@
         reprlist = [repr(item) for item in self._to_unwrapped_list()]
         return "%s(%s)" % (self.__class__.__name__, ', '.join(reprlist))
 
-    def tolist(self):
-        raise NotImplementedError
+    #def tolist(self):   --- inherited from W_AbstractTupleObject
+    #    raise NotImplementedError
 
     def _to_unwrapped_list(self):
         "NOT_RPYTHON"
@@ -46,6 +47,9 @@
     def unwrap(self, space):
         return tuple(self._to_unwrapped_list())
 
+    def delegating(self):
+        pass     # for tests only
+
 
 def make_specialised_class(typetuple):
     assert type(typetuple) == tuple
@@ -84,6 +88,9 @@
                 list_w[i] = value
             return list_w
 
+        # same source code, but builds and returns a resizable list
+        getitems_copy = func_with_new_name(tolist, 'getitems_copy')
+
         def _to_unwrapped_list(self):
             "NOT_RPYTHON"
             list_w = [None] * nValues
@@ -224,6 +231,7 @@
 registerimplementation(W_SpecialisedTupleObject)
 
 def delegate_SpecialisedTuple2Tuple(space, w_specialised):
+    w_specialised.delegating()
     return W_TupleObject(w_specialised.tolist())
 
 def len__SpecialisedTuple(space, w_tuple):
diff --git a/pypy/objspace/std/test/test_specialisedtupleobject.py 
b/pypy/objspace/std/test/test_specialisedtupleobject.py
--- a/pypy/objspace/std/test/test_specialisedtupleobject.py
+++ b/pypy/objspace/std/test/test_specialisedtupleobject.py
@@ -63,11 +63,11 @@
         def forbid_delegation(space, w_tuple):
             def delegation_forbidden():
                 # haaaack
-                if sys._getframe(2).f_code.co_name == '_mm_repr_tupleS0':
-                    return old_tolist()
-                raise NotImplementedError, w_tuple
-            old_tolist = w_tuple.tolist
-            w_tuple.tolist = delegation_forbidden
+                co = sys._getframe(2).f_code
+                if co.co_name.startswith('_mm_repr_tuple'):
+                    return
+                raise OperationError(space.w_ReferenceError, w_tuple)
+            w_tuple.delegating = delegation_forbidden
             return w_tuple
         cls.w_forbid_delegation = 
cls.space.wrap(gateway.interp2app(forbid_delegation))
 
@@ -96,6 +96,10 @@
         obj = (1, 2, 3)
         assert self.isspecialised(obj, '_ooo')
 
+    def test_delegation(self):
+        t = self.forbid_delegation((42, 43))
+        raises(ReferenceError, t.__getslice__, 0, 1)
+
     def test_len(self):
         t = self.forbid_delegation((42,43))
         assert len(t) == 2
diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py
--- a/pypy/objspace/std/tupleobject.py
+++ b/pypy/objspace/std/tupleobject.py
@@ -12,6 +12,15 @@
 class W_AbstractTupleObject(W_Object):
     __slots__ = ()
 
+    def tolist(self):
+        "Returns the items, as a fixed-size list."
+        raise NotImplementedError
+
+    def getitems_copy(self):
+        "Returns a copy of the items, as a resizable list."
+        raise NotImplementedError
+
+
 class W_TupleObject(W_AbstractTupleObject):
     from pypy.objspace.std.tupletype import tuple_typedef as typedef
     _immutable_fields_ = ['wrappeditems[*]']
@@ -29,6 +38,12 @@
         items = [space.unwrap(w_item) for w_item in w_tuple.wrappeditems]
         return tuple(items)
 
+    def tolist(self):
+        return self.wrappeditems
+
+    def getitems_copy(self):
+        return self.wrappeditems[:]   # returns a resizable list
+
 registerimplementation(W_TupleObject)
 
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to