changeset: 103437:70758c12e888 user: Eric Snow date: Fri Sep 09 11:59:08 2016 -0700 files: Lib/test/test_ordered_dict.py Misc/NEWS Objects/odictobject.c description: Issue #27576: Fix call order in OrderedDict.__init__(). diff -r d5bb5ad5a108 -r 70758c12e888 Lib/test/test_ordered_dict.py --- a/Lib/test/test_ordered_dict.py Fri Sep 09 12:01:10 2016 -0700 +++ b/Lib/test/test_ordered_dict.py Fri Sep 09 11:59:08 2016 -0700 @@ -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 -r d5bb5ad5a108 -r 70758c12e888 Misc/NEWS --- a/Misc/NEWS Fri Sep 09 12:01:10 2016 -0700 +++ b/Misc/NEWS Fri Sep 09 11:59:08 2016 -0700 @@ -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 -r d5bb5ad5a108 -r 70758c12e888 Objects/odictobject.c --- a/Objects/odictobject.c Fri Sep 09 12:01:10 2016 -0700 +++ b/Objects/odictobject.c Fri Sep 09 11:59:08 2016 -0700 @@ -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);