[Python-checkins] python/dist/src/Objects classobject.c,2.155,2.156

gvanrossum@users.sourceforge.net gvanrossum@users.sourceforge.net
Thu, 13 Jun 2002 14:42:07 -0700


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

Modified Files:
	classobject.c 
Log Message:
Major cleanup operation: whenever there's a call that looks for an
optional attribute, only clear the exception when the internal getattr
operation raised AttributeError.  Many places in this file already had
that policy; but just as many didn't, and there didn't seem to be any
rhyme or reason to it.  Be consistently cautious.

Question: should I backport this?  On the one hand it's a bugfix.  On
the other hand it's a change in behavior.  Certain forms of buggy or
just weird code would work in the past but raise an exception under
the new rules; e.g. if you define a __getattr__ method that raises a
non-AttributeError exception.


Index: classobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/classobject.c,v
retrieving revision 2.155
retrieving revision 2.156
diff -C2 -d -r2.155 -r2.156
*** classobject.c	13 Jun 2002 21:31:27 -0000	2.155
--- classobject.c	13 Jun 2002 21:42:04 -0000	2.156
***************
*** 716,719 ****
--- 716,721 ----
  	if (res == NULL && (func = inst->in_class->cl_getattr) != NULL) {
  		PyObject *args;
+ 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 			return NULL;
  		PyErr_Clear();
  		args = Py_BuildValue("(OO)", inst, name);
***************
*** 817,829 ****
  	func = instance_getattr(inst, reprstr);
  	if (func == NULL) {
! 		PyObject *classname = inst->in_class->cl_name;
! 		PyObject *mod = PyDict_GetItemString(
! 			inst->in_class->cl_dict, "__module__");
  		char *cname;
  		if (classname != NULL && PyString_Check(classname))
  			cname = PyString_AsString(classname);
  		else
  			cname = "?";
- 		PyErr_Clear();
  		if (mod == NULL || !PyString_Check(mod))
  			return PyString_FromFormat("<?.%s instance at %p>",
--- 819,834 ----
  	func = instance_getattr(inst, reprstr);
  	if (func == NULL) {
! 		PyObject *classname, *mod;
  		char *cname;
+ 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 			return NULL;
+ 		PyErr_Clear();
+ 		classname = inst->in_class->cl_name;
+ 		mod = PyDict_GetItemString(inst->in_class->cl_dict,
+ 					   "__module__");
  		if (classname != NULL && PyString_Check(classname))
  			cname = PyString_AsString(classname);
  		else
  			cname = "?";
  		if (mod == NULL || !PyString_Check(mod))
  			return PyString_FromFormat("<?.%s instance at %p>",
***************
*** 850,853 ****
--- 855,860 ----
  	func = instance_getattr(inst, strstr);
  	if (func == NULL) {
+ 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 			return NULL;
  		PyErr_Clear();
  		return instance_repr(inst);
***************
*** 870,881 ****
  	func = instance_getattr(inst, hashstr);
  	if (func == NULL) {
  		/* If there is no __eq__ and no __cmp__ method, we hash on the
  		   address.  If an __eq__ or __cmp__ method exists, there must
  		   be a __hash__. */
- 		PyErr_Clear();
  		if (eqstr == NULL)
  			eqstr = PyString_InternFromString("__eq__");
  		func = instance_getattr(inst, eqstr);
  		if (func == NULL) {
  			PyErr_Clear();
  			if (cmpstr == NULL)
--- 877,892 ----
  	func = instance_getattr(inst, hashstr);
  	if (func == NULL) {
+ 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 			return -1;
+ 		PyErr_Clear();
  		/* If there is no __eq__ and no __cmp__ method, we hash on the
  		   address.  If an __eq__ or __cmp__ method exists, there must
  		   be a __hash__. */
  		if (eqstr == NULL)
  			eqstr = PyString_InternFromString("__eq__");
  		func = instance_getattr(inst, eqstr);
  		if (func == NULL) {
+ 			if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 				return -1;
  			PyErr_Clear();
  			if (cmpstr == NULL)
***************
*** 883,886 ****
--- 894,900 ----
  			func = instance_getattr(inst, cmpstr);
  			if (func == NULL) {
+ 				if (!PyErr_ExceptionMatches(
+ 					PyExc_AttributeError))
+ 					return -1;
  				PyErr_Clear();
  				return _Py_HashPointer(inst);
***************
*** 1077,1080 ****
--- 1091,1096 ----
  
  	if (func == NULL) {
+ 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 			return NULL;
  		PyErr_Clear();
  
***************
*** 1144,1147 ****
--- 1160,1165 ----
  		func = instance_getattr(inst, delslicestr);
  		if (func == NULL) {
+ 			if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 				return -1;
  			PyErr_Clear();
  			if (delitemstr == NULL)
***************
*** 1163,1166 ****
--- 1181,1186 ----
  		func = instance_getattr(inst, setslicestr);
  		if (func == NULL) {
+ 			if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 				return -1;
  			PyErr_Clear();
  			if (setitemstr == NULL)
***************
*** 1310,1313 ****
--- 1330,1335 ----
  	coercefunc = PyObject_GetAttr(v, coerce_obj);
  	if (coercefunc == NULL) {
+ 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 			return NULL;
  		PyErr_Clear();
  		return generic_binary_op(v, w, opname);
***************
*** 1392,1395 ****
--- 1414,1419 ----
  	if (coercefunc == NULL) {
  		/* No __coerce__ method */
+ 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 			return -1;
  		PyErr_Clear();
  		return 1;
***************
*** 1503,1506 ****
--- 1527,1532 ----
  	cmp_func = PyObject_GetAttr(v, cmp_obj);
  	if (cmp_func == NULL) {
+ 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 			return -2;
  		PyErr_Clear();
  		return 2;
***************
*** 1602,1609 ****
--- 1628,1639 ----
  		nonzerostr = PyString_InternFromString("__nonzero__");
  	if ((func = instance_getattr(self, nonzerostr)) == NULL) {
+ 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 			return -1;
  		PyErr_Clear();
  		if (lenstr == NULL)
  			lenstr = PyString_InternFromString("__len__");
  		if ((func = instance_getattr(self, lenstr)) == NULL) {
+ 			if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 				return -1;
  			PyErr_Clear();
  			/* Fall back to the default behavior:
***************
*** 1824,1831 ****
  	PyObject *func;
  
! 	if (iterstr == NULL)
  		iterstr = PyString_InternFromString("__iter__");
! 	if (getitemstr == NULL)
  		getitemstr = PyString_InternFromString("__getitem__");
  
  	if ((func = instance_getattr(self, iterstr)) != NULL) {
--- 1854,1867 ----
  	PyObject *func;
  
! 	if (iterstr == NULL) {
  		iterstr = PyString_InternFromString("__iter__");
! 		if (iterstr == NULL)
! 			return NULL;
! 	}
! 	if (getitemstr == NULL) {
  		getitemstr = PyString_InternFromString("__getitem__");
+ 		if (getitemstr == NULL)
+ 			return NULL;
+ 	}
  
  	if ((func = instance_getattr(self, iterstr)) != NULL) {
***************
*** 1842,1848 ****
  		return res;
  	}
  	PyErr_Clear();
  	if ((func = instance_getattr(self, getitemstr)) == NULL) {
! 		PyErr_SetString(PyExc_TypeError, "iteration over non-sequence");
  		return NULL;
  	}
--- 1878,1887 ----
  		return res;
  	}
+ 	if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 		return NULL;
  	PyErr_Clear();
  	if ((func = instance_getattr(self, getitemstr)) == NULL) {
! 		PyErr_SetString(PyExc_TypeError,
! 				"iteration over non-sequence");
  		return NULL;
  	}
***************
*** 1884,1887 ****
--- 1923,1928 ----
  	if (call == NULL) {
  		PyInstanceObject *inst = (PyInstanceObject*) func;
+ 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+ 			return NULL;
  		PyErr_Clear();
  		PyErr_Format(PyExc_AttributeError,
***************
*** 2116,2121 ****
  
  	funcname = PyObject_GetAttrString(func, "__name__");
! 	if (funcname == NULL)
  		PyErr_Clear();
  	else if (!PyString_Check(funcname)) {
  		Py_DECREF(funcname);
--- 2157,2165 ----
  
  	funcname = PyObject_GetAttrString(func, "__name__");
! 	if (funcname == NULL) {
! 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
! 			return NULL;
  		PyErr_Clear();
+ 	}
  	else if (!PyString_Check(funcname)) {
  		Py_DECREF(funcname);
***************
*** 2128,2133 ****
  	else {
  		klassname = PyObject_GetAttrString(klass, "__name__");
! 		if (klassname == NULL)
  			PyErr_Clear();
  		else if (!PyString_Check(klassname)) {
  			Py_DECREF(klassname);
--- 2172,2180 ----
  	else {
  		klassname = PyObject_GetAttrString(klass, "__name__");
! 		if (klassname == NULL) {
! 			if (!PyErr_ExceptionMatches(PyExc_AttributeError))
! 				return NULL;
  			PyErr_Clear();
+ 		}
  		else if (!PyString_Check(klassname)) {
  			Py_DECREF(klassname);
***************
*** 2208,2211 ****
--- 2255,2259 ----
  		name = PyObject_GetAttrString(class, "__name__");
  	if (name == NULL) {
+ 		/* This function cannot return an exception */
  		PyErr_Clear();
  		return "?";
***************
*** 2231,2234 ****
--- 2279,2283 ----
  	class = PyObject_GetAttrString(inst, "__class__");
  	if (class == NULL) {
+ 		/* This function cannot return an exception */
  		PyErr_Clear();
  		class = (PyObject *)(inst->ob_type);