[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