]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #27576: Fix call order in OrderedDict.__init__().
authorEric Snow <ericsnowcurrently@gmail.com>
Fri, 9 Sep 2016 18:59:08 +0000 (11:59 -0700)
committerEric Snow <ericsnowcurrently@gmail.com>
Fri, 9 Sep 2016 18:59:08 +0000 (11:59 -0700)
Lib/test/test_ordered_dict.py
Misc/NEWS
Objects/odictobject.c

index d6e72a6ed29a202965331e5dc1666d3cfd7b5a64..2da36d3032e6805581c7d6e4d7640e01dd3ef4ed 100644 (file)
@@ -98,6 +98,19 @@ class OrderedDictTests:
         self.assertRaises(TypeError, OrderedDict().update, (), ())
         self.assertRaises(TypeError, OrderedDict.update)
 
+    def test_init_calls(self):
+        calls = []
+        class Spam:
+            def keys(self):
+                calls.append('keys')
+                return ()
+            def items(self):
+                calls.append('items')
+                return ()
+
+        self.OrderedDict(Spam())
+        self.assertEqual(calls, ['keys'])
+
     def test_fromkeys(self):
         OrderedDict = self.OrderedDict
         od = OrderedDict.fromkeys('abc')
index f99ca495ffcfc3341f2de8778ca70307ca26ee16..1e29158d96be2a33a7322ddfc0f42cd8df61fa2f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -113,6 +113,8 @@ Core and Builtins
 Library
 -------
 
+- Issue #27576: Fix call order in OrderedDict.__init__().
+
 - email.generator.DecodedGenerator now supports the policy keyword.
 
 - Issue #28027: Remove undocumented modules from ``Lib/plat-*``: IN, CDROM,
index 5968e3f5d5a4fa4b0421c905026b63df00655d20..22b1f1dfed9cce63219a869a5c65cbc857077361 100644 (file)
@@ -2356,8 +2356,7 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
         PyObject *other = PyTuple_GET_ITEM(args, 0);  /* borrowed reference */
         assert(other != NULL);
         Py_INCREF(other);
-        if (PyDict_CheckExact(other) ||
-            _PyObject_HasAttrId(other, &PyId_items)) {  /* never fails */
+        if PyDict_CheckExact(other) {
             PyObject *items;
             if (PyDict_CheckExact(other))
                 items = PyDict_Items(other);
@@ -2400,6 +2399,20 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
             if (res != 0 || PyErr_Occurred())
                 return NULL;
         }
+        else if (_PyObject_HasAttrId(other, &PyId_items)) {  /* never fails */
+            PyObject *items;
+            if (PyDict_CheckExact(other))
+                items = PyDict_Items(other);
+            else
+                items = _PyObject_CallMethodId(other, &PyId_items, NULL);
+            Py_DECREF(other);
+            if (items == NULL)
+                return NULL;
+            res = mutablemapping_add_pairs(self, items);
+            Py_DECREF(items);
+            if (res == -1)
+                return NULL;
+        }
         else {
             res = mutablemapping_add_pairs(self, other);
             Py_DECREF(other);