From 6bf3237379b17632db52cb39d181e8bac70173f3 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 19 Jul 2020 09:18:55 +0300 Subject: [PATCH] bpo-41333: Convert OrderedDict.pop() to Argument Clinic (GH-21534) --- .../2020-07-18-18-07-40.bpo-41333.upkHIm.rst | 1 + Objects/clinic/dictobject.c.h | 5 ++- Objects/clinic/odictobject.c.h | 45 ++++++++++++++++++- Objects/dictobject.c | 5 ++- Objects/odictobject.c | 37 +++++++-------- 5 files changed, 68 insertions(+), 25 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-07-18-18-07-40.bpo-41333.upkHIm.rst diff --git a/Misc/NEWS.d/next/Library/2020-07-18-18-07-40.bpo-41333.upkHIm.rst b/Misc/NEWS.d/next/Library/2020-07-18-18-07-40.bpo-41333.upkHIm.rst new file mode 100644 index 00000000000..73e8b119977 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-07-18-18-07-40.bpo-41333.upkHIm.rst @@ -0,0 +1 @@ +:meth:`collections.OrderedDict.pop` is now 2 times faster. diff --git a/Objects/clinic/dictobject.c.h b/Objects/clinic/dictobject.c.h index 7395e3bcebb..beb3f360f86 100644 --- a/Objects/clinic/dictobject.c.h +++ b/Objects/clinic/dictobject.c.h @@ -122,7 +122,8 @@ PyDoc_STRVAR(dict_pop__doc__, "\n" "D.pop(k[,d]) -> v, remove specified key and return the corresponding value.\n" "\n" -"If key is not found, default is returned if given, otherwise KeyError is raised"); +"If the key is not found, return the default if given; otherwise,\n" +"raise a KeyError."); #define DICT_POP_METHODDEF \ {"pop", (PyCFunction)(void(*)(void))dict_pop, METH_FASTCALL, dict_pop__doc__}, @@ -190,4 +191,4 @@ dict___reversed__(PyDictObject *self, PyObject *Py_UNUSED(ignored)) { return dict___reversed___impl(self); } -/*[clinic end generated code: output=4d98145508da8fa3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7b77c16e43d6735a input=a9049054013a1b77]*/ diff --git a/Objects/clinic/odictobject.c.h b/Objects/clinic/odictobject.c.h index f43bc14ce1b..a3ab9ea507f 100644 --- a/Objects/clinic/odictobject.c.h +++ b/Objects/clinic/odictobject.c.h @@ -83,6 +83,49 @@ exit: return return_value; } +PyDoc_STRVAR(OrderedDict_pop__doc__, +"pop($self, /, key, default=)\n" +"--\n" +"\n" +"od.pop(key[,default]) -> v, remove specified key and return the corresponding value.\n" +"\n" +"If the key is not found, return the default if given; otherwise,\n" +"raise a KeyError."); + +#define ORDEREDDICT_POP_METHODDEF \ + {"pop", (PyCFunction)(void(*)(void))OrderedDict_pop, METH_FASTCALL|METH_KEYWORDS, OrderedDict_pop__doc__}, + +static PyObject * +OrderedDict_pop_impl(PyODictObject *self, PyObject *key, + PyObject *default_value); + +static PyObject * +OrderedDict_pop(PyODictObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"key", "default", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "pop", 0}; + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *key; + PyObject *default_value = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + key = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + default_value = args[1]; +skip_optional_pos: + return_value = OrderedDict_pop_impl(self, key, default_value); + +exit: + return return_value; +} + PyDoc_STRVAR(OrderedDict_popitem__doc__, "popitem($self, /, last=True)\n" "--\n" @@ -168,4 +211,4 @@ skip_optional_pos: exit: return return_value; } -/*[clinic end generated code: output=8eb1296df9142908 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e0afaad5b4bb47fe input=a9049054013a1b77]*/ diff --git a/Objects/dictobject.c b/Objects/dictobject.c index b1f11b3e695..ba22489539a 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -3054,12 +3054,13 @@ dict.pop D.pop(k[,d]) -> v, remove specified key and return the corresponding value. -If key is not found, default is returned if given, otherwise KeyError is raised +If the key is not found, return the default if given; otherwise, +raise a KeyError. [clinic start generated code]*/ static PyObject * dict_pop_impl(PyDictObject *self, PyObject *key, PyObject *default_value) -/*[clinic end generated code: output=3abb47b89f24c21c input=eeebec7812190348]*/ +/*[clinic end generated code: output=3abb47b89f24c21c input=e221baa01044c44c]*/ { return _PyDict_Pop((PyObject*)self, key, default_value); } diff --git a/Objects/odictobject.c b/Objects/odictobject.c index d5bf499575d..b4ac560d235 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -1045,30 +1045,28 @@ OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key, /* pop() */ -PyDoc_STRVAR(odict_pop__doc__, -"od.pop(k[,d]) -> v, remove specified key and return the corresponding\n\ - value. If key is not found, d is returned if given, otherwise KeyError\n\ - is raised.\n\ -\n\ - "); - /* forward */ static PyObject * _odict_popkey(PyObject *, PyObject *, PyObject *); /* Skips __missing__() calls. */ +/*[clinic input] +OrderedDict.pop + + key: object + default: object = NULL + +od.pop(key[,default]) -> v, remove specified key and return the corresponding value. + +If the key is not found, return the default if given; otherwise, +raise a KeyError. +[clinic start generated code]*/ + static PyObject * -odict_pop(PyObject *od, PyObject *args, PyObject *kwargs) +OrderedDict_pop_impl(PyODictObject *self, PyObject *key, + PyObject *default_value) +/*[clinic end generated code: output=7a6447d104e7494b input=7efe36601007dff7]*/ { - static char *kwlist[] = {"key", "default", 0}; - PyObject *key, *failobj = NULL; - - /* borrowed */ - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:pop", kwlist, - &key, &failobj)) { - return NULL; - } - - return _odict_popkey(od, key, failobj); + return _odict_popkey((PyObject *)self, key, default_value); } static PyObject * @@ -1362,8 +1360,7 @@ static PyMethodDef odict_methods[] = { {"__reduce__", (PyCFunction)odict_reduce, METH_NOARGS, odict_reduce__doc__}, ORDEREDDICT_SETDEFAULT_METHODDEF - {"pop", (PyCFunction)(void(*)(void))odict_pop, - METH_VARARGS | METH_KEYWORDS, odict_pop__doc__}, + ORDEREDDICT_POP_METHODDEF ORDEREDDICT_POPITEM_METHODDEF {"keys", odictkeys_new, METH_NOARGS, odict_keys__doc__},