gh-101277: Finalise isolating itertools (GH-101305)

Add repeat, islice, chain, tee, teedataobject, and batched types to module state.

Automerge-Triggered-By: GH:erlend-aasland
This commit is contained in:
Erlend E. Aasland 2023-02-10 12:58:14 +01:00 committed by GitHub
parent d40a23c0a1
commit 826bf0e695
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 220 additions and 344 deletions

View File

@ -0,0 +1,2 @@
Remove global state from :mod:`itertools` module (:pep:`687`). Patches by
Erlend E. Aasland.

View File

@ -232,7 +232,7 @@ static PyObject *
itertools_teedataobject(PyTypeObject *type, PyObject *args, PyObject *kwargs) itertools_teedataobject(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
PyTypeObject *base_tp = &teedataobject_type; PyTypeObject *base_tp = clinic_state()->teedataobject_type;
PyObject *it; PyObject *it;
PyObject *values; PyObject *values;
PyObject *next; PyObject *next;
@ -270,7 +270,7 @@ static PyObject *
itertools__tee(PyTypeObject *type, PyObject *args, PyObject *kwargs) itertools__tee(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
PyTypeObject *base_tp = &tee_type; PyTypeObject *base_tp = clinic_state()->tee_type;
PyObject *iterable; PyObject *iterable;
if ((type == base_tp || type->tp_init == base_tp->tp_init) && if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
@ -913,4 +913,4 @@ skip_optional_pos:
exit: exit:
return return_value; return return_value;
} }
/*[clinic end generated code: output=a08b58d7dac825da input=a9049054013a1b77]*/ /*[clinic end generated code: output=111cbd102c2a23c9 input=a9049054013a1b77]*/

View File

@ -5,6 +5,7 @@
#include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_object.h" // _PyObject_GC_TRACK() #include "pycore_object.h" // _PyObject_GC_TRACK()
#include "pycore_tuple.h" // _PyTuple_ITEMS() #include "pycore_tuple.h" // _PyTuple_ITEMS()
#include "structmember.h" // PyMemberDef
#include <stddef.h> // offsetof() #include <stddef.h> // offsetof()
/* Itertools module written and maintained /* Itertools module written and maintained
@ -13,6 +14,8 @@
typedef struct { typedef struct {
PyTypeObject *accumulate_type; PyTypeObject *accumulate_type;
PyTypeObject *batched_type;
PyTypeObject *chain_type;
PyTypeObject *combinations_type; PyTypeObject *combinations_type;
PyTypeObject *compress_type; PyTypeObject *compress_type;
PyTypeObject *count_type; PyTypeObject *count_type;
@ -22,11 +25,15 @@ typedef struct {
PyTypeObject *filterfalse_type; PyTypeObject *filterfalse_type;
PyTypeObject *groupby_type; PyTypeObject *groupby_type;
PyTypeObject *_grouper_type; PyTypeObject *_grouper_type;
PyTypeObject *islice_type;
PyTypeObject *pairwise_type; PyTypeObject *pairwise_type;
PyTypeObject *permutations_type; PyTypeObject *permutations_type;
PyTypeObject *product_type; PyTypeObject *product_type;
PyTypeObject *repeat_type;
PyTypeObject *starmap_type; PyTypeObject *starmap_type;
PyTypeObject *takewhile_type; PyTypeObject *takewhile_type;
PyTypeObject *tee_type;
PyTypeObject *teedataobject_type;
PyTypeObject *ziplongest_type; PyTypeObject *ziplongest_type;
} itertools_state; } itertools_state;
@ -60,14 +67,14 @@ find_state_by_type(PyTypeObject *tp)
module itertools module itertools
class itertools.groupby "groupbyobject *" "clinic_state()->groupby_type" class itertools.groupby "groupbyobject *" "clinic_state()->groupby_type"
class itertools._grouper "_grouperobject *" "clinic_state()->_grouper_type" class itertools._grouper "_grouperobject *" "clinic_state()->_grouper_type"
class itertools.teedataobject "teedataobject *" "&teedataobject_type" class itertools.teedataobject "teedataobject *" "clinic_state()->teedataobject_type"
class itertools._tee "teeobject *" "&tee_type" class itertools._tee "teeobject *" "clinic_state()->tee_type"
class itertools.batched "batchedobject *" "&batched_type" class itertools.batched "batchedobject *" "clinic_state()->batched_type"
class itertools.cycle "cycleobject *" "clinic_state()->cycle_type" class itertools.cycle "cycleobject *" "clinic_state()->cycle_type"
class itertools.dropwhile "dropwhileobject *" "clinic_state()->dropwhile_type" class itertools.dropwhile "dropwhileobject *" "clinic_state()->dropwhile_type"
class itertools.takewhile "takewhileobject *" "clinic_state()->takewhile_type" class itertools.takewhile "takewhileobject *" "clinic_state()->takewhile_type"
class itertools.starmap "starmapobject *" "clinic_state()->starmap_type" class itertools.starmap "starmapobject *" "clinic_state()->starmap_type"
class itertools.chain "chainobject *" "&chain_type" class itertools.chain "chainobject *" "clinic_state()->chain_type"
class itertools.combinations "combinationsobject *" "clinic_state()->combinations_type" class itertools.combinations "combinationsobject *" "clinic_state()->combinations_type"
class itertools.combinations_with_replacement "cwr_object *" "clinic_state()->cwr_type" class itertools.combinations_with_replacement "cwr_object *" "clinic_state()->cwr_type"
class itertools.permutations "permutationsobject *" "clinic_state()->permutations_type" class itertools.permutations "permutationsobject *" "clinic_state()->permutations_type"
@ -77,11 +84,7 @@ class itertools.filterfalse "filterfalseobject *" "clinic_state()->filterfalse_t
class itertools.count "countobject *" "clinic_state()->count_type" class itertools.count "countobject *" "clinic_state()->count_type"
class itertools.pairwise "pairwiseobject *" "clinic_state()->pairwise_type" class itertools.pairwise "pairwiseobject *" "clinic_state()->pairwise_type"
[clinic start generated code]*/ [clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=28ffff5c0c93eed7]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=aa48fe4de9d4080f]*/
static PyTypeObject teedataobject_type;
static PyTypeObject tee_type;
static PyTypeObject batched_type;
#define clinic_state() (find_state_by_type(type)) #define clinic_state() (find_state_by_type(type))
#define clinic_state_by_cls() (get_module_state_by_cls(base_tp)) #define clinic_state_by_cls() (get_module_state_by_cls(base_tp))
@ -162,17 +165,18 @@ batched_new_impl(PyTypeObject *type, PyObject *iterable, Py_ssize_t n)
static void static void
batched_dealloc(batchedobject *bo) batched_dealloc(batchedobject *bo)
{ {
PyTypeObject *tp = Py_TYPE(bo);
PyObject_GC_UnTrack(bo); PyObject_GC_UnTrack(bo);
Py_XDECREF(bo->it); Py_XDECREF(bo->it);
Py_TYPE(bo)->tp_free(bo); tp->tp_free(bo);
Py_DECREF(tp);
} }
static int static int
batched_traverse(batchedobject *bo, visitproc visit, void *arg) batched_traverse(batchedobject *bo, visitproc visit, void *arg)
{ {
if (bo->it != NULL) { Py_VISIT(Py_TYPE(bo));
Py_VISIT(bo->it); Py_VISIT(bo->it);
}
return 0; return 0;
} }
@ -222,48 +226,25 @@ batched_next(batchedobject *bo)
return result; return result;
} }
static PyTypeObject batched_type = { static PyType_Slot batched_slots[] = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) {Py_tp_dealloc, batched_dealloc},
"itertools.batched", /* tp_name */ {Py_tp_getattro, PyObject_GenericGetAttr},
sizeof(batchedobject), /* tp_basicsize */ {Py_tp_doc, (void *)batched_new__doc__},
0, /* tp_itemsize */ {Py_tp_traverse, batched_traverse},
/* methods */ {Py_tp_iter, PyObject_SelfIter},
(destructor)batched_dealloc, /* tp_dealloc */ {Py_tp_iternext, batched_next},
0, /* tp_vectorcall_offset */ {Py_tp_alloc, PyType_GenericAlloc},
0, /* tp_getattr */ {Py_tp_new, batched_new},
0, /* tp_setattr */ {Py_tp_free, PyObject_GC_Del},
0, /* tp_as_async */ {0, NULL},
0, /* tp_repr */ };
0, /* tp_as_number */
0, /* tp_as_sequence */ static PyType_Spec batched_spec = {
0, /* tp_as_mapping */ .name = "itertools.batched",
0, /* tp_hash */ .basicsize = sizeof(batchedobject),
0, /* tp_call */ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
0, /* tp_str */ Py_TPFLAGS_IMMUTABLETYPE),
PyObject_GenericGetAttr, /* tp_getattro */ .slots = batched_slots,
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
batched_new__doc__, /* tp_doc */
(traverseproc)batched_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)batched_next, /* tp_iternext */
0, /* 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 */
PyType_GenericAlloc, /* tp_alloc */
batched_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
}; };
@ -737,14 +718,15 @@ typedef struct {
teedataobject *dataobj; teedataobject *dataobj;
int index; /* 0 <= index <= LINKCELLS */ int index; /* 0 <= index <= LINKCELLS */
PyObject *weakreflist; PyObject *weakreflist;
itertools_state *state;
} teeobject; } teeobject;
static PyObject * static PyObject *
teedataobject_newinternal(PyObject *it) teedataobject_newinternal(itertools_state *state, PyObject *it)
{ {
teedataobject *tdo; teedataobject *tdo;
tdo = PyObject_GC_New(teedataobject, &teedataobject_type); tdo = PyObject_GC_New(teedataobject, state->teedataobject_type);
if (tdo == NULL) if (tdo == NULL)
return NULL; return NULL;
@ -757,10 +739,10 @@ teedataobject_newinternal(PyObject *it)
} }
static PyObject * static PyObject *
teedataobject_jumplink(teedataobject *tdo) teedataobject_jumplink(itertools_state *state, teedataobject *tdo)
{ {
if (tdo->nextlink == NULL) if (tdo->nextlink == NULL)
tdo->nextlink = teedataobject_newinternal(tdo->it); tdo->nextlink = teedataobject_newinternal(state, tdo->it);
return Py_XNewRef(tdo->nextlink); return Py_XNewRef(tdo->nextlink);
} }
@ -796,6 +778,7 @@ teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg)
{ {
int i; int i;
Py_VISIT(Py_TYPE(tdo));
Py_VISIT(tdo->it); Py_VISIT(tdo->it);
for (i = 0; i < tdo->numread; i++) for (i = 0; i < tdo->numread; i++)
Py_VISIT(tdo->values[i]); Py_VISIT(tdo->values[i]);
@ -804,9 +787,9 @@ teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg)
} }
static void static void
teedataobject_safe_decref(PyObject *obj) teedataobject_safe_decref(PyObject *obj, PyTypeObject *tdo_type)
{ {
while (obj && Py_IS_TYPE(obj, &teedataobject_type) && while (obj && Py_IS_TYPE(obj, tdo_type) &&
Py_REFCNT(obj) == 1) { Py_REFCNT(obj) == 1) {
PyObject *nextlink = ((teedataobject *)obj)->nextlink; PyObject *nextlink = ((teedataobject *)obj)->nextlink;
((teedataobject *)obj)->nextlink = NULL; ((teedataobject *)obj)->nextlink = NULL;
@ -826,16 +809,19 @@ teedataobject_clear(teedataobject *tdo)
Py_CLEAR(tdo->values[i]); Py_CLEAR(tdo->values[i]);
tmp = tdo->nextlink; tmp = tdo->nextlink;
tdo->nextlink = NULL; tdo->nextlink = NULL;
teedataobject_safe_decref(tmp); itertools_state *state = get_module_state_by_cls(Py_TYPE(tdo));
teedataobject_safe_decref(tmp, state->teedataobject_type);
return 0; return 0;
} }
static void static void
teedataobject_dealloc(teedataobject *tdo) teedataobject_dealloc(teedataobject *tdo)
{ {
PyTypeObject *tp = Py_TYPE(tdo);
PyObject_GC_UnTrack(tdo); PyObject_GC_UnTrack(tdo);
teedataobject_clear(tdo); teedataobject_clear(tdo);
PyObject_GC_Del(tdo); PyObject_GC_Del(tdo);
Py_DECREF(tp);
} }
static PyObject * static PyObject *
@ -874,9 +860,10 @@ itertools_teedataobject_impl(PyTypeObject *type, PyObject *it,
teedataobject *tdo; teedataobject *tdo;
Py_ssize_t i, len; Py_ssize_t i, len;
assert(type == &teedataobject_type); itertools_state *state = get_module_state_by_cls(type);
assert(type == state->teedataobject_type);
tdo = (teedataobject *)teedataobject_newinternal(it); tdo = (teedataobject *)teedataobject_newinternal(state, it);
if (!tdo) if (!tdo)
return NULL; return NULL;
@ -892,7 +879,7 @@ itertools_teedataobject_impl(PyTypeObject *type, PyObject *it,
if (len == LINKCELLS) { if (len == LINKCELLS) {
if (next != Py_None) { if (next != Py_None) {
if (!Py_IS_TYPE(next, &teedataobject_type)) if (!Py_IS_TYPE(next, state->teedataobject_type))
goto err; goto err;
assert(tdo->nextlink == NULL); assert(tdo->nextlink == NULL);
tdo->nextlink = Py_NewRef(next); tdo->nextlink = Py_NewRef(next);
@ -915,47 +902,24 @@ static PyMethodDef teedataobject_methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static PyTypeObject teedataobject_type = { static PyType_Slot teedataobject_slots[] = {
PyVarObject_HEAD_INIT(0, 0) /* Must fill in type value later */ {Py_tp_dealloc, teedataobject_dealloc},
"itertools._tee_dataobject", /* tp_name */ {Py_tp_getattro, PyObject_GenericGetAttr},
sizeof(teedataobject), /* tp_basicsize */ {Py_tp_doc, (void *)itertools_teedataobject__doc__},
0, /* tp_itemsize */ {Py_tp_traverse, teedataobject_traverse},
/* methods */ {Py_tp_clear, teedataobject_clear},
(destructor)teedataobject_dealloc, /* tp_dealloc */ {Py_tp_methods, teedataobject_methods},
0, /* tp_vectorcall_offset */ {Py_tp_new, itertools_teedataobject},
0, /* tp_getattr */ {Py_tp_free, PyObject_GC_Del},
0, /* tp_setattr */ {0, NULL},
0, /* tp_as_async */ };
0, /* tp_repr */
0, /* tp_as_number */ static PyType_Spec teedataobject_spec = {
0, /* tp_as_sequence */ .name = "itertools._tee_dataobject",
0, /* tp_as_mapping */ .basicsize = sizeof(teedataobject),
0, /* tp_hash */ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
0, /* tp_call */ Py_TPFLAGS_IMMUTABLETYPE),
0, /* tp_str */ .slots = teedataobject_slots,
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
itertools_teedataobject__doc__, /* tp_doc */
(traverseproc)teedataobject_traverse, /* tp_traverse */
(inquiry)teedataobject_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
teedataobject_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_teedataobject, /* tp_new */
PyObject_GC_Del, /* tp_free */
}; };
@ -965,7 +929,7 @@ tee_next(teeobject *to)
PyObject *value, *link; PyObject *value, *link;
if (to->index >= LINKCELLS) { if (to->index >= LINKCELLS) {
link = teedataobject_jumplink(to->dataobj); link = teedataobject_jumplink(to->state, to->dataobj);
if (link == NULL) if (link == NULL)
return NULL; return NULL;
Py_SETREF(to->dataobj, (teedataobject *)link); Py_SETREF(to->dataobj, (teedataobject *)link);
@ -981,6 +945,7 @@ tee_next(teeobject *to)
static int static int
tee_traverse(teeobject *to, visitproc visit, void *arg) tee_traverse(teeobject *to, visitproc visit, void *arg)
{ {
Py_VISIT(Py_TYPE(to));
Py_VISIT((PyObject *)to->dataobj); Py_VISIT((PyObject *)to->dataobj);
return 0; return 0;
} }
@ -990,12 +955,13 @@ tee_copy(teeobject *to, PyObject *Py_UNUSED(ignored))
{ {
teeobject *newto; teeobject *newto;
newto = PyObject_GC_New(teeobject, &tee_type); newto = PyObject_GC_New(teeobject, Py_TYPE(to));
if (newto == NULL) if (newto == NULL)
return NULL; return NULL;
newto->dataobj = (teedataobject*)Py_NewRef(to->dataobj); newto->dataobj = (teedataobject*)Py_NewRef(to->dataobj);
newto->index = to->index; newto->index = to->index;
newto->weakreflist = NULL; newto->weakreflist = NULL;
newto->state = to->state;
PyObject_GC_Track(newto); PyObject_GC_Track(newto);
return (PyObject *)newto; return (PyObject *)newto;
} }
@ -1003,7 +969,7 @@ tee_copy(teeobject *to, PyObject *Py_UNUSED(ignored))
PyDoc_STRVAR(teecopy_doc, "Returns an independent iterator."); PyDoc_STRVAR(teecopy_doc, "Returns an independent iterator.");
static PyObject * static PyObject *
tee_fromiterable(PyObject *iterable) tee_fromiterable(itertools_state *state, PyObject *iterable)
{ {
teeobject *to; teeobject *to;
PyObject *it; PyObject *it;
@ -1011,17 +977,17 @@ tee_fromiterable(PyObject *iterable)
it = PyObject_GetIter(iterable); it = PyObject_GetIter(iterable);
if (it == NULL) if (it == NULL)
return NULL; return NULL;
if (PyObject_TypeCheck(it, &tee_type)) { if (PyObject_TypeCheck(it, state->tee_type)) {
to = (teeobject *)tee_copy((teeobject *)it, NULL); to = (teeobject *)tee_copy((teeobject *)it, NULL);
goto done; goto done;
} }
PyObject *dataobj = teedataobject_newinternal(it); PyObject *dataobj = teedataobject_newinternal(state, it);
if (!dataobj) { if (!dataobj) {
to = NULL; to = NULL;
goto done; goto done;
} }
to = PyObject_GC_New(teeobject, &tee_type); to = PyObject_GC_New(teeobject, state->tee_type);
if (to == NULL) { if (to == NULL) {
Py_DECREF(dataobj); Py_DECREF(dataobj);
goto done; goto done;
@ -1029,6 +995,7 @@ tee_fromiterable(PyObject *iterable)
to->dataobj = (teedataobject *)dataobj; to->dataobj = (teedataobject *)dataobj;
to->index = 0; to->index = 0;
to->weakreflist = NULL; to->weakreflist = NULL;
to->state = state;
PyObject_GC_Track(to); PyObject_GC_Track(to);
done: done:
Py_DECREF(it); Py_DECREF(it);
@ -1047,7 +1014,8 @@ static PyObject *
itertools__tee_impl(PyTypeObject *type, PyObject *iterable) itertools__tee_impl(PyTypeObject *type, PyObject *iterable)
/*[clinic end generated code: output=b02d3fd26c810c3f input=adc0779d2afe37a2]*/ /*[clinic end generated code: output=b02d3fd26c810c3f input=adc0779d2afe37a2]*/
{ {
return tee_fromiterable(iterable); itertools_state *state = get_module_state_by_cls(type);
return tee_fromiterable(state, iterable);
} }
static int static int
@ -1062,9 +1030,11 @@ tee_clear(teeobject *to)
static void static void
tee_dealloc(teeobject *to) tee_dealloc(teeobject *to)
{ {
PyTypeObject *tp = Py_TYPE(to);
PyObject_GC_UnTrack(to); PyObject_GC_UnTrack(to);
tee_clear(to); tee_clear(to);
PyObject_GC_Del(to); PyObject_GC_Del(to);
Py_DECREF(tp);
} }
static PyObject * static PyObject *
@ -1082,7 +1052,8 @@ tee_setstate(teeobject *to, PyObject *state)
PyErr_SetString(PyExc_TypeError, "state is not a tuple"); PyErr_SetString(PyExc_TypeError, "state is not a tuple");
return NULL; return NULL;
} }
if (!PyArg_ParseTuple(state, "O!i", &teedataobject_type, &tdo, &index)) { PyTypeObject *tdo_type = to->state->teedataobject_type;
if (!PyArg_ParseTuple(state, "O!i", tdo_type, &tdo, &index)) {
return NULL; return NULL;
} }
if (index < 0 || index > LINKCELLS) { if (index < 0 || index > LINKCELLS) {
@ -1102,47 +1073,31 @@ static PyMethodDef tee_methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static PyTypeObject tee_type = { static PyMemberDef tee_members[] = {
PyVarObject_HEAD_INIT(NULL, 0) {"__weaklistoffset__", T_PYSSIZET, offsetof(teeobject, weakreflist), READONLY},
"itertools._tee", /* tp_name */ {NULL},
sizeof(teeobject), /* tp_basicsize */ };
0, /* tp_itemsize */
/* methods */ static PyType_Slot tee_slots[] = {
(destructor)tee_dealloc, /* tp_dealloc */ {Py_tp_dealloc, tee_dealloc},
0, /* tp_vectorcall_offset */ {Py_tp_doc, (void *)itertools__tee__doc__},
0, /* tp_getattr */ {Py_tp_traverse, tee_traverse},
0, /* tp_setattr */ {Py_tp_clear, tee_clear},
0, /* tp_as_async */ {Py_tp_iter, PyObject_SelfIter},
0, /* tp_repr */ {Py_tp_iternext, tee_next},
0, /* tp_as_number */ {Py_tp_methods, tee_methods},
0, /* tp_as_sequence */ {Py_tp_members, tee_members},
0, /* tp_as_mapping */ {Py_tp_new, itertools__tee},
0, /* tp_hash */ {Py_tp_free, PyObject_GC_Del},
0, /* tp_call */ {0, NULL},
0, /* tp_str */ };
0, /* tp_getattro */
0, /* tp_setattro */ static PyType_Spec tee_spec = {
0, /* tp_as_buffer */ .name = "itertools._tee",
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ .basicsize = sizeof(teeobject),
itertools__tee__doc__, /* tp_doc */ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
(traverseproc)tee_traverse, /* tp_traverse */ Py_TPFLAGS_IMMUTABLETYPE),
(inquiry)tee_clear, /* tp_clear */ .slots = tee_slots,
0, /* tp_richcompare */
offsetof(teeobject, weakreflist), /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)tee_next, /* tp_iternext */
tee_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__tee, /* tp_new */
PyObject_GC_Del, /* tp_free */
}; };
/*[clinic input] /*[clinic input]
@ -1184,7 +1139,8 @@ itertools_tee_impl(PyObject *module, PyObject *iterable, Py_ssize_t n)
copyable = it; copyable = it;
} }
else { else {
copyable = tee_fromiterable(it); itertools_state *state = get_module_state(module);
copyable = tee_fromiterable(state, it);
Py_DECREF(it); Py_DECREF(it);
if (copyable == NULL) { if (copyable == NULL) {
Py_DECREF(result); Py_DECREF(result);
@ -1682,8 +1638,6 @@ typedef struct {
Py_ssize_t cnt; Py_ssize_t cnt;
} isliceobject; } isliceobject;
static PyTypeObject islice_type;
static PyObject * static PyObject *
islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
@ -1693,7 +1647,9 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Py_ssize_t numargs; Py_ssize_t numargs;
isliceobject *lz; isliceobject *lz;
if ((type == &islice_type || type->tp_init == islice_type.tp_init) && itertools_state *st = find_state_by_type(type);
PyTypeObject *islice_type = st->islice_type;
if ((type == islice_type || type->tp_init == islice_type->tp_init) &&
!_PyArg_NoKeywords("islice", kwds)) !_PyArg_NoKeywords("islice", kwds))
return NULL; return NULL;
@ -1772,14 +1728,17 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void static void
islice_dealloc(isliceobject *lz) islice_dealloc(isliceobject *lz)
{ {
PyTypeObject *tp = Py_TYPE(lz);
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_XDECREF(lz->it); Py_XDECREF(lz->it);
Py_TYPE(lz)->tp_free(lz); tp->tp_free(lz);
Py_DECREF(tp);
} }
static int static int
islice_traverse(isliceobject *lz, visitproc visit, void *arg) islice_traverse(isliceobject *lz, visitproc visit, void *arg)
{ {
Py_VISIT(Py_TYPE(lz));
Py_VISIT(lz->it); Py_VISIT(lz->it);
return 0; return 0;
} }
@ -1885,48 +1844,25 @@ specified as another value, step determines how many values are\n\
skipped between successive calls. Works like a slice() on a list\n\ skipped between successive calls. Works like a slice() on a list\n\
but returns an iterator."); but returns an iterator.");
static PyTypeObject islice_type = { static PyType_Slot islice_slots[] = {
PyVarObject_HEAD_INIT(NULL, 0) {Py_tp_dealloc, islice_dealloc},
"itertools.islice", /* tp_name */ {Py_tp_getattro, PyObject_GenericGetAttr},
sizeof(isliceobject), /* tp_basicsize */ {Py_tp_doc, (void *)islice_doc},
0, /* tp_itemsize */ {Py_tp_traverse, islice_traverse},
/* methods */ {Py_tp_iter, PyObject_SelfIter},
(destructor)islice_dealloc, /* tp_dealloc */ {Py_tp_iternext, islice_next},
0, /* tp_vectorcall_offset */ {Py_tp_methods, islice_methods},
0, /* tp_getattr */ {Py_tp_new, islice_new},
0, /* tp_setattr */ {Py_tp_free, PyObject_GC_Del},
0, /* tp_as_async */ {0, NULL},
0, /* tp_repr */ };
0, /* tp_as_number */
0, /* tp_as_sequence */ static PyType_Spec islice_spec = {
0, /* tp_as_mapping */ .name = "itertools.islice",
0, /* tp_hash */ .basicsize = sizeof(isliceobject),
0, /* tp_call */ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
0, /* tp_str */ Py_TPFLAGS_IMMUTABLETYPE),
PyObject_GenericGetAttr, /* tp_getattro */ .slots = islice_slots,
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
islice_doc, /* tp_doc */
(traverseproc)islice_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)islice_next, /* tp_iternext */
islice_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 */
islice_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
}; };
@ -2056,8 +1992,6 @@ typedef struct {
PyObject *active; /* Currently running input iterator */ PyObject *active; /* Currently running input iterator */
} chainobject; } chainobject;
static PyTypeObject chain_type;
static PyObject * static PyObject *
chain_new_internal(PyTypeObject *type, PyObject *source) chain_new_internal(PyTypeObject *type, PyObject *source)
{ {
@ -2079,7 +2013,9 @@ chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
PyObject *source; PyObject *source;
if ((type == &chain_type || type->tp_init == chain_type.tp_init) && itertools_state *state = find_state_by_type(type);
PyTypeObject *chain_type = state->chain_type;
if ((type == chain_type || type->tp_init == chain_type->tp_init) &&
!_PyArg_NoKeywords("chain", kwds)) !_PyArg_NoKeywords("chain", kwds))
return NULL; return NULL;
@ -2114,15 +2050,18 @@ itertools_chain_from_iterable(PyTypeObject *type, PyObject *arg)
static void static void
chain_dealloc(chainobject *lz) chain_dealloc(chainobject *lz)
{ {
PyTypeObject *tp = Py_TYPE(lz);
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_XDECREF(lz->active); Py_XDECREF(lz->active);
Py_XDECREF(lz->source); Py_XDECREF(lz->source);
Py_TYPE(lz)->tp_free(lz); tp->tp_free(lz);
Py_DECREF(tp);
} }
static int static int
chain_traverse(chainobject *lz, visitproc visit, void *arg) chain_traverse(chainobject *lz, visitproc visit, void *arg)
{ {
Py_VISIT(Py_TYPE(lz));
Py_VISIT(lz->source); Py_VISIT(lz->source);
Py_VISIT(lz->active); Py_VISIT(lz->active);
return 0; return 0;
@ -2227,48 +2166,25 @@ static PyMethodDef chain_methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static PyTypeObject chain_type = { static PyType_Slot chain_slots[] = {
PyVarObject_HEAD_INIT(NULL, 0) {Py_tp_dealloc, chain_dealloc},
"itertools.chain", /* tp_name */ {Py_tp_getattro, PyObject_GenericGetAttr},
sizeof(chainobject), /* tp_basicsize */ {Py_tp_doc, (void *)chain_doc},
0, /* tp_itemsize */ {Py_tp_traverse, chain_traverse},
/* methods */ {Py_tp_iter, PyObject_SelfIter},
(destructor)chain_dealloc, /* tp_dealloc */ {Py_tp_iternext, chain_next},
0, /* tp_vectorcall_offset */ {Py_tp_methods, chain_methods},
0, /* tp_getattr */ {Py_tp_new, chain_new},
0, /* tp_setattr */ {Py_tp_free, PyObject_GC_Del},
0, /* tp_as_async */ {0, NULL},
0, /* tp_repr */ };
0, /* tp_as_number */
0, /* tp_as_sequence */ static PyType_Spec chain_spec = {
0, /* tp_as_mapping */ .name = "itertools.chain",
0, /* tp_hash */ .basicsize = sizeof(chainobject),
0, /* tp_call */ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
0, /* tp_str */ Py_TPFLAGS_IMMUTABLETYPE),
PyObject_GenericGetAttr, /* tp_getattro */ .slots = chain_slots,
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
chain_doc, /* tp_doc */
(traverseproc)chain_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)chain_next, /* tp_iternext */
chain_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 */
chain_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
}; };
@ -3574,6 +3490,7 @@ typedef struct {
PyObject *it; PyObject *it;
PyObject *binop; PyObject *binop;
PyObject *initial; PyObject *initial;
itertools_state *state;
} accumulateobject; } accumulateobject;
/*[clinic input] /*[clinic input]
@ -3612,6 +3529,7 @@ itertools_accumulate_impl(PyTypeObject *type, PyObject *iterable,
lz->total = NULL; lz->total = NULL;
lz->it = it; lz->it = it;
lz->initial = Py_XNewRef(initial); lz->initial = Py_XNewRef(initial);
lz->state = find_state_by_type(type);
return (PyObject *)lz; return (PyObject *)lz;
} }
@ -3674,13 +3592,13 @@ accumulate_next(accumulateobject *lz)
static PyObject * static PyObject *
accumulate_reduce(accumulateobject *lz, PyObject *Py_UNUSED(ignored)) accumulate_reduce(accumulateobject *lz, PyObject *Py_UNUSED(ignored))
{ {
itertools_state *state = lz->state;
if (lz->initial != Py_None) { if (lz->initial != Py_None) {
PyObject *it; PyObject *it;
assert(lz->total == NULL); assert(lz->total == NULL);
if (PyType_Ready(&chain_type) < 0) it = PyObject_CallFunction((PyObject *)(state->chain_type), "(O)O",
return NULL;
it = PyObject_CallFunction((PyObject *)&chain_type, "(O)O",
lz->initial, lz->it); lz->initial, lz->it);
if (it == NULL) if (it == NULL)
return NULL; return NULL;
@ -3690,11 +3608,7 @@ accumulate_reduce(accumulateobject *lz, PyObject *Py_UNUSED(ignored))
if (lz->total == Py_None) { if (lz->total == Py_None) {
PyObject *it; PyObject *it;
if (PyType_Ready(&chain_type) < 0) it = PyObject_CallFunction((PyObject *)(state->chain_type), "(O)O",
return NULL;
if (PyType_Ready(&islice_type) < 0)
return NULL;
it = PyObject_CallFunction((PyObject *)&chain_type, "(O)O",
lz->total, lz->it); lz->total, lz->it);
if (it == NULL) if (it == NULL)
return NULL; return NULL;
@ -3702,7 +3616,8 @@ accumulate_reduce(accumulateobject *lz, PyObject *Py_UNUSED(ignored))
it, lz->binop ? lz->binop : Py_None); it, lz->binop ? lz->binop : Py_None);
if (it == NULL) if (it == NULL)
return NULL; return NULL;
return Py_BuildValue("O(NiO)", &islice_type, it, 1, Py_None);
return Py_BuildValue("O(NiO)", state->islice_type, it, 1, Py_None);
} }
return Py_BuildValue("O(OO)O", Py_TYPE(lz), return Py_BuildValue("O(OO)O", Py_TYPE(lz),
lz->it, lz->binop?lz->binop:Py_None, lz->it, lz->binop?lz->binop:Py_None,
@ -4261,8 +4176,6 @@ typedef struct {
Py_ssize_t cnt; Py_ssize_t cnt;
} repeatobject; } repeatobject;
static PyTypeObject repeat_type;
static PyObject * static PyObject *
repeat_new(PyTypeObject *type, PyObject *args, PyObject *kwds) repeat_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
@ -4292,14 +4205,17 @@ repeat_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void static void
repeat_dealloc(repeatobject *ro) repeat_dealloc(repeatobject *ro)
{ {
PyTypeObject *tp = Py_TYPE(ro);
PyObject_GC_UnTrack(ro); PyObject_GC_UnTrack(ro);
Py_XDECREF(ro->element); Py_XDECREF(ro->element);
Py_TYPE(ro)->tp_free(ro); tp->tp_free(ro);
Py_DECREF(tp);
} }
static int static int
repeat_traverse(repeatobject *ro, visitproc visit, void *arg) repeat_traverse(repeatobject *ro, visitproc visit, void *arg)
{ {
Py_VISIT(Py_TYPE(ro));
Py_VISIT(ro->element); Py_VISIT(ro->element);
return 0; return 0;
} }
@ -4361,48 +4277,26 @@ PyDoc_STRVAR(repeat_doc,
for the specified number of times. If not specified, returns the object\n\ for the specified number of times. If not specified, returns the object\n\
endlessly."); endlessly.");
static PyTypeObject repeat_type = { static PyType_Slot repeat_slots[] = {
PyVarObject_HEAD_INIT(NULL, 0) {Py_tp_dealloc, repeat_dealloc},
"itertools.repeat", /* tp_name */ {Py_tp_repr, repeat_repr},
sizeof(repeatobject), /* tp_basicsize */ {Py_tp_getattro, PyObject_GenericGetAttr},
0, /* tp_itemsize */ {Py_tp_doc, (void *)repeat_doc},
/* methods */ {Py_tp_traverse, repeat_traverse},
(destructor)repeat_dealloc, /* tp_dealloc */ {Py_tp_iter, PyObject_SelfIter},
0, /* tp_vectorcall_offset */ {Py_tp_iternext, repeat_next},
0, /* tp_getattr */ {Py_tp_methods, repeat_methods},
0, /* tp_setattr */ {Py_tp_new, repeat_new},
0, /* tp_as_async */ {Py_tp_free, PyObject_GC_Del},
(reprfunc)repeat_repr, /* tp_repr */ {0, NULL},
0, /* tp_as_number */ };
0, /* tp_as_sequence */
0, /* tp_as_mapping */ static PyType_Spec repeat_spec = {
0, /* tp_hash */ .name = "itertools.repeat",
0, /* tp_call */ .basicsize = sizeof(repeatobject),
0, /* tp_str */ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
PyObject_GenericGetAttr, /* tp_getattro */ Py_TPFLAGS_IMMUTABLETYPE),
0, /* tp_setattro */ .slots = repeat_slots,
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
repeat_doc, /* tp_doc */
(traverseproc)repeat_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)repeat_next, /* tp_iternext */
repeat_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 */
repeat_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
}; };
@ -4695,6 +4589,8 @@ itertoolsmodule_traverse(PyObject *mod, visitproc visit, void *arg)
{ {
itertools_state *state = get_module_state(mod); itertools_state *state = get_module_state(mod);
Py_VISIT(state->accumulate_type); Py_VISIT(state->accumulate_type);
Py_VISIT(state->batched_type);
Py_VISIT(state->chain_type);
Py_VISIT(state->combinations_type); Py_VISIT(state->combinations_type);
Py_VISIT(state->compress_type); Py_VISIT(state->compress_type);
Py_VISIT(state->count_type); Py_VISIT(state->count_type);
@ -4704,11 +4600,15 @@ itertoolsmodule_traverse(PyObject *mod, visitproc visit, void *arg)
Py_VISIT(state->filterfalse_type); Py_VISIT(state->filterfalse_type);
Py_VISIT(state->groupby_type); Py_VISIT(state->groupby_type);
Py_VISIT(state->_grouper_type); Py_VISIT(state->_grouper_type);
Py_VISIT(state->islice_type);
Py_VISIT(state->pairwise_type); Py_VISIT(state->pairwise_type);
Py_VISIT(state->permutations_type); Py_VISIT(state->permutations_type);
Py_VISIT(state->product_type); Py_VISIT(state->product_type);
Py_VISIT(state->repeat_type);
Py_VISIT(state->starmap_type); Py_VISIT(state->starmap_type);
Py_VISIT(state->takewhile_type); Py_VISIT(state->takewhile_type);
Py_VISIT(state->tee_type);
Py_VISIT(state->teedataobject_type);
Py_VISIT(state->ziplongest_type); Py_VISIT(state->ziplongest_type);
return 0; return 0;
} }
@ -4718,6 +4618,8 @@ itertoolsmodule_clear(PyObject *mod)
{ {
itertools_state *state = get_module_state(mod); itertools_state *state = get_module_state(mod);
Py_CLEAR(state->accumulate_type); Py_CLEAR(state->accumulate_type);
Py_CLEAR(state->batched_type);
Py_CLEAR(state->chain_type);
Py_CLEAR(state->combinations_type); Py_CLEAR(state->combinations_type);
Py_CLEAR(state->compress_type); Py_CLEAR(state->compress_type);
Py_CLEAR(state->count_type); Py_CLEAR(state->count_type);
@ -4727,11 +4629,15 @@ itertoolsmodule_clear(PyObject *mod)
Py_CLEAR(state->filterfalse_type); Py_CLEAR(state->filterfalse_type);
Py_CLEAR(state->groupby_type); Py_CLEAR(state->groupby_type);
Py_CLEAR(state->_grouper_type); Py_CLEAR(state->_grouper_type);
Py_CLEAR(state->islice_type);
Py_CLEAR(state->pairwise_type); Py_CLEAR(state->pairwise_type);
Py_CLEAR(state->permutations_type); Py_CLEAR(state->permutations_type);
Py_CLEAR(state->product_type); Py_CLEAR(state->product_type);
Py_CLEAR(state->repeat_type);
Py_CLEAR(state->starmap_type); Py_CLEAR(state->starmap_type);
Py_CLEAR(state->takewhile_type); Py_CLEAR(state->takewhile_type);
Py_CLEAR(state->tee_type);
Py_CLEAR(state->teedataobject_type);
Py_CLEAR(state->ziplongest_type); Py_CLEAR(state->ziplongest_type);
return 0; return 0;
} }
@ -4758,6 +4664,8 @@ itertoolsmodule_exec(PyObject *mod)
{ {
itertools_state *state = get_module_state(mod); itertools_state *state = get_module_state(mod);
ADD_TYPE(mod, state->accumulate_type, &accumulate_spec); ADD_TYPE(mod, state->accumulate_type, &accumulate_spec);
ADD_TYPE(mod, state->batched_type, &batched_spec);
ADD_TYPE(mod, state->chain_type, &chain_spec);
ADD_TYPE(mod, state->combinations_type, &combinations_spec); ADD_TYPE(mod, state->combinations_type, &combinations_spec);
ADD_TYPE(mod, state->compress_type, &compress_spec); ADD_TYPE(mod, state->compress_type, &compress_spec);
ADD_TYPE(mod, state->count_type, &count_spec); ADD_TYPE(mod, state->count_type, &count_spec);
@ -4767,30 +4675,18 @@ itertoolsmodule_exec(PyObject *mod)
ADD_TYPE(mod, state->filterfalse_type, &filterfalse_spec); ADD_TYPE(mod, state->filterfalse_type, &filterfalse_spec);
ADD_TYPE(mod, state->groupby_type, &groupby_spec); ADD_TYPE(mod, state->groupby_type, &groupby_spec);
ADD_TYPE(mod, state->_grouper_type, &_grouper_spec); ADD_TYPE(mod, state->_grouper_type, &_grouper_spec);
ADD_TYPE(mod, state->islice_type, &islice_spec);
ADD_TYPE(mod, state->pairwise_type, &pairwise_spec); ADD_TYPE(mod, state->pairwise_type, &pairwise_spec);
ADD_TYPE(mod, state->permutations_type, &permutations_spec); ADD_TYPE(mod, state->permutations_type, &permutations_spec);
ADD_TYPE(mod, state->product_type, &product_spec); ADD_TYPE(mod, state->product_type, &product_spec);
ADD_TYPE(mod, state->repeat_type, &repeat_spec);
ADD_TYPE(mod, state->starmap_type, &starmap_spec); ADD_TYPE(mod, state->starmap_type, &starmap_spec);
ADD_TYPE(mod, state->takewhile_type, &takewhile_spec); ADD_TYPE(mod, state->takewhile_type, &takewhile_spec);
ADD_TYPE(mod, state->tee_type, &tee_spec);
ADD_TYPE(mod, state->teedataobject_type, &teedataobject_spec);
ADD_TYPE(mod, state->ziplongest_type, &ziplongest_spec); ADD_TYPE(mod, state->ziplongest_type, &ziplongest_spec);
PyTypeObject *typelist[] = { Py_SET_TYPE(state->teedataobject_type, &PyType_Type);
&batched_type,
&islice_type,
&chain_type,
&repeat_type,
&tee_type,
&teedataobject_type
};
Py_SET_TYPE(&teedataobject_type, &PyType_Type);
for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) {
if (PyModule_AddType(mod, typelist[i]) < 0) {
return -1;
}
}
return 0; return 0;
} }

View File

@ -335,28 +335,6 @@ Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type -
Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type -
Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_Type -
Modules/_testcapi/vectorcall.c - MethodDescriptor2_Type - Modules/_testcapi/vectorcall.c - MethodDescriptor2_Type -
Modules/itertoolsmodule.c - _grouper_type -
Modules/itertoolsmodule.c - accumulate_type -
Modules/itertoolsmodule.c - batched_type -
Modules/itertoolsmodule.c - chain_type -
Modules/itertoolsmodule.c - combinations_type -
Modules/itertoolsmodule.c - compress_type -
Modules/itertoolsmodule.c - count_type -
Modules/itertoolsmodule.c - cwr_type -
Modules/itertoolsmodule.c - cycle_type -
Modules/itertoolsmodule.c - dropwhile_type -
Modules/itertoolsmodule.c - filterfalse_type -
Modules/itertoolsmodule.c - groupby_type -
Modules/itertoolsmodule.c - islice_type -
Modules/itertoolsmodule.c - pairwise_type -
Modules/itertoolsmodule.c - permutations_type -
Modules/itertoolsmodule.c - product_type -
Modules/itertoolsmodule.c - repeat_type -
Modules/itertoolsmodule.c - starmap_type -
Modules/itertoolsmodule.c - takewhile_type -
Modules/itertoolsmodule.c - tee_type -
Modules/itertoolsmodule.c - teedataobject_type -
Modules/itertoolsmodule.c - ziplongest_type -
################################## ##################################

Can't render this file because it has a wrong number of fields in line 4.