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

Serhiy Storchaka webhook-mailer at python.org
Sat Nov 11 09:20:03 EST 2017


https://github.com/python/cpython/commit/60c3d3551a96febac7b6016fb44605643842c686
commit: 60c3d3551a96febac7b6016fb44605643842c686
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2017-11-11T16:19:56+02:00
summary:

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 .

files:
M Objects/dictobject.c
M Objects/odictobject.c

diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 779746a31aa..b20b85c909e 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -2183,16 +2183,25 @@ dict_update_common(PyObject *self, PyObject *args, PyObject *kwds,
     PyObject *arg = NULL;
     int result = 0;
 
-    if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg))
+    if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg)) {
         result = -1;
-
+    }
     else if (arg != NULL) {
         _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);
-        else
+        }
+        else if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
+            PyErr_Clear();
             result = PyDict_MergeFromSeq2(self, arg, 1);
+        }
+        else {
+            result = -1;
+        }
     }
+
     if (result == 0 && kwds != NULL) {
         if (PyArg_ValidateKeywordArguments(kwds))
             result = PyDict_Merge(self, kwds, 1);
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
index 5d22ce71588..218aa2c5d9c 100644
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -2343,15 +2343,12 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
     }
 
     if (len) {
+        PyObject *func;
         PyObject *other = PyTuple_GET_ITEM(args, 0);  /* borrowed reference */
         assert(other != NULL);
         Py_INCREF(other);
-        if PyDict_CheckExact(other) {
-            PyObject *items;
-            if (PyDict_CheckExact(other))
-                items = PyDict_Items(other);
-            else
-                items = _PyObject_CallMethodId(other, &PyId_items, NULL);
+        if (PyDict_CheckExact(other)) {
+            PyObject *items = PyDict_Items(other);
             Py_DECREF(other);
             if (items == NULL)
                 return NULL;
@@ -2359,10 +2356,14 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
             Py_DECREF(items);
             if (res == -1)
                 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;
-            keys = _PyObject_CallMethodIdObjArgs(other, &PyId_keys, NULL);
+            keys = _PyObject_CallNoArg(func);
+            Py_DECREF(func);
             if (keys == NULL) {
                 Py_DECREF(other);
                 return NULL;
@@ -2388,29 +2389,45 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
             Py_DECREF(iterator);
             if (res != 0 || PyErr_Occurred())
                 return NULL;
+            goto handle_kwargs;
+        }
+        else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+            Py_DECREF(other);
+            return NULL;
+        }
+        else {
+            PyErr_Clear();
         }
-        else if (_PyObject_HasAttrId(other, &PyId_items)) {  /* never fails */
+
+        func = _PyObject_GetAttrId(other, &PyId_items);
+        if (func != NULL) {
             PyObject *items;
-            if (PyDict_CheckExact(other))
-                items = PyDict_Items(other);
-            else
-                items = _PyObject_CallMethodId(other, &PyId_items, NULL);
             Py_DECREF(other);
+            items = _PyObject_CallNoArg(func);
+            Py_DECREF(func);
             if (items == NULL)
                 return NULL;
             res = mutablemapping_add_pairs(self, items);
             Py_DECREF(items);
             if (res == -1)
                 return NULL;
+            goto handle_kwargs;
         }
-        else {
-            res = mutablemapping_add_pairs(self, other);
+        else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
             Py_DECREF(other);
-            if (res != 0)
-                return NULL;
+            return NULL;
         }
+        else {
+            PyErr_Clear();
+        }
+
+        res = mutablemapping_add_pairs(self, other);
+        Py_DECREF(other);
+        if (res != 0)
+            return NULL;
     }
 
+  handle_kwargs:
     /* now handle kwargs */
     assert(kwargs == NULL || PyDict_Check(kwargs));
     if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {



More information about the Python-checkins mailing list