Assignments to __class_ broken in Python 2.5?
samwyse
samwyse at gmail.com
Fri Jul 13 01:56:10 EDT 2007
On Jul 12, 11:48 am, samwyse <samw... at gmail.com> wrote:
> On Jul 12, 6:31 am,samwyse<samw... at gmail.com> wrote:
>
> > On Jul 8, 8:50 am, Christoph Zwerschke <c... at online.de> wrote:
>
> > > With Py 2.5 I get:
>
> > > new.__class__ = old.__class__
> > > TypeError: __class__ must be set to a class
>
> Hmmm, under Python 2.4.X, printing repr(old.__class__) gives me this:
> <class exceptions.UnicodeDecodeError at 0x00A24F00>
> while under 2.5.X, I get this:
> <type 'exceptions.UnicodeDecodeError'>
>
> So, let's try sub-classing the type:
>
> def modify_message(old, f):
> class Empty: pass
> new = Empty()
> print "old.__class__ =", repr(old.__class__)
> print "Empty =", repr(Empty)
> new.__class__ = Empty
>
> class Excpt(old.__class__): pass
> print "Excpt =", repr(Excpt)
> print "Excpt.__class__ =", repr(Excpt.__class__)
> new.__class__ = Excpt
>
> new.__dict__ = old.__dict__.copy()
> new.__str__ = f
> return new
>
> Nope, that gives us the same message:
>
> old.__class__ = <type 'exceptions.UnicodeDecodeError'>
> Empty = <class __main__.Empty at 0x00AB0AB0>
> Excpt = <class '__main__.Excpt'>
> Excpt.__class__ = <type 'type'>
> Traceback (most recent call last):
> [...]
> TypeError: __class__ must be set to a class
>
> Excpt certainly appears to be a class. Does anyone smarter than me
> know what's going on here?
OK, in classobject.h, we find this:
#define PyClass_Check(op) ((op)->ob_type == &PyClass_Type)
That seems straightforward enough. And the relevant message appears
in classobject.c here:
static int
instance_setattr(PyInstanceObject *inst, PyObject *name, PyObject *v)
[...]
if (strcmp(sname, "__class__") == 0) {
if (v == NULL || !PyClass_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"__class__ must be set to a class");
return -1;
}
Back in our test code, we got these:
> Empty = <class __main__.Empty at 0x00AB0AB0>
> Excpt = <class '__main__.Excpt'>
The first class (Empty) passes the PyClass_Check macro, the second one
(Excpt) evidently fails. I'll need to dig deeper. Meanwhile, I still
have to wonder why the code doesn't allow __class_ to be assigned a
type instead of a class. Why can't we do this in the C code (assuming
the appropriate PyType_Check macro):
if (v == NULL || !(PyClass_Check(v) || PyType_Check(v))) {
More information about the Python-list
mailing list