[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);