[ python-Bugs-975646 ] tp_(get|set)attro? inheritance bug
SourceForge.net
noreply at sourceforge.net
Wed Jun 23 08:30:24 EDT 2004
Bugs item #975646, was opened at 2004-06-18 23:04
Message generated for change (Comment added) made by gustavo
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=975646&group_id=5470
Category: Python Interpreter Core
Group: Python 2.3
Status: Open
Resolution: None
Priority: 5
Submitted By: Gustavo J. A. M. Carneiro (gustavo)
Assigned to: Nobody/Anonymous (nobody)
Summary: tp_(get|set)attro? inheritance bug
Initial Comment:
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.
----------------------------------------------------------------------
>Comment By: Gustavo J. A. M. Carneiro (gustavo)
Date: 2004-06-23 13:30
Message:
Logged In: YES
user_id=908
PyGTK implements only tp_getattr, none of tp_getattro,
tp_setattr, or tp_setattro.
We already have a workaround in pygtk, but it was my civic
duty to report this bug O:-)
----------------------------------------------------------------------
Comment By: Guido van Rossum (gvanrossum)
Date: 2004-06-23 05:38
Message:
Logged In: YES
user_id=6380
No time to think about this more, but yes, a type should
only implement *one* of tp_getattr and tp_getattro, and only
*one* (best the matching one!) of tp_setattr and
tp_setattro. If you are trying to get different semantics
for getattro and getattr, you're crazy (that's not what the
two are for -- tp_getattr is only there for b/w compat).
----------------------------------------------------------------------
Comment By: Michael Hudson (mwh)
Date: 2004-06-22 10:17
Message:
Logged In: YES
user_id=6656
Without wanting to think about this terribly hard, wouldn't a
workaround be for pygtk to implement tp_getattro and not
tp_getattr? IMO, this is a good idea anyway...
----------------------------------------------------------------------
Comment By: Martin v. Löwis (loewis)
Date: 2004-06-21 06:05
Message:
Logged In: YES
user_id=21627
Guido, is this a bug?
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=975646&group_id=5470
More information about the Python-bugs-list
mailing list