[Python-Dev] tp_(get|set)attro? inheritance bug?

Brett bac at OCF.Berkeley.EDU
Thu Jun 17 17:37:38 EDT 2004


Did an SF bug report ever get filed for this?

On Jun 11, 2004, at 10:58, Gustavo J. A. M. Carneiro wrote:

>   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... line
>
> 	/* 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.
>
> -- 
> Gustavo João Alves Marques Carneiro
> <gjc at inescporto.pt> <gustavo at users.sourceforge.net>
> The universe is always one step beyond logic.
>
>
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> http://mail.python.org/mailman/options/python-dev/brett%40python.org




More information about the Python-Dev mailing list