bpo-31572: Get rid of _PyObject_HasAttrId() in dict and OrderedDict. (#3728)

Silence only AttributeError when get "key" and "items" attributes in
the constructor and the update() method of dict and OrderedDict .
This commit is contained in:
Serhiy Storchaka 2017-11-11 16:19:56 +02:00 committed by GitHub
parent 1707e4020f
commit 60c3d3551a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 22 deletions

View File

@ -2183,16 +2183,25 @@ dict_update_common(PyObject *self, PyObject *args, PyObject *kwds,
PyObject *arg = NULL; PyObject *arg = NULL;
int result = 0; int result = 0;
if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg)) if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg)) {
result = -1; result = -1;
}
else if (arg != NULL) { else if (arg != NULL) {
_Py_IDENTIFIER(keys); _Py_IDENTIFIER(keys);
if (_PyObject_HasAttrId(arg, &PyId_keys)) PyObject *func = _PyObject_GetAttrId(arg, &PyId_keys);
if (func != NULL) {
Py_DECREF(func);
result = PyDict_Merge(self, arg, 1); result = PyDict_Merge(self, arg, 1);
else }
else if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
result = PyDict_MergeFromSeq2(self, arg, 1); result = PyDict_MergeFromSeq2(self, arg, 1);
} }
else {
result = -1;
}
}
if (result == 0 && kwds != NULL) { if (result == 0 && kwds != NULL) {
if (PyArg_ValidateKeywordArguments(kwds)) if (PyArg_ValidateKeywordArguments(kwds))
result = PyDict_Merge(self, kwds, 1); result = PyDict_Merge(self, kwds, 1);

View File

@ -2343,15 +2343,12 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
} }
if (len) { if (len) {
PyObject *func;
PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */ PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */
assert(other != NULL); assert(other != NULL);
Py_INCREF(other); Py_INCREF(other);
if PyDict_CheckExact(other) { if (PyDict_CheckExact(other)) {
PyObject *items; PyObject *items = PyDict_Items(other);
if (PyDict_CheckExact(other))
items = PyDict_Items(other);
else
items = _PyObject_CallMethodId(other, &PyId_items, NULL);
Py_DECREF(other); Py_DECREF(other);
if (items == NULL) if (items == NULL)
return NULL; return NULL;
@ -2359,10 +2356,14 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
Py_DECREF(items); Py_DECREF(items);
if (res == -1) if (res == -1)
return NULL; return NULL;
goto handle_kwargs;
} }
else if (_PyObject_HasAttrId(other, &PyId_keys)) { /* never fails */
func = _PyObject_GetAttrId(other, &PyId_keys);
if (func != NULL) {
PyObject *keys, *iterator, *key; PyObject *keys, *iterator, *key;
keys = _PyObject_CallMethodIdObjArgs(other, &PyId_keys, NULL); keys = _PyObject_CallNoArg(func);
Py_DECREF(func);
if (keys == NULL) { if (keys == NULL) {
Py_DECREF(other); Py_DECREF(other);
return NULL; return NULL;
@ -2388,29 +2389,45 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
Py_DECREF(iterator); Py_DECREF(iterator);
if (res != 0 || PyErr_Occurred()) if (res != 0 || PyErr_Occurred())
return NULL; return NULL;
goto handle_kwargs;
} }
else if (_PyObject_HasAttrId(other, &PyId_items)) { /* never fails */ else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyObject *items;
if (PyDict_CheckExact(other))
items = PyDict_Items(other);
else
items = _PyObject_CallMethodId(other, &PyId_items, NULL);
Py_DECREF(other); Py_DECREF(other);
return NULL;
}
else {
PyErr_Clear();
}
func = _PyObject_GetAttrId(other, &PyId_items);
if (func != NULL) {
PyObject *items;
Py_DECREF(other);
items = _PyObject_CallNoArg(func);
Py_DECREF(func);
if (items == NULL) if (items == NULL)
return NULL; return NULL;
res = mutablemapping_add_pairs(self, items); res = mutablemapping_add_pairs(self, items);
Py_DECREF(items); Py_DECREF(items);
if (res == -1) if (res == -1)
return NULL; return NULL;
goto handle_kwargs;
}
else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
Py_DECREF(other);
return NULL;
} }
else { else {
PyErr_Clear();
}
res = mutablemapping_add_pairs(self, other); res = mutablemapping_add_pairs(self, other);
Py_DECREF(other); Py_DECREF(other);
if (res != 0) if (res != 0)
return NULL; return NULL;
} }
}
handle_kwargs:
/* now handle kwargs */ /* now handle kwargs */
assert(kwargs == NULL || PyDict_Check(kwargs)); assert(kwargs == NULL || PyDict_Check(kwargs));
if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) { if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {