[pypy-svn] r12327 - in pypy/dist/pypy: interpreter objspace/std objspace/std/test

pedronis at codespeak.net pedronis at codespeak.net
Sun May 15 21:43:20 CEST 2005


Author: pedronis
Date: Sun May 15 21:43:20 2005
New Revision: 12327

Modified:
   pypy/dist/pypy/interpreter/baseobjspace.py
   pypy/dist/pypy/interpreter/typedef.py
   pypy/dist/pypy/objspace/std/objecttype.py
   pypy/dist/pypy/objspace/std/test/test_typeobject.py
   pypy/dist/pypy/objspace/std/typeobject.py
Log:
supporting for modifying .__class__ on objects



Modified: pypy/dist/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/dist/pypy/interpreter/baseobjspace.py	Sun May 15 21:43:20 2005
@@ -28,6 +28,10 @@
     def getclass(self, space):
         return space.gettypeobject(self.typedef)
 
+    def setclass(self, space, w_subtype):
+        raise OperationError(space.w_TypeError,
+                             space.wrap("__class__ assignment: only for heap types"))
+
     def getname(self, space, default):
         try:
             return space.str_w(space.getattr(self, space.wrap('__name__')))

Modified: pypy/dist/pypy/interpreter/typedef.py
==============================================================================
--- pypy/dist/pypy/interpreter/typedef.py	(original)
+++ pypy/dist/pypy/interpreter/typedef.py	Sun May 15 21:43:20 2005
@@ -56,8 +56,8 @@
         def getclass(self, space):
             return self.w__class__
 
-        def setclass(self, w_subtype):
-            # XXX sanity checks here
+        def setclass(self, space, w_subtype):
+            # only used by descr_set___class__
             self.w__class__ = w_subtype
 
         def __del__(self):

Modified: pypy/dist/pypy/objspace/std/objecttype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objecttype.py	(original)
+++ pypy/dist/pypy/objspace/std/objecttype.py	Sun May 15 21:43:20 2005
@@ -16,6 +16,21 @@
 def descr__class__(space, w_obj):
     return space.type(w_obj)
 
+def descr_set___class__(space, w_obj, w_newcls):
+    from pypy.objspace.std.typeobject import W_TypeObject
+    if not isinstance(w_newcls, W_TypeObject):
+        raise OperationError(space.w_TypeError,
+                             space.wrap("__class__ must be set to new-style class, not '%s' object" % 
+                                        space.type(w_newcls).getname(space, '?')))
+    w_oldcls = space.type(w_obj)
+    if w_oldcls.get_layout() == w_newcls.get_layout() and w_oldcls.hasdict == w_newcls.hasdict:
+        w_obj.setclass(space, w_newcls)
+    else:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("__class__ assignment: '%s' object layout differs from '%s'" %
+                                        (w_oldcls.getname(space, '?'), w_newcls.getname(space, '?'))))
+    
+
 def descr__new__(space, w_type, __args__):
     from pypy.objspace.std.objectobject import W_ObjectObject
     from pypy.objspace.std.typetype import _precheck_for_new
@@ -139,7 +154,7 @@
     __delattr__ = gateway.interp2app(Object.descr__delattr__.im_func),
     __str__ = gateway.interp2app(descr__str__),
     __repr__ = gateway.interp2app(descr__repr__),
-    __class__ = GetSetProperty(descr__class__),
+    __class__ = GetSetProperty(descr__class__, descr_set___class__),
     __new__ = newmethod(descr__new__,
                         unwrap_spec = [gateway.ObjSpace,gateway.W_Root,gateway.Arguments]),
     __hash__ = gateway.interp2app(descr__hash__),

Modified: pypy/dist/pypy/objspace/std/test/test_typeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_typeobject.py	(original)
+++ pypy/dist/pypy/objspace/std/test/test_typeobject.py	Sun May 15 21:43:20 2005
@@ -343,3 +343,88 @@
         class C:
             __metaclass__ = _classobj
         raises(TypeError, type, 'D', (C,), {})
+
+    def test_set___class__(self):
+        raises(TypeError, "1 .__class__ = int")
+        raises(TypeError, "1 .__class__ = bool")
+        class A(object):
+            pass
+        class B(object):
+            pass
+        a = A()
+        a.__class__ = B
+        assert a.__class__ == B
+        class A(object):
+            __slots__ = ('a',)
+        class B(A):
+            pass
+        class C(B):
+            pass
+        class D(A):
+            pass
+        d = D()
+        d.__class__ = C
+        assert d.__class__ == C
+        d.__class__ = B
+        assert d.__class__ == B
+        raises(TypeError, "d.__class__ = A")
+        d.__class__ = C
+        assert d.__class__ == C
+        d.__class__ = D
+        assert d.__class__ == D
+        class AA(object):
+            __slots__ = ('a',)
+        aa = AA()
+        raises(TypeError, "aa.__class__ = A")
+        raises(TypeError, "aa.__class__ = object")
+        class Z1(A):
+            pass
+        class Z2(A):
+            __slots__ = ['__dict__']
+        z1 = Z1()
+        z1.__class__ = Z2
+        assert z1.__class__ == Z2
+        z2 = Z2()
+        z2.__class__ = Z1
+        assert z2.__class__ == Z1
+        
+        class I(int):
+            pass
+        class F(float):
+            pass
+        f = F()
+        raises(TypeError, "f.__class__ = I")
+        i = I()
+        raises(TypeError, "i.__class__ = F")
+        raises(TypeError, "i.__class__ = int")
+
+        class I2(int):
+            pass
+        class I3(I2):
+            __slots__ = ['a']
+        class I4(I3):
+            pass
+
+        i = I()
+        i2 = I()
+        i.__class__ = I2
+        i2.__class__ = I
+        assert i.__class__ ==  I2
+        assert i2.__class__ == I
+        
+        i3 = I3()
+        raises(TypeError, "i3.__class__ = I2")
+        i3.__class__ = I4
+        assert i3.__class__ == I4
+        i3.__class__ = I3
+        assert i3.__class__ == I3
+
+        class X(object):
+            pass
+        class Y(object):
+            __slots__ = ()
+        raises(TypeError, "X().__class__ = Y")
+        raises(TypeError, "Y().__class__ = X")
+
+        raises(TypeError, "X().__class__ = object")
+        raises(TypeError, "X().__class__ = 1")

Modified: pypy/dist/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/typeobject.py	(original)
+++ pypy/dist/pypy/objspace/std/typeobject.py	Sun May 15 21:43:20 2005
@@ -164,6 +164,17 @@
 
         w_self.mro_w = w_self.compute_mro()
 
+    # compute the most parent class with the same layout as us
+    def get_layout(w_self):
+        w_bestbase = w_self.w_bestbase
+        if w_bestbase is None: # object
+            return w_self
+        if w_self.instancetypedef is not w_bestbase.instancetypedef:
+            return w_self
+        if w_self.nslots == w_bestbase.nslots:
+            return w_bestbase.get_layout()
+        return w_self
+
     def compute_mro(w_self):
         return compute_C3_mro(w_self.space, w_self)
 



More information about the Pypy-commit mailing list