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

View File

@ -335,28 +335,6 @@ Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type -
Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type -
Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_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.