summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_ordered_dict.py13
-rw-r--r--Misc/NEWS2
-rw-r--r--Objects/odictobject.c17
3 files changed, 30 insertions, 2 deletions
diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py
index d6e72a6ed2..2da36d3032 100644
--- a/Lib/test/test_ordered_dict.py
+++ b/Lib/test/test_ordered_dict.py
@@ -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')
diff --git a/Misc/NEWS b/Misc/NEWS
index f99ca495ff..1e29158d96 100644
--- 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,
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
index 5968e3f5d5..22b1f1dfed 100644
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -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);