summaryrefslogtreecommitdiffstats
path: root/Objects/object.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2018-01-25 08:49:40 (GMT)
committerINADA Naoki <methane@users.noreply.github.com>2018-01-25 08:49:40 (GMT)
commitf320be77ffb73e3b9e7fc98c37b8df3975d84b40 (patch)
tree552338f0200938249233fa4aa7b00add61965337 /Objects/object.c
parent2b822a0bb1de2612c85d8f75e3ce89eda2ac9f68 (diff)
downloadcpython-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.c76
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