Assignments to __class_ broken in Python 2.5?

samwyse samwyse at gmail.com
Fri Jul 13 07:58:21 EDT 2007


(Yes, I probably should have said CPython in my subject, not Python.
Sorry.)

On Jul 13, 12:56 am, samwyse <samw... at gmail.com> wrote:

> 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))) {

After a good night's sleep, I can see that Empty is a "real" class;
i.e. its repr() is handled by class_repr() in classobject.c.  Excpt,
on the other hand, is a type; i.e. its repr is handled by type_repr()
in typeobject.c.  (You can tell because class_repr() returns a value
formatted as "<class %s.%s at %p>" whereas type_repr returns a value
formatted as "<%s '%s.%s'>", where the first %s gets filled with
either "type" or "class".)

This is looking more and more like a failure to abide by PEP 252/253.
I think that the patch is simple, but I'm unusre of the
ramifications.  I also haven't looked at the 2.4 source to see how
things used to work.  Still, I think that I've got a work-around for
OP's problem, I just need to test it under both 2.4 and 2.5.




More information about the Python-list mailing list