[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.119,2.120

Guido van Rossum gvanrossum@users.sourceforge.net
Mon, 03 Dec 2001 07:36:30 -0800


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv7905

Modified Files:
	typeobject.c 
Log Message:
Address SF patch #480716 as well as related issues.

SF patch #480716 by Greg Chapman fixes the problem that super's
__get__ method always returns an instance of super, even when the
instance whose __get__ method is called is an instance of a subclass
of super.

Other issues fixed:

- super(C, C()).__class__ would return the __class__ attribute of C()
  rather than the __class__ attribute of the super object.  This is
  confusing.  To fix this, I decided to change the semantics of super
  so that it only applies to code attributes, not to data attributes.
  After all, overriding data attributes is not supported anyway.

- While super(C, x) carefully checked that x is an instance of C,
  super(C).__get__(x) made no such check, allowing for a loophole.
  This is now fixed.


Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.119
retrieving revision 2.120
diff -C2 -d -r2.119 -r2.120
*** typeobject.c	2001/12/03 00:08:33	2.119
--- typeobject.c	2001/12/03 15:36:28	2.120
***************
*** 3930,3934 ****
  				continue;
  			res = PyDict_GetItem(dict, name);
! 			if (res != NULL) {
  				Py_INCREF(res);
  				f = res->ob_type->tp_descr_get;
--- 3930,3934 ----
  				continue;
  			res = PyDict_GetItem(dict, name);
! 			if (res != NULL  && !PyDescr_IsData(res)) {
  				Py_INCREF(res);
  				f = res->ob_type->tp_descr_get;
***************
*** 3945,3948 ****
--- 3945,3963 ----
  }
  
+ static int
+ supercheck(PyTypeObject *type, PyObject *obj)
+ {
+ 	if (!PyType_IsSubtype(obj->ob_type, type) &&
+ 	    !(PyType_Check(obj) &&
+ 	      PyType_IsSubtype((PyTypeObject *)obj, type))) {
+ 		PyErr_SetString(PyExc_TypeError,
+ 			"super(type, obj): "
+ 			"obj must be an instance or subtype of type");
+ 		return -1;
+ 	}
+ 	else
+ 		return 0;
+ }
+ 
  static PyObject *
  super_descr_get(PyObject *self, PyObject *obj, PyObject *type)
***************
*** 3956,3967 ****
  		return self;
  	}
! 	new = (superobject *)PySuper_Type.tp_new(&PySuper_Type, NULL, NULL);
! 	if (new == NULL)
! 		return NULL;
! 	Py_INCREF(su->type);
! 	Py_INCREF(obj);
! 	new->type = su->type;
! 	new->obj = obj;
! 	return (PyObject *)new;
  }
  
--- 3971,3993 ----
  		return self;
  	}
! 	if (su->ob_type != &PySuper_Type)
! 		/* If su is an instance of a subclass of super,
! 		   call its type */
! 		return PyObject_CallFunction((PyObject *)su->ob_type,
! 					     "OO", su->type, obj);
! 	else {
! 		/* Inline the common case */
! 		if (supercheck(su->type, obj) < 0)
! 			return NULL;
! 		new = (superobject *)PySuper_Type.tp_new(&PySuper_Type,
! 							 NULL, NULL);
! 		if (new == NULL)
! 			return NULL;
! 		Py_INCREF(su->type);
! 		Py_INCREF(obj);
! 		new->type = su->type;
! 		new->obj = obj;
! 		return (PyObject *)new;
! 	}
  }
  
***************
*** 3977,3989 ****
  	if (obj == Py_None)
  		obj = NULL;
! 	if (obj != NULL &&
! 	    !PyType_IsSubtype(obj->ob_type, type) &&
! 	    !(PyType_Check(obj) &&
! 	      PyType_IsSubtype((PyTypeObject *)obj, type))) {
! 		PyErr_SetString(PyExc_TypeError,
! 			"super(type, obj): "
! 			"obj must be an instance or subtype of type");
  		return -1;
- 	}
  	Py_INCREF(type);
  	Py_XINCREF(obj);
--- 4003,4008 ----
  	if (obj == Py_None)
  		obj = NULL;
! 	if (obj != NULL && supercheck(type, obj) < 0)
  		return -1;
  	Py_INCREF(type);
  	Py_XINCREF(obj);