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

@ -171,16 +171,14 @@ PyObject_GetItem(PyObject *o, PyObject *key)
if (PyType_Check(o)) {
PyObject *meth, *result, *stack[1] = {key};
_Py_IDENTIFIER(__class_getitem__);
meth = _PyObject_GetAttrId(o, &PyId___class_getitem__);
if (_PyObject_LookupAttrId(o, &PyId___class_getitem__, &meth) < 0) {
return NULL;
}
if (meth) {
result = _PyObject_FastCall(meth, stack, 1);
Py_DECREF(meth);
return result;
}
else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
return NULL;
}
PyErr_Clear();
}
return type_error("'%.200s' object is not subscriptable", o);
@ -2268,14 +2266,9 @@ abstract_get_bases(PyObject *cls)
PyObject *bases;
Py_ALLOW_RECURSION
bases = _PyObject_GetAttrId(cls, &PyId___bases__);
(void)_PyObject_LookupAttrId(cls, &PyId___bases__, &bases);
Py_END_ALLOW_RECURSION
if (bases == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear();
return NULL;
}
if (!PyTuple_Check(bases)) {
if (bases != NULL && !PyTuple_Check(bases)) {
Py_DECREF(bases);
return NULL;
}
@ -2338,26 +2331,23 @@ static int
recursive_isinstance(PyObject *inst, PyObject *cls)
{
PyObject *icls;
int retval = 0;
int retval;
_Py_IDENTIFIER(__class__);
if (PyType_Check(cls)) {
retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);
if (retval == 0) {
PyObject *c = _PyObject_GetAttrId(inst, &PyId___class__);
if (c == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear();
else
retval = -1;
}
else {
if (c != (PyObject *)(inst->ob_type) &&
PyType_Check(c))
retval = _PyObject_LookupAttrId(inst, &PyId___class__, &icls);
if (icls != NULL) {
if (icls != (PyObject *)(inst->ob_type) && PyType_Check(icls)) {
retval = PyType_IsSubtype(
(PyTypeObject *)c,
(PyTypeObject *)icls,
(PyTypeObject *)cls);
Py_DECREF(c);
}
else {
retval = 0;
}
Py_DECREF(icls);
}
}
}
@ -2365,14 +2355,8 @@ recursive_isinstance(PyObject *inst, PyObject *cls)
if (!check_class(cls,
"isinstance() arg 2 must be a type or tuple of types"))
return -1;
icls = _PyObject_GetAttrId(inst, &PyId___class__);
if (icls == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear();
else
retval = -1;
}
else {
retval = _PyObject_LookupAttrId(inst, &PyId___class__, &icls);
if (icls != NULL) {
retval = abstract_issubclass(icls, cls);
Py_DECREF(icls);
}