From 683cfd90764588ac71c498f86498438c4c514cfa Mon Sep 17 00:00:00 2001 From: Tal Einat Date: Mon, 30 Oct 2017 10:14:28 +0200 Subject: [PATCH 1/6] bpo-20180: itertools.groupby Argument Clinic conversion --- Modules/clinic/itertoolsmodule.c.h | 63 +++++++ Modules/itertoolsmodule.c | 271 ++++++++++++++++------------- 2 files changed, 211 insertions(+), 123 deletions(-) create mode 100644 Modules/clinic/itertoolsmodule.c.h diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h new file mode 100644 index 00000000000000..83b5b6b62d77d0 --- /dev/null +++ b/Modules/clinic/itertoolsmodule.c.h @@ -0,0 +1,63 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(itertools_groupby__doc__, +"groupby(iterable, key=None)\n" +"--\n" +"\n" +"make an iterator that returns consecutive keys and groups from the iterable\n" +"\n" +" iterable\n" +" Elements to divide into groups according to the key function.\n" +" key\n" +" A function computing a key value for each element. If None, key\n" +" defaults to an identity function and returns the element unchanged."); + +static PyObject * +itertools_groupby_impl(PyTypeObject *type, PyObject *iterable, PyObject *key); + +static PyObject * +itertools_groupby(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"iterable", "key", NULL}; + static _PyArg_Parser _parser = {"O|O:groupby", _keywords, 0}; + PyObject *iterable; + PyObject *key = Py_None; + + if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, + &iterable, &key)) { + goto exit; + } + return_value = itertools_groupby_impl(type, iterable, key); + +exit: + return return_value; +} + +static PyObject * +itertools__grouper_impl(PyTypeObject *type, PyObject *parent, + PyObject *tgtkey); + +static PyObject * +itertools__grouper(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + PyObject *parent; + PyObject *tgtkey; + + if ((type == &_grouper_type) && + !_PyArg_NoKeywords("_grouper", kwargs)) { + goto exit; + } + if (!PyArg_ParseTuple(args, "O!O:_grouper", + &groupby_type, &parent, &tgtkey)) { + goto exit; + } + return_value = itertools__grouper_impl(type, parent, tgtkey); + +exit: + return return_value; +} +/*[clinic end generated code: output=ecc325ee9ecf0cf6 input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 8a36755bfa7265..7e8b1b47dcdf40 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -7,6 +7,13 @@ by Raymond D. Hettinger */ +/*[clinic input] +module itertools +class itertools.groupby "groupbyobject *" "&groupby_type" +class itertools._grouper "_grouperobject *" "&_grouper_type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9d506f5bb9177570]*/ + /* groupby object ************************************************************/ @@ -23,16 +30,24 @@ typedef struct { static PyTypeObject groupby_type; static PyObject *_grouper_create(groupbyobject *, PyObject *); +/*[clinic input] +@classmethod +itertools.groupby.__new__ + + iterable: object + Elements to divide into groups according to the key function. + key: object = None + A function computing a key value for each element. If None, key + defaults to an identity function and returns the element unchanged. + +make an iterator that returns consecutive keys and groups from the iterable +[clinic start generated code]*/ + static PyObject * -groupby_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +itertools_groupby_impl(PyTypeObject *type, PyObject *iterable, PyObject *key) +/*[clinic end generated code: output=83016d6c995ed8a5 input=dc17e1c0520e528f]*/ { - static char *kwargs[] = {"iterable", "key", NULL}; groupbyobject *gbo; - PyObject *it, *keyfunc = Py_None; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:groupby", kwargs, - &it, &keyfunc)) - return NULL; gbo = (groupbyobject *)type->tp_alloc(type, 0); if (gbo == NULL) @@ -40,9 +55,9 @@ groupby_new(PyTypeObject *type, PyObject *args, PyObject *kwds) gbo->tgtkey = NULL; gbo->currkey = NULL; gbo->currvalue = NULL; - gbo->keyfunc = keyfunc; - Py_INCREF(keyfunc); - gbo->it = PyObject_GetIter(it); + gbo->keyfunc = key; + Py_INCREF(key); + gbo->it = PyObject_GetIter(iterable); if (gbo->it == NULL) { Py_DECREF(gbo); return NULL; @@ -178,63 +193,6 @@ groupby_setstate(groupbyobject *lz, PyObject *state) PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); -static PyMethodDef groupby_methods[] = { - {"__reduce__", (PyCFunction)groupby_reduce, METH_NOARGS, - reduce_doc}, - {"__setstate__", (PyCFunction)groupby_setstate, METH_O, - setstate_doc}, - {NULL, NULL} /* sentinel */ -}; - -PyDoc_STRVAR(groupby_doc, -"groupby(iterable, key=None) -> make an iterator that returns consecutive\n\ -keys and groups from the iterable. If the key function is not specified or\n\ -is None, the element itself is used for grouping.\n"); - -static PyTypeObject groupby_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.groupby", /* tp_name */ - sizeof(groupbyobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)groupby_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - groupby_doc, /* tp_doc */ - (traverseproc)groupby_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)groupby_next, /* tp_iternext */ - groupby_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - groupby_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - /* _grouper object (internal) ************************************************/ @@ -246,14 +204,20 @@ typedef struct { static PyTypeObject _grouper_type; -static PyObject * -_grouper_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *parent, *tgtkey; +/*[clinic input] +@classmethod +itertools._grouper.__new__ - if (!PyArg_ParseTuple(args, "O!O", &groupby_type, &parent, &tgtkey)) - return NULL; + parent: object(subclass_of='&groupby_type') + tgtkey: object + / +[clinic start generated code]*/ +static PyObject * +itertools__grouper_impl(PyTypeObject *type, PyObject *parent, + PyObject *tgtkey) +/*[clinic end generated code: output=462efb1cdebb5914 input=dc180d7771fc8c59]*/ +{ return _grouper_create((groupbyobject*) parent, tgtkey); } @@ -328,56 +292,6 @@ _grouper_reduce(_grouperobject *lz, PyObject *Py_UNUSED(ignored)) return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->parent, lz->tgtkey); } -static PyMethodDef _grouper_methods[] = { - {"__reduce__", (PyCFunction)_grouper_reduce, METH_NOARGS, - reduce_doc}, - {NULL, NULL} /* sentinel */ -}; - - -static PyTypeObject _grouper_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools._grouper", /* tp_name */ - sizeof(_grouperobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)_grouper_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)_grouper_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)_grouper_next, /* tp_iternext */ - _grouper_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - _grouper_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - /* tee object and with supporting function and objects ***********************/ @@ -4601,6 +4515,117 @@ static PyTypeObject ziplongest_type = { PyObject_GC_Del, /* tp_free */ }; + +#include "clinic/itertoolsmodule.c.h" + + +/* groupby object method and type definitons ********************************/ + +static PyMethodDef groupby_methods[] = { + {"__reduce__", (PyCFunction)groupby_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)groupby_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + +static PyTypeObject groupby_type = { + PyVarObject_HEAD_INIT(NULL, 0) + "itertools.groupby", /* tp_name */ + sizeof(groupbyobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)groupby_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + itertools_groupby__doc__, /* tp_doc */ + (traverseproc)groupby_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)groupby_next, /* tp_iternext */ + groupby_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + itertools_groupby, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + + +/* _grouper object (internal) method and type definitons *********************/ + +static PyMethodDef _grouper_methods[] = { + {"__reduce__", (PyCFunction)_grouper_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + +static PyTypeObject _grouper_type = { + PyVarObject_HEAD_INIT(NULL, 0) + "itertools._grouper", /* tp_name */ + sizeof(_grouperobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)_grouper_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)_grouper_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)_grouper_next, /* tp_iternext */ + _grouper_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + itertools__grouper, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + + /* module level code ********************************************************/ PyDoc_STRVAR(module_doc, From 3ad194193000d4a343f1f9e77131266b62887707 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 10 Sep 2018 02:05:38 -0700 Subject: [PATCH 2/6] Move the method definition arrays and static object definitions back to the original positions. --- Modules/itertoolsmodule.c | 220 ++++++++++++++++++-------------------- 1 file changed, 106 insertions(+), 114 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 7e8b1b47dcdf40..30fae500d6b1bc 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -7,6 +7,10 @@ by Raymond D. Hettinger */ +static PyTypeObject _grouper_type; +static PyTypeObject groupby_type; +#include "clinic/itertoolsmodule.c.h" + /*[clinic input] module itertools class itertools.groupby "groupbyobject *" "&groupby_type" @@ -27,7 +31,6 @@ typedef struct { const void *currgrouper; /* borrowed reference */ } groupbyobject; -static PyTypeObject groupby_type; static PyObject *_grouper_create(groupbyobject *, PyObject *); /*[clinic input] @@ -193,6 +196,58 @@ groupby_setstate(groupbyobject *lz, PyObject *state) PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); +static PyMethodDef groupby_methods[] = { + {"__reduce__", (PyCFunction)groupby_reduce, METH_NOARGS, + reduce_doc}, + {"__setstate__", (PyCFunction)groupby_setstate, METH_O, + setstate_doc}, + {NULL, NULL} /* sentinel */ +}; + +static PyTypeObject groupby_type = { + PyVarObject_HEAD_INIT(NULL, 0) + "itertools.groupby", /* tp_name */ + sizeof(groupbyobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)groupby_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + itertools_groupby__doc__, /* tp_doc */ + (traverseproc)groupby_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)groupby_next, /* tp_iternext */ + groupby_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + itertools_groupby, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + /* _grouper object (internal) ************************************************/ @@ -202,8 +257,6 @@ typedef struct { PyObject *tgtkey; } _grouperobject; -static PyTypeObject _grouper_type; - /*[clinic input] @classmethod itertools._grouper.__new__ @@ -293,6 +346,56 @@ _grouper_reduce(_grouperobject *lz, PyObject *Py_UNUSED(ignored)) } +static PyMethodDef _grouper_methods[] = { + {"__reduce__", (PyCFunction)_grouper_reduce, METH_NOARGS, + reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + +static PyTypeObject _grouper_type = { + PyVarObject_HEAD_INIT(NULL, 0) + "itertools._grouper", /* tp_name */ + sizeof(_grouperobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)_grouper_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)_grouper_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)_grouper_next, /* tp_iternext */ + _grouper_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + itertools__grouper, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + + /* tee object and with supporting function and objects ***********************/ /* The teedataobject pre-allocates space for LINKCELLS number of objects. @@ -4515,117 +4618,6 @@ static PyTypeObject ziplongest_type = { PyObject_GC_Del, /* tp_free */ }; - -#include "clinic/itertoolsmodule.c.h" - - -/* groupby object method and type definitons ********************************/ - -static PyMethodDef groupby_methods[] = { - {"__reduce__", (PyCFunction)groupby_reduce, METH_NOARGS, - reduce_doc}, - {"__setstate__", (PyCFunction)groupby_setstate, METH_O, - setstate_doc}, - {NULL, NULL} /* sentinel */ -}; - -static PyTypeObject groupby_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.groupby", /* tp_name */ - sizeof(groupbyobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)groupby_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - itertools_groupby__doc__, /* tp_doc */ - (traverseproc)groupby_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)groupby_next, /* tp_iternext */ - groupby_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools_groupby, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - - -/* _grouper object (internal) method and type definitons *********************/ - -static PyMethodDef _grouper_methods[] = { - {"__reduce__", (PyCFunction)_grouper_reduce, METH_NOARGS, - reduce_doc}, - {NULL, NULL} /* sentinel */ -}; - -static PyTypeObject _grouper_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools._grouper", /* tp_name */ - sizeof(_grouperobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)_grouper_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)_grouper_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)_grouper_next, /* tp_iternext */ - _grouper_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itertools__grouper, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - - /* module level code ********************************************************/ PyDoc_STRVAR(module_doc, From fd66cd6514bd76328b33365d26ebef826ddb8dc5 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 10 Sep 2018 02:23:33 -0700 Subject: [PATCH 3/6] Restore original variable names --- Modules/clinic/itertoolsmodule.c.h | 12 ++++++------ Modules/itertoolsmodule.c | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index 83b5b6b62d77d0..a9c2448b3388d0 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -15,7 +15,7 @@ PyDoc_STRVAR(itertools_groupby__doc__, " defaults to an identity function and returns the element unchanged."); static PyObject * -itertools_groupby_impl(PyTypeObject *type, PyObject *iterable, PyObject *key); +itertools_groupby_impl(PyTypeObject *type, PyObject *it, PyObject *keyfunc); static PyObject * itertools_groupby(PyTypeObject *type, PyObject *args, PyObject *kwargs) @@ -23,14 +23,14 @@ itertools_groupby(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; static const char * const _keywords[] = {"iterable", "key", NULL}; static _PyArg_Parser _parser = {"O|O:groupby", _keywords, 0}; - PyObject *iterable; - PyObject *key = Py_None; + PyObject *it; + PyObject *keyfunc = Py_None; if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, - &iterable, &key)) { + &it, &keyfunc)) { goto exit; } - return_value = itertools_groupby_impl(type, iterable, key); + return_value = itertools_groupby_impl(type, it, keyfunc); exit: return return_value; @@ -60,4 +60,4 @@ itertools__grouper(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=ecc325ee9ecf0cf6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=82794a1bf512c104 input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 30fae500d6b1bc..003d5e91c499b0 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -37,9 +37,9 @@ static PyObject *_grouper_create(groupbyobject *, PyObject *); @classmethod itertools.groupby.__new__ - iterable: object + iterable as it: object Elements to divide into groups according to the key function. - key: object = None + key as keyfunc: object = None A function computing a key value for each element. If None, key defaults to an identity function and returns the element unchanged. @@ -47,8 +47,8 @@ make an iterator that returns consecutive keys and groups from the iterable [clinic start generated code]*/ static PyObject * -itertools_groupby_impl(PyTypeObject *type, PyObject *iterable, PyObject *key) -/*[clinic end generated code: output=83016d6c995ed8a5 input=dc17e1c0520e528f]*/ +itertools_groupby_impl(PyTypeObject *type, PyObject *it, PyObject *keyfunc) +/*[clinic end generated code: output=cbb1ae3a90fd4141 input=25a2c2e644462895]*/ { groupbyobject *gbo; @@ -58,9 +58,9 @@ itertools_groupby_impl(PyTypeObject *type, PyObject *iterable, PyObject *key) gbo->tgtkey = NULL; gbo->currkey = NULL; gbo->currvalue = NULL; - gbo->keyfunc = key; - Py_INCREF(key); - gbo->it = PyObject_GetIter(iterable); + gbo->keyfunc = keyfunc; + Py_INCREF(keyfunc); + gbo->it = PyObject_GetIter(it); if (gbo->it == NULL) { Py_DECREF(gbo); return NULL; @@ -345,13 +345,13 @@ _grouper_reduce(_grouperobject *lz, PyObject *Py_UNUSED(ignored)) return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->parent, lz->tgtkey); } - static PyMethodDef _grouper_methods[] = { {"__reduce__", (PyCFunction)_grouper_reduce, METH_NOARGS, reduce_doc}, {NULL, NULL} /* sentinel */ }; + static PyTypeObject _grouper_type = { PyVarObject_HEAD_INIT(NULL, 0) "itertools._grouper", /* tp_name */ From 0c418ec54efbfec618f55b066efeea218d0727b3 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 10 Sep 2018 02:30:28 -0700 Subject: [PATCH 4/6] Restore the original wording for describing the key function --- Modules/clinic/itertoolsmodule.c.h | 7 ++++--- Modules/itertoolsmodule.c | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h index a9c2448b3388d0..68e67494bc9366 100644 --- a/Modules/clinic/itertoolsmodule.c.h +++ b/Modules/clinic/itertoolsmodule.c.h @@ -11,8 +11,9 @@ PyDoc_STRVAR(itertools_groupby__doc__, " iterable\n" " Elements to divide into groups according to the key function.\n" " key\n" -" A function computing a key value for each element. If None, key\n" -" defaults to an identity function and returns the element unchanged."); +" A function for computing the group category for each element.\n" +" If the key function is not specified or is None, the element itself\n" +" is used for grouping."); static PyObject * itertools_groupby_impl(PyTypeObject *type, PyObject *it, PyObject *keyfunc); @@ -60,4 +61,4 @@ itertools__grouper(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=82794a1bf512c104 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=82e10c91569d2b95 input=a9049054013a1b77]*/ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 003d5e91c499b0..55ff08db8b5a4b 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -40,15 +40,16 @@ itertools.groupby.__new__ iterable as it: object Elements to divide into groups according to the key function. key as keyfunc: object = None - A function computing a key value for each element. If None, key - defaults to an identity function and returns the element unchanged. + A function for computing the group category for each element. + If the key function is not specified or is None, the element itself + is used for grouping. make an iterator that returns consecutive keys and groups from the iterable [clinic start generated code]*/ static PyObject * itertools_groupby_impl(PyTypeObject *type, PyObject *it, PyObject *keyfunc) -/*[clinic end generated code: output=cbb1ae3a90fd4141 input=25a2c2e644462895]*/ +/*[clinic end generated code: output=cbb1ae3a90fd4141 input=6b3d123e87ff65a1]*/ { groupbyobject *gbo; From af837243d5ef416757d6696cce8e689427e72d9d Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 10 Sep 2018 03:26:30 -0700 Subject: [PATCH 5/6] Move module level clinic input to section for module level code --- Modules/itertoolsmodule.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 55ff08db8b5a4b..9281a67cb91735 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -7,17 +7,10 @@ by Raymond D. Hettinger */ -static PyTypeObject _grouper_type; static PyTypeObject groupby_type; +static PyTypeObject _grouper_type; #include "clinic/itertoolsmodule.c.h" -/*[clinic input] -module itertools -class itertools.groupby "groupbyobject *" "&groupby_type" -class itertools._grouper "_grouperobject *" "&_grouper_type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9d506f5bb9177570]*/ - /* groupby object ************************************************************/ @@ -4621,6 +4614,14 @@ static PyTypeObject ziplongest_type = { /* module level code ********************************************************/ +/*[clinic input] +module itertools +class itertools.groupby "groupbyobject *" "&groupby_type" +class itertools._grouper "_grouperobject *" "&_grouper_type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9d506f5bb9177570]*/ + + PyDoc_STRVAR(module_doc, "Functional tools for creating and using iterators.\n\ \n\ From 5e7734ba411f59a649d1c00a046243f5344aa1dc Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 10 Sep 2018 03:44:56 -0700 Subject: [PATCH 6/6] Fix clinic dependency by moving module clinic input back to the top --- Modules/itertoolsmodule.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 9281a67cb91735..3ad7e5c806519e 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -7,6 +7,13 @@ by Raymond D. Hettinger */ +/*[clinic input] +module itertools +class itertools.groupby "groupbyobject *" "&groupby_type" +class itertools._grouper "_grouperobject *" "&_grouper_type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9d506f5bb9177570]*/ + static PyTypeObject groupby_type; static PyTypeObject _grouper_type; #include "clinic/itertoolsmodule.c.h" @@ -4614,14 +4621,6 @@ static PyTypeObject ziplongest_type = { /* module level code ********************************************************/ -/*[clinic input] -module itertools -class itertools.groupby "groupbyobject *" "&groupby_type" -class itertools._grouper "_grouperobject *" "&_grouper_type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9d506f5bb9177570]*/ - - PyDoc_STRVAR(module_doc, "Functional tools for creating and using iterators.\n\ \n\