bpo-32571: Avoid raising unneeded AttributeError and silencing it in C code (GH-5222)

Add two new private APIs: _PyObject_LookupAttr() and _PyObject_LookupAttrId()
This commit is contained in:
Serhiy Storchaka 2018-01-25 10:49:40 +02:00 committed by INADA Naoki
parent 2b822a0bb1
commit f320be77ff
22 changed files with 1455 additions and 1442 deletions

View file

@ -71,12 +71,10 @@ update_bases(PyObject *bases, PyObject *const *args, Py_ssize_t nargs)
}
continue;
}
meth = _PyObject_GetAttrId(base, &PyId___mro_entries__);
if (_PyObject_LookupAttrId(base, &PyId___mro_entries__, &meth) < 0) {
goto error;
}
if (!meth) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
goto error;
}
PyErr_Clear();
if (new_bases) {
if (PyList_Append(new_bases, base) < 0) {
goto error;
@ -218,18 +216,11 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
}
/* else: meta is not a class, so we cannot do the metaclass
calculation, so we will use the explicitly given object as it is */
prep = _PyObject_GetAttrId(meta, &PyId___prepare__);
if (prep == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
ns = PyDict_New();
}
else {
Py_DECREF(meta);
Py_XDECREF(mkw);
Py_DECREF(bases);
return NULL;
}
if (_PyObject_LookupAttrId(meta, &PyId___prepare__, &prep) < 0) {
ns = NULL;
}
else if (prep == NULL) {
ns = PyDict_New();
}
else {
PyObject *pargs[2] = {name, bases};
@ -1127,8 +1118,7 @@ builtin_getattr(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
return NULL;
}
if (dflt != NULL) {
result = _PyObject_GetAttrWithoutError(v, name);
if (result == NULL && !PyErr_Occurred()) {
if (_PyObject_LookupAttr(v, name, &result) == 0) {
Py_INCREF(dflt);
return dflt;
}
@ -1191,13 +1181,12 @@ builtin_hasattr_impl(PyObject *module, PyObject *obj, PyObject *name)
"hasattr(): attribute name must be string");
return NULL;
}
v = _PyObject_GetAttrWithoutError(obj, name);
if (v == NULL) {
if (!PyErr_Occurred()) {
Py_RETURN_FALSE;
}
if (_PyObject_LookupAttr(obj, name, &v) < 0) {
return NULL;
}
if (v == NULL) {
Py_RETURN_FALSE;
}
Py_DECREF(v);
Py_RETURN_TRUE;
}