This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author gustavo
Recipients
Date 2004-06-18.22:04:18
SpamBayes Score
Marked as misclassified
Message-id
In-reply-to
Content
 Documentation says, regarding tp_getattr:
«
This field is inherited by subtypes together with
tp_getattro: a subtype inherits both tp_getattr and
tp_getattro from its base type when the subtype's
tp_getattr and tp_getattro are both NULL.
»

  Implementation disagrees, at least in cvs head, but
the effect of the bug (non-inheritance of tp_getattr)
happens in 2.3.3.  Follow with me:

In function type_new (typeobject.c) line 1927:
        /* Special case some slots */
        if (type->tp_dictoffset != 0 || nslots > 0) {
                if (base->tp_getattr == NULL &&
base->tp_getattro == NULL)
                        type->tp_getattro =
PyObject_GenericGetAttr;
                if (base->tp_setattr == NULL &&
base->tp_setattro == NULL)
                        type->tp_setattro =
PyObject_GenericSetAttr;
        }
...later in the same function...

        /* Initialize the rest */
        if (PyType_Ready(type) < 0) {
                Py_DECREF(type);
                return NULL;
        }

Inside PyType_Ready(), line 3208:
        for (i = 1; i < n; i++) {
                PyObject *b = PyTuple_GET_ITEM(bases, i);
                if (PyType_Check(b))
                        inherit_slots(type,
(PyTypeObject *)b);
        }

Inside inherit_slots, line (3056):
        if (type->tp_getattr == NULL &&
type->tp_getattro == NULL) {
                type->tp_getattr = base->tp_getattr;
                type->tp_getattro = base->tp_getattro;
        }
        if (type->tp_setattr == NULL &&
type->tp_setattro == NULL) {
                type->tp_setattr = base->tp_setattr;
                type->tp_setattro = base->tp_setattro;
        }

    So, if you have followed through, you'll notice
that type_new first sets tp_getattro = GenericGetAttr,
in case 'base' has neither tp_getattr nor tp_getattro.

    So, you are thinking that there is no problem.  If
base has tp_getattr, that code path won't be execute. 
The problem is with multiple inheritance.  In type_new,
'base' is determined by calling best_base().  But the
selected base may not have tp_getattr, while
another might have.  In this case, setting tp_getattro
based on information from the wrong base precludes the
slot from being inherited from the right base.  This is
happening in pygtk, unfortunately.

    One possible solution would be to move the first
code block to after the PyType_Ready() call.
History
Date User Action Args
2007-08-23 14:22:44adminlinkissue975646 messages
2007-08-23 14:22:44admincreate