[Python-checkins] cpython: Issue #27576: Fix call order in OrderedDict.__init__().

eric.snow python-checkins at python.org
Fri Sep 9 15:04:32 EDT 2016


https://hg.python.org/cpython/rev/70758c12e888
changeset:   103437:70758c12e888
user:        Eric Snow <ericsnowcurrently at gmail.com>
date:        Fri Sep 09 11:59:08 2016 -0700
summary:
  Issue #27576: Fix call order in OrderedDict.__init__().

files:
  Lib/test/test_ordered_dict.py |  13 +++++++++++++
  Misc/NEWS                     |   2 ++
  Objects/odictobject.c         |  17 +++++++++++++++--
  3 files changed, 30 insertions(+), 2 deletions(-)


diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py
--- a/Lib/test/test_ordered_dict.py
+++ b/Lib/test/test_ordered_dict.py
@@ -98,6 +98,19 @@
         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')
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -113,6 +113,8 @@
 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,
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -2356,8 +2356,7 @@
         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 @@
             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);

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list