mirror of
https://github.com/python/cpython.git
synced 2025-08-30 21:48:47 +00:00
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:
parent
2b822a0bb1
commit
f320be77ff
22 changed files with 1455 additions and 1442 deletions
|
@ -817,16 +817,11 @@ _PyObject_IsAbstract(PyObject *obj)
|
|||
if (obj == NULL)
|
||||
return 0;
|
||||
|
||||
isabstract = _PyObject_GetAttrId(obj, &PyId___isabstractmethod__);
|
||||
if (isabstract == NULL) {
|
||||
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
res = _PyObject_LookupAttrId(obj, &PyId___isabstractmethod__, &isabstract);
|
||||
if (res > 0) {
|
||||
res = PyObject_IsTrue(isabstract);
|
||||
Py_DECREF(isabstract);
|
||||
}
|
||||
res = PyObject_IsTrue(isabstract);
|
||||
Py_DECREF(isabstract);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -888,47 +883,74 @@ PyObject_GetAttr(PyObject *v, PyObject *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
_PyObject_GetAttrWithoutError(PyObject *v, PyObject *name)
|
||||
int
|
||||
_PyObject_LookupAttr(PyObject *v, PyObject *name, PyObject **result)
|
||||
{
|
||||
PyTypeObject *tp = Py_TYPE(v);
|
||||
PyObject *ret = NULL;
|
||||
|
||||
if (!PyUnicode_Check(name)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"attribute name must be string, not '%.200s'",
|
||||
name->ob_type->tp_name);
|
||||
return NULL;
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tp->tp_getattro == PyObject_GenericGetAttr) {
|
||||
return _PyObject_GenericGetAttrWithDict(v, name, NULL, 1);
|
||||
*result = _PyObject_GenericGetAttrWithDict(v, name, NULL, 1);
|
||||
if (*result != NULL) {
|
||||
return 1;
|
||||
}
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (tp->tp_getattro != NULL) {
|
||||
ret = (*tp->tp_getattro)(v, name);
|
||||
*result = (*tp->tp_getattro)(v, name);
|
||||
}
|
||||
else if (tp->tp_getattr != NULL) {
|
||||
const char *name_str = PyUnicode_AsUTF8(name);
|
||||
if (name_str == NULL)
|
||||
return NULL;
|
||||
ret = (*tp->tp_getattr)(v, (char *)name_str);
|
||||
if (name_str == NULL) {
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
*result = (*tp->tp_getattr)(v, (char *)name_str);
|
||||
}
|
||||
if (ret == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||
PyErr_Clear();
|
||||
if (*result != NULL) {
|
||||
return 1;
|
||||
}
|
||||
return ret;
|
||||
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||
return -1;
|
||||
}
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_PyObject_LookupAttrId(PyObject *v, _Py_Identifier *name, PyObject **result)
|
||||
{
|
||||
PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
|
||||
if (!oname) {
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
return _PyObject_LookupAttr(v, oname, result);
|
||||
}
|
||||
|
||||
int
|
||||
PyObject_HasAttr(PyObject *v, PyObject *name)
|
||||
{
|
||||
PyObject *res = _PyObject_GetAttrWithoutError(v, name);
|
||||
if (res != NULL) {
|
||||
Py_DECREF(res);
|
||||
return 1;
|
||||
PyObject *res;
|
||||
if (_PyObject_LookupAttr(v, name, &res) < 0) {
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
}
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
if (res == NULL) {
|
||||
return 0;
|
||||
}
|
||||
Py_DECREF(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue