On 17 Sep 2005 08:51:50 -0700 "Michele Simionato" <[EMAIL PROTECTED]> wrote:
Hi > I think this is more of a documentation issue than of a bug. No... I don't think it's a documentation issue. What's the problem with the documentation in this case ? Trying to use 'type' as a metaclass with a subclass of another class using a custom metaclass is an error and should raise the same exception the metaclass conflict does. In fact, is the same error. > It may seems strange at first, but __metaclass__ and __class__ may be > different. > > For instance, if M is metaclass > > >>> class C(object): pass > > >>> C.__metaclass__ = M > > you get a class with metaclass hook equal to M, but C.__class__ is > still 'type'. But in this case, it's a __metaclass__ attribute defined after class creation, after the call to the metaclass found in object.__class__, not dict["__metaclass__"] which have priority over object.__class__. The interpreter is not aware of this __metaclass__ attribute during class creation, since it's not in the dict passed on the type(name, bases, dict) call. > In you example, setting the __metaclass__ to 'type' does not change > the metaclass of the created class, which is inherited from the base > class. Yes, but, as I said, dict["__metaclass__"] has priority over the base class __class__. If I use a metaclass which is not a subclass of my base classes metaclass I get a TypeError: metaclass conflict exception. If I use 'type' which is also not a subclass of my base classes metaclass, I was supposed to get the same exception, but the interpreter ignores dict["__metaclass__"] and use the metaclass in base class __class__. Seems like the problem is in Objects/typeobject.c, PyType_IsSubtype (814-846) or the for loop in 1604-1621. Seems like PyType_IsSubtype is returning true for a type being a subtype of it's own subtypes and it never reaches the exception and return NULL. The problem seems to be the third if statement and after it, when the winner and metatype are exchanged if different. It's more evident using 'type' because it's the base of all types, but after looking the source code, I tested with this code: Python 2.4.1 (#1, Sep 16 2005, 17:47:47) [GCC 3.3.4] on linux2 Type "help", "copyright", "credits" or "license" for more information. c>>> class M_A(type): pass ... >>> class A: __metaclass__ = M_A ... >>> class M_B(M_A): pass ... >>> class B(A): __metaclass__ = M_B ... >>> class C(B): __metaclass__ = M_A ... >>> C.__class__ <class '__main__.M_B'> >>> C.__metaclass__ <class '__main__.M_A'> >>> Is this supposed to happen ? C's metaclass must be a subclass of M_B. If I try with any other class not related to this hierarchy, I will get a metaclass conflict error. But with M_A, the error is ignored, probably because PyType_IsSubtype is returning 1 for M_A being a subtype of M_B and the winner and metatype are exchanged later, so we end with M_B as C's real type. > I suggest you to file a documentation bug. Unfortunately the basic > documentation about metaclasses is a bit lacking and you have to > discover many things by trial and errors. I still think this is a bug, not a documentation issue. Regards -- Pedro Werneck > > Michele Simionato > > -- > http://mail.python.org/mailman/listinfo/python-list > -- http://mail.python.org/mailman/listinfo/python-list