diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -1696,6 +1696,15 @@ self.assertRaises(TypeError, OrderedDict().update, (), ()) self.assertRaises(TypeError, OrderedDict.update) + def test_fromkeys(self): + OrderedDict = self.module.OrderedDict + od = OrderedDict.fromkeys('abc') + self.assertEqual(list(od.items()), [(c, None) for c in 'abc']) + od = OrderedDict.fromkeys('abc', value=None) + self.assertEqual(list(od.items()), [(c, None) for c in 'abc']) + od = OrderedDict.fromkeys('abc', value=0) + self.assertEqual(list(od.items()), [(c, 0) for c in 'abc']) + def test_abc(self): OrderedDict = self.module.OrderedDict self.assertIsInstance(OrderedDict(), MutableMapping) @@ -1801,7 +1810,8 @@ for i in range(8): obj.popitem(True) obj.popitem(True) - self.assertEqual(len(obj), 21) + obj.popitem(last=True) + self.assertEqual(len(obj), 20) def test_pop(self): OrderedDict = self.module.OrderedDict @@ -1825,6 +1835,7 @@ self.assertEqual(m.pop('b', 5), 5) self.assertEqual(m.pop('a', 6), 1) self.assertEqual(m.pop('a', 6), 6) + self.assertEqual(m.pop('a', default=6), 6) with self.assertRaises(KeyError): m.pop('a') @@ -1931,6 +1942,7 @@ self.assertEqual(od.setdefault('x', 10), 10) # make sure 'x' is added to the end self.assertEqual(list(od.items())[-1], ('x', 10)) + self.assertEqual(od.setdefault('g', default=9), 9) # make sure setdefault still works when __missing__ is defined class Missing(OrderedDict): @@ -1962,6 +1974,8 @@ self.assertEqual(list(od), list('cabde')) od.move_to_end('e') self.assertEqual(list(od), list('cabde')) + od.move_to_end('b', last=False) + self.assertEqual(list(od), list('bcade')) with self.assertRaises(KeyError): od.move_to_end('x') with self.assertRaises(KeyError): diff --git a/Objects/odictobject.c b/Objects/odictobject.c --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -930,12 +930,17 @@ "); static PyObject * -odict_fromkeys(PyObject *cls, PyObject *args) +odict_fromkeys(PyObject *cls, PyObject *args, PyObject *kwargs) { + static char *kwlist[] = {"iterable", "value", 0}; PyObject *seq; PyObject *value = Py_None; - if (!PyArg_UnpackTuple(args, "fromkeys", 1, 2, &seq, &value)) /* borrowed */ + + /* both borrowed */ + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:fromkeys", kwlist, + &seq, &value)) { return NULL; + } return _PyDict_FromKeys(cls, seq, value); } @@ -1071,14 +1076,17 @@ /* Skips __missing__() calls. */ static PyObject * -odict_setdefault(register PyODictObject *od, PyObject *args) +odict_setdefault(register PyODictObject *od, PyObject *args, PyObject *kwargs) { + static char *kwlist[] = {"key", "default", 0}; PyObject *key, *result = NULL; PyObject *failobj = Py_None; /* both borrowed */ - if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:setdefault", kwlist, + &key, &failobj)) { return NULL; + } if (PyODict_CheckExact(od)) { result = PyODict_GetItemWithError(od, key); /* borrowed */ @@ -1126,11 +1134,14 @@ /* Skips __missing__() calls. */ static PyObject * -odict_pop(PyObject *od, PyObject *args) +odict_pop(PyObject *od, PyObject *args, PyObject *kwargs) { + static char *kwlist[] = {"key", "default", 0}; PyObject *key, *failobj = NULL; - if (!PyArg_UnpackTuple(args, "pop", 1, 2, &key, &failobj)) { /* borrowed */ + /* borrowed */ + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:pop", kwlist, + &key, &failobj)) { return NULL; } @@ -1202,8 +1213,9 @@ "); static PyObject * -odict_popitem(PyObject *od, PyObject *args) +odict_popitem(PyObject *od, PyObject *args, PyObject *kwargs) { + static char *kwlist[] = {"last", 0}; PyObject *key, *value, *item = NULL, *last = NULL; _ODictNode *node; @@ -1214,8 +1226,11 @@ /* pull the item */ - if (!PyArg_UnpackTuple(args, "popitem", 0, 1, &last)) /* borrowed */ + /* borrowed */ + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:popitem", kwlist, + &last)) { return NULL; + } if (last == NULL || last == Py_True) node = _odict_LAST((PyODictObject *)od); @@ -1360,14 +1375,17 @@ "); static PyObject * -odict_move_to_end(PyODictObject *od, PyObject *args) +odict_move_to_end(PyODictObject *od, PyObject *args, PyObject *kwargs) { + static char *kwlist[] = {"key", "last", 0}; PyObject *key, *last = NULL; Py_ssize_t pos = -1; /* both borrowed */ - if (!PyArg_UnpackTuple(args, "move_to_end", 1, 2, &key, &last)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:move_to_end", kwlist, + &key, &last)) { return NULL; + } if (_odict_EMPTY(od)) { PyErr_SetObject(PyExc_KeyError, key); return NULL; @@ -1439,20 +1457,20 @@ odict_repr__doc__}, {"__setitem__", (PyCFunction)odict_mp_ass_sub, METH_NOARGS, odict_setitem__doc__}, - {"fromkeys", (PyCFunction)odict_fromkeys, METH_VARARGS | METH_CLASS, - odict_fromkeys__doc__}, + {"fromkeys", (PyCFunction)odict_fromkeys, + METH_VARARGS | METH_KEYWORDS | METH_CLASS, odict_fromkeys__doc__}, /* overridden dict methods */ {"__sizeof__", (PyCFunction)odict_sizeof, METH_NOARGS, odict_sizeof__doc__}, {"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS, odict_reduce__doc__}, - {"setdefault", (PyCFunction)odict_setdefault, METH_VARARGS, - odict_setdefault__doc__}, - {"pop", (PyCFunction)odict_pop, METH_VARARGS, - odict_pop__doc__}, - {"popitem", (PyCFunction)odict_popitem, METH_VARARGS, - odict_popitem__doc__}, + {"setdefault", (PyCFunction)odict_setdefault, + METH_VARARGS | METH_KEYWORDS, odict_setdefault__doc__}, + {"pop", (PyCFunction)odict_pop, + METH_VARARGS | METH_KEYWORDS, odict_pop__doc__}, + {"popitem", (PyCFunction)odict_popitem, + METH_VARARGS | METH_KEYWORDS, odict_popitem__doc__}, {"keys", (PyCFunction)odictkeys_new, METH_NOARGS, odict_keys__doc__}, {"values", (PyCFunction)odictvalues_new, METH_NOARGS, @@ -1469,8 +1487,8 @@ /* new methods */ {"__reversed__", (PyCFunction)odict_reversed, METH_NOARGS, odict_reversed__doc__}, - {"move_to_end", (PyCFunction)odict_move_to_end, METH_VARARGS, - odict_move_to_end__doc__}, + {"move_to_end", (PyCFunction)odict_move_to_end, + METH_VARARGS | METH_KEYWORDS, odict_move_to_end__doc__}, {NULL, NULL} /* sentinel */ };