diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2018-01-25 08:49:40 (GMT) |
---|---|---|
committer | INADA Naoki <methane@users.noreply.github.com> | 2018-01-25 08:49:40 (GMT) |
commit | f320be77ffb73e3b9e7fc98c37b8df3975d84b40 (patch) | |
tree | 552338f0200938249233fa4aa7b00add61965337 /Objects/object.c | |
parent | 2b822a0bb1de2612c85d8f75e3ce89eda2ac9f68 (diff) | |
download | cpython-f320be77ffb73e3b9e7fc98c37b8df3975d84b40.zip cpython-f320be77ffb73e3b9e7fc98c37b8df3975d84b40.tar.gz cpython-f320be77ffb73e3b9e7fc98c37b8df3975d84b40.tar.bz2 |
bpo-32571: Avoid raising unneeded AttributeError and silencing it in C code (GH-5222)
Add two new private APIs: _PyObject_LookupAttr() and _PyObject_LookupAttrId()
Diffstat (limited to 'Objects/object.c')
-rw-r--r-- | Objects/object.c | 76 |
1 files changed, 49 insertions, 27 deletions
diff --git a/Objects/object.c b/Objects/object.c index 8cec6e2..7b2adbe 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -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 |