[Python-checkins] python/dist/src/Objects typeobject.c,2.208,2.209

gvanrossum@users.sourceforge.net gvanrossum@users.sourceforge.net
Tue, 11 Feb 2003 19:58:40 -0800


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

Modified Files:
	typeobject.c 
Log Message:
Implement another useful feature for proxies: in super(X, x), x may
now be a proxy for an X instance, as long as issubclass(x.__class__, X).


Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.208
retrieving revision 2.209
diff -C2 -d -r2.208 -r2.209
*** typeobject.c	11 Feb 2003 20:38:29 -0000	2.208
--- typeobject.c	12 Feb 2003 03:58:38 -0000	2.209
***************
*** 5026,5029 ****
--- 5026,5030 ----
  	PyTypeObject *type;
  	PyObject *obj;
+ 	PyTypeObject *obj_type;
  } superobject;
  
***************
*** 5033,5036 ****
--- 5034,5039 ----
  	{"__self__",  T_OBJECT, offsetof(superobject, obj), READONLY,
  	 "the instance invoking super(); may be None"},
+ 	{"__self_class__", T_OBJECT, offsetof(superobject, obj_type), READONLY,
+ 	 "the type of the the instance invoking super(); may be None"},
  	{0}
  };
***************
*** 5044,5047 ****
--- 5047,5051 ----
  	Py_XDECREF(su->obj);
  	Py_XDECREF(su->type);
+ 	Py_XDECREF(su->obj_type);
  	self->ob_type->tp_free(self);
  }
***************
*** 5052,5060 ****
  	superobject *su = (superobject *)self;
  
! 	if (su->obj)
  		return PyString_FromFormat(
  			"<super: <class '%s'>, <%s object>>",
  			su->type ? su->type->tp_name : "NULL",
! 			su->obj->ob_type->tp_name);
  	else
  		return PyString_FromFormat(
--- 5056,5064 ----
  	superobject *su = (superobject *)self;
  
! 	if (su->obj_type)
  		return PyString_FromFormat(
  			"<super: <class '%s'>, <%s object>>",
  			su->type ? su->type->tp_name : "NULL",
! 			su->obj_type->tp_name);
  	else
  		return PyString_FromFormat(
***************
*** 5068,5072 ****
  	superobject *su = (superobject *)self;
  
! 	if (su->obj != NULL) {
  		PyObject *mro, *res, *tmp, *dict;
  		PyTypeObject *starttype;
--- 5072,5076 ----
  	superobject *su = (superobject *)self;
  
! 	if (su->obj_type != NULL) {
  		PyObject *mro, *res, *tmp, *dict;
  		PyTypeObject *starttype;
***************
*** 5074,5078 ****
  		int i, n;
  
! 		starttype = su->obj->ob_type;
  		mro = starttype->tp_mro;
  
--- 5078,5082 ----
  		int i, n;
  
! 		starttype = su->obj_type;
  		mro = starttype->tp_mro;
  
***************
*** 5087,5090 ****
--- 5091,5095 ----
  				break;
  		}
+ #if 0
  		if (i >= n && PyType_Check(su->obj)) {
  			starttype = (PyTypeObject *)(su->obj);
***************
*** 5102,5105 ****
--- 5107,5111 ----
  			}
  		}
+ #endif
  		i++;
  		res = NULL;
***************
*** 5129,5145 ****
  }
  
! 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;
  }
  
--- 5135,5203 ----
  }
  
! static PyTypeObject *
  supercheck(PyTypeObject *type, PyObject *obj)
  {
! 	/* Check that a super() call makes sense.  Return a type object.
! 
! 	   obj can be a new-style class, or an instance of one:
! 
! 	   - If it is a class, it must be a subclass of 'type'.  This case is
! 	     used for class methods; the return value is obj.
! 
! 	   - If it is an instance, it must be an instance of 'type'.  This is
! 	     the normal case; the return value is obj.__class__.
! 
! 	   But... when obj is an instance, we want to allow for the case where
! 	   obj->ob_type is not a subclass of type, but obj.__class__ is!
! 	   This will allow using super() with a proxy for obj.
! 	*/
! 
! 	if (PyType_Check(obj)) {
! 		/* It's a new-style class */
! 		if (PyType_IsSubtype((PyTypeObject *)obj, type)) {
! 			Py_INCREF(obj);
! 			return (PyTypeObject *)obj;
! 		}
! 		else
! 			goto fail;
! 	}
! 	else if (PyType_IsSubtype(obj->ob_type, type)) {
! 		Py_INCREF(obj->ob_type);
! 		return obj->ob_type;
! 	}
! 	else {
! 		/* Try the slow way */
! 		static PyObject *class_str = NULL;
! 		PyObject *class_attr;
! 
! 		if (class_str == NULL) {
! 			class_str = PyString_FromString("__class__");
! 			if (class_str == NULL)
! 				return NULL;
! 		}
! 
! 		class_attr = PyObject_GetAttr(obj, class_str);
! 
! 		if (class_attr != NULL &&
! 		    PyType_Check(class_attr) &&
! 		    (PyTypeObject *)class_attr != obj->ob_type)
! 		{
! 			int ok = PyType_IsSubtype(
! 				(PyTypeObject *)class_attr, type);
! 			if (ok)
! 				return (PyTypeObject *)class_attr;
! 		}
! 
! 		if (class_attr == NULL)
! 			PyErr_Clear();
! 		else
! 			Py_DECREF(class_attr);
! 	}
! 
!   fail:
! 	PyErr_SetString(PyExc_TypeError,
  			"super(type, obj): "
  			"obj must be an instance or subtype of type");
! 	return NULL;
  }
  
***************
*** 5162,5166 ****
  	else {
  		/* Inline the common case */
! 		if (supercheck(su->type, obj) < 0)
  			return NULL;
  		new = (superobject *)PySuper_Type.tp_new(&PySuper_Type,
--- 5220,5225 ----
  	else {
  		/* Inline the common case */
! 		PyTypeObject *obj_type = supercheck(su->type, obj);
! 		if (obj_type == NULL)
  			return NULL;
  		new = (superobject *)PySuper_Type.tp_new(&PySuper_Type,
***************
*** 5172,5175 ****
--- 5231,5235 ----
  		new->type = su->type;
  		new->obj = obj;
+ 		new->obj_type = obj_type;
  		return (PyObject *)new;
  	}
***************
*** 5182,5185 ****
--- 5242,5246 ----
  	PyTypeObject *type;
  	PyObject *obj = NULL;
+ 	PyTypeObject *obj_type = NULL;
  
  	if (!PyArg_ParseTuple(args, "O!|O:super", &PyType_Type, &type, &obj))
***************
*** 5187,5196 ****
  	if (obj == Py_None)
  		obj = NULL;
! 	if (obj != NULL && supercheck(type, obj) < 0)
! 		return -1;
  	Py_INCREF(type);
- 	Py_XINCREF(obj);
  	su->type = type;
  	su->obj = obj;
  	return 0;
  }
--- 5248,5261 ----
  	if (obj == Py_None)
  		obj = NULL;
! 	if (obj != NULL) {
! 		obj_type = supercheck(type, obj);
! 		if (obj_type == NULL)
! 			return -1;
! 		Py_INCREF(obj);
! 	}
  	Py_INCREF(type);
  	su->type = type;
  	su->obj = obj;
+ 	su->obj_type = obj_type;
  	return 0;
  }
***************
*** 5220,5223 ****
--- 5285,5289 ----
  	VISIT(su->obj);
  	VISIT(su->type);
+ 	VISIT(su->obj_type);
  
  #undef VISIT