[Python-checkins] gh-101277: Port more itertools static types to heap types (#101304)

erlend-aasland webhook-mailer at python.org
Wed Feb 8 15:25:51 EST 2023


https://github.com/python/cpython/commit/de3669ebcb33ca8e3373fbbaed646c5f287979b8
commit: de3669ebcb33ca8e3373fbbaed646c5f287979b8
branch: main
author: Erlend E. Aasland <erlend.aasland at protonmail.com>
committer: erlend-aasland <erlend.aasland at protonmail.com>
date: 2023-02-08T21:25:42+01:00
summary:

gh-101277: Port more itertools static types to heap types (#101304)

Add accumulate, compress, count, filterfalse, pairwise, product,
and zip_longest types to module state.

files:
M Modules/clinic/itertoolsmodule.c.h
M Modules/itertoolsmodule.c

diff --git a/Modules/clinic/itertoolsmodule.c.h b/Modules/clinic/itertoolsmodule.c.h
index be44246cc970..d15d5f0890ca 100644
--- a/Modules/clinic/itertoolsmodule.c.h
+++ b/Modules/clinic/itertoolsmodule.c.h
@@ -102,7 +102,7 @@ static PyObject *
 pairwise_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    PyTypeObject *base_tp = &pairwise_type;
+    PyTypeObject *base_tp = clinic_state()->pairwise_type;
     PyObject *iterable;
 
     if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
@@ -821,7 +821,7 @@ static PyObject *
 itertools_filterfalse(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    PyTypeObject *base_tp = &filterfalse_type;
+    PyTypeObject *base_tp = clinic_state()->filterfalse_type;
     PyObject *func;
     PyObject *seq;
 
@@ -913,4 +913,4 @@ itertools_count(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=b86fcd99bd32145e input=a9049054013a1b77]*/
+/*[clinic end generated code: output=a08b58d7dac825da input=a9049054013a1b77]*/
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index c9baa47e2c0e..ce8720d0fd92 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -12,15 +12,22 @@
 */
 
 typedef struct {
+    PyTypeObject *accumulate_type;
     PyTypeObject *combinations_type;
+    PyTypeObject *compress_type;
+    PyTypeObject *count_type;
     PyTypeObject *cwr_type;
     PyTypeObject *cycle_type;
     PyTypeObject *dropwhile_type;
+    PyTypeObject *filterfalse_type;
     PyTypeObject *groupby_type;
     PyTypeObject *_grouper_type;
+    PyTypeObject *pairwise_type;
     PyTypeObject *permutations_type;
+    PyTypeObject *product_type;
     PyTypeObject *starmap_type;
     PyTypeObject *takewhile_type;
+    PyTypeObject *ziplongest_type;
 } itertools_state;
 
 static inline itertools_state *
@@ -48,7 +55,6 @@ find_state_by_type(PyTypeObject *tp)
     assert(mod != NULL);
     return get_module_state(mod);
 }
-#define clinic_state() (find_state_by_type(type))
 
 /*[clinic input]
 module itertools
@@ -65,23 +71,19 @@ class itertools.chain "chainobject *" "&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"
-class itertools.accumulate "accumulateobject *" "&accumulate_type"
-class itertools.compress "compressobject *" "&compress_type"
-class itertools.filterfalse "filterfalseobject *" "&filterfalse_type"
-class itertools.count "countobject *" "&count_type"
-class itertools.pairwise "pairwiseobject *" "&pairwise_type"
+class itertools.accumulate "accumulateobject *" "clinic_state()->accumulate_type"
+class itertools.compress "compressobject *" "clinic_state()->compress_type"
+class itertools.filterfalse "filterfalseobject *" "clinic_state()->filterfalse_type"
+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=1790ac655869a651]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=28ffff5c0c93eed7]*/
 
 static PyTypeObject teedataobject_type;
 static PyTypeObject tee_type;
 static PyTypeObject batched_type;
-static PyTypeObject accumulate_type;
-static PyTypeObject compress_type;
-static PyTypeObject filterfalse_type;
-static PyTypeObject count_type;
-static PyTypeObject pairwise_type;
 
+#define clinic_state() (find_state_by_type(type))
 #define clinic_state_by_cls() (get_module_state_by_cls(base_tp))
 #include "clinic/itertoolsmodule.c.h"
 #undef clinic_state_by_cls
@@ -308,15 +310,18 @@ pairwise_new_impl(PyTypeObject *type, PyObject *iterable)
 static void
 pairwise_dealloc(pairwiseobject *po)
 {
+    PyTypeObject *tp = Py_TYPE(po);
     PyObject_GC_UnTrack(po);
     Py_XDECREF(po->it);
     Py_XDECREF(po->old);
-    Py_TYPE(po)->tp_free(po);
+    tp->tp_free(po);
+    Py_DECREF(tp);
 }
 
 static int
 pairwise_traverse(pairwiseobject *po, visitproc visit, void *arg)
 {
+    Py_VISIT(Py_TYPE(po));
     Py_VISIT(po->it);
     Py_VISIT(po->old);
     return 0;
@@ -351,48 +356,25 @@ pairwise_next(pairwiseobject *po)
     return result;
 }
 
-static PyTypeObject pairwise_type = {
-    PyVarObject_HEAD_INIT(&PyType_Type, 0)
-    "itertools.pairwise",           /* tp_name */
-    sizeof(pairwiseobject),         /* tp_basicsize */
-    0,                              /* tp_itemsize */
-    /* methods */
-    (destructor)pairwise_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 */
-    pairwise_new__doc__,            /* tp_doc */
-    (traverseproc)pairwise_traverse,    /* tp_traverse */
-    0,                              /* tp_clear */
-    0,                              /* tp_richcompare */
-    0,                              /* tp_weaklistoffset */
-    PyObject_SelfIter,              /* tp_iter */
-    (iternextfunc)pairwise_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 */
-    pairwise_new,                   /* tp_new */
-    PyObject_GC_Del,                /* tp_free */
+static PyType_Slot pairwise_slots[] = {
+    {Py_tp_dealloc, pairwise_dealloc},
+    {Py_tp_getattro, PyObject_GenericGetAttr},
+    {Py_tp_doc, (void *)pairwise_new__doc__},
+    {Py_tp_traverse, pairwise_traverse},
+    {Py_tp_iter, PyObject_SelfIter},
+    {Py_tp_iternext, pairwise_next},
+    {Py_tp_alloc, PyType_GenericAlloc},
+    {Py_tp_new, pairwise_new},
+    {Py_tp_free, PyObject_GC_Del},
+    {0, NULL},
+};
+
+static PyType_Spec pairwise_spec = {
+    .name = "itertools.pairwise",
+    .basicsize = sizeof(pairwiseobject),
+    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
+              Py_TPFLAGS_IMMUTABLETYPE),
+    .slots = pairwise_slots,
 };
 
 
@@ -2300,8 +2282,6 @@ typedef struct {
     int stopped;            /* set to 1 when the iterator is exhausted */
 } productobject;
 
-static PyTypeObject product_type;
-
 static PyObject *
 product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
@@ -2388,12 +2368,14 @@ product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 static void
 product_dealloc(productobject *lz)
 {
+    PyTypeObject *tp = Py_TYPE(lz);
     PyObject_GC_UnTrack(lz);
     Py_XDECREF(lz->pools);
     Py_XDECREF(lz->result);
     if (lz->indices != NULL)
         PyMem_Free(lz->indices);
-    Py_TYPE(lz)->tp_free(lz);
+    tp->tp_free(lz);
+    Py_DECREF(tp);
 }
 
 static PyObject *
@@ -2409,6 +2391,7 @@ PyDoc_STRVAR(sizeof_doc, "Returns size in memory, in bytes.");
 static int
 product_traverse(productobject *lz, visitproc visit, void *arg)
 {
+    Py_VISIT(Py_TYPE(lz));
     Py_VISIT(lz->pools);
     Py_VISIT(lz->result);
     return 0;
@@ -2600,48 +2583,25 @@ product(A, repeat=4) means the same as product(A, A, A, A).\n\n\
 product('ab', range(3)) --> ('a',0) ('a',1) ('a',2) ('b',0) ('b',1) ('b',2)\n\
 product((0,1), (0,1), (0,1)) --> (0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) ...");
 
-static PyTypeObject product_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "itertools.product",                /* tp_name */
-    sizeof(productobject),              /* tp_basicsize */
-    0,                                  /* tp_itemsize */
-    /* methods */
-    (destructor)product_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 */
-    product_doc,                        /* tp_doc */
-    (traverseproc)product_traverse,     /* tp_traverse */
-    0,                                  /* tp_clear */
-    0,                                  /* tp_richcompare */
-    0,                                  /* tp_weaklistoffset */
-    PyObject_SelfIter,                  /* tp_iter */
-    (iternextfunc)product_next,         /* tp_iternext */
-    product_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 */
-    product_new,                        /* tp_new */
-    PyObject_GC_Del,                    /* tp_free */
+static PyType_Slot product_slots[] = {
+    {Py_tp_dealloc, product_dealloc},
+    {Py_tp_getattro, PyObject_GenericGetAttr},
+    {Py_tp_doc, (void *)product_doc},
+    {Py_tp_traverse, product_traverse},
+    {Py_tp_iter, PyObject_SelfIter},
+    {Py_tp_iternext, product_next},
+    {Py_tp_methods, product_methods},
+    {Py_tp_new, product_new},
+    {Py_tp_free, PyObject_GC_Del},
+    {0, NULL},
+};
+
+static PyType_Spec product_spec = {
+    .name = "itertools.product",
+    .basicsize = sizeof(productobject),
+    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
+              Py_TPFLAGS_IMMUTABLETYPE),
+    .slots = product_slots,
 };
 
 
@@ -3658,17 +3618,20 @@ itertools_accumulate_impl(PyTypeObject *type, PyObject *iterable,
 static void
 accumulate_dealloc(accumulateobject *lz)
 {
+    PyTypeObject *tp = Py_TYPE(lz);
     PyObject_GC_UnTrack(lz);
     Py_XDECREF(lz->binop);
     Py_XDECREF(lz->total);
     Py_XDECREF(lz->it);
     Py_XDECREF(lz->initial);
-    Py_TYPE(lz)->tp_free(lz);
+    tp->tp_free(lz);
+    Py_DECREF(tp);
 }
 
 static int
 accumulate_traverse(accumulateobject *lz, visitproc visit, void *arg)
 {
+    Py_VISIT(Py_TYPE(lz));
     Py_VISIT(lz->binop);
     Py_VISIT(lz->it);
     Py_VISIT(lz->total);
@@ -3762,48 +3725,25 @@ static PyMethodDef accumulate_methods[] = {
     {NULL,              NULL}   /* sentinel */
 };
 
-static PyTypeObject accumulate_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "itertools.accumulate",             /* tp_name */
-    sizeof(accumulateobject),           /* tp_basicsize */
-    0,                                  /* tp_itemsize */
-    /* methods */
-    (destructor)accumulate_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 */
-    itertools_accumulate__doc__,        /* tp_doc */
-    (traverseproc)accumulate_traverse,  /* tp_traverse */
-    0,                                  /* tp_clear */
-    0,                                  /* tp_richcompare */
-    0,                                  /* tp_weaklistoffset */
-    PyObject_SelfIter,                  /* tp_iter */
-    (iternextfunc)accumulate_next,      /* tp_iternext */
-    accumulate_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_accumulate,               /* tp_new */
-    PyObject_GC_Del,                    /* tp_free */
+static PyType_Slot accumulate_slots[] = {
+    {Py_tp_dealloc, accumulate_dealloc},
+    {Py_tp_getattro, PyObject_GenericGetAttr},
+    {Py_tp_doc, (void *)itertools_accumulate__doc__},
+    {Py_tp_traverse, accumulate_traverse},
+    {Py_tp_iter, PyObject_SelfIter},
+    {Py_tp_iternext, accumulate_next},
+    {Py_tp_methods, accumulate_methods},
+    {Py_tp_new, itertools_accumulate},
+    {Py_tp_free, PyObject_GC_Del},
+    {0, NULL},
+};
+
+static PyType_Spec accumulate_spec = {
+    .name = "itertools.accumulate",
+    .basicsize = sizeof(accumulateobject),
+    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
+              Py_TPFLAGS_IMMUTABLETYPE),
+    .slots = accumulate_slots,
 };
 
 
@@ -3864,15 +3804,18 @@ itertools_compress_impl(PyTypeObject *type, PyObject *seq1, PyObject *seq2)
 static void
 compress_dealloc(compressobject *lz)
 {
+    PyTypeObject *tp = Py_TYPE(lz);
     PyObject_GC_UnTrack(lz);
     Py_XDECREF(lz->data);
     Py_XDECREF(lz->selectors);
-    Py_TYPE(lz)->tp_free(lz);
+    tp->tp_free(lz);
+    Py_DECREF(tp);
 }
 
 static int
 compress_traverse(compressobject *lz, visitproc visit, void *arg)
 {
+    Py_VISIT(Py_TYPE(lz));
     Py_VISIT(lz->data);
     Py_VISIT(lz->selectors);
     return 0;
@@ -3927,48 +3870,25 @@ static PyMethodDef compress_methods[] = {
     {NULL,              NULL}   /* sentinel */
 };
 
-static PyTypeObject compress_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "itertools.compress",               /* tp_name */
-    sizeof(compressobject),             /* tp_basicsize */
-    0,                                  /* tp_itemsize */
-    /* methods */
-    (destructor)compress_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 */
-    itertools_compress__doc__,          /* tp_doc */
-    (traverseproc)compress_traverse,    /* tp_traverse */
-    0,                                  /* tp_clear */
-    0,                                  /* tp_richcompare */
-    0,                                  /* tp_weaklistoffset */
-    PyObject_SelfIter,                  /* tp_iter */
-    (iternextfunc)compress_next,        /* tp_iternext */
-    compress_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_compress,                 /* tp_new */
-    PyObject_GC_Del,                    /* tp_free */
+static PyType_Slot compress_slots[] = {
+    {Py_tp_dealloc, compress_dealloc},
+    {Py_tp_getattro, PyObject_GenericGetAttr},
+    {Py_tp_doc, (void *)itertools_compress__doc__},
+    {Py_tp_traverse, compress_traverse},
+    {Py_tp_iter, PyObject_SelfIter},
+    {Py_tp_iternext, compress_next},
+    {Py_tp_methods, compress_methods},
+    {Py_tp_new, itertools_compress},
+    {Py_tp_free, PyObject_GC_Del},
+    {0, NULL},
+};
+
+static PyType_Spec compress_spec = {
+    .name = "itertools.compress",
+    .basicsize = sizeof(compressobject),
+    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
+              Py_TPFLAGS_IMMUTABLETYPE),
+    .slots = compress_slots,
 };
 
 
@@ -4018,15 +3938,18 @@ itertools_filterfalse_impl(PyTypeObject *type, PyObject *func, PyObject *seq)
 static void
 filterfalse_dealloc(filterfalseobject *lz)
 {
+    PyTypeObject *tp = Py_TYPE(lz);
     PyObject_GC_UnTrack(lz);
     Py_XDECREF(lz->func);
     Py_XDECREF(lz->it);
-    Py_TYPE(lz)->tp_free(lz);
+    tp->tp_free(lz);
+    Py_DECREF(tp);
 }
 
 static int
 filterfalse_traverse(filterfalseobject *lz, visitproc visit, void *arg)
 {
+    Py_VISIT(Py_TYPE(lz));
     Py_VISIT(lz->it);
     Py_VISIT(lz->func);
     return 0;
@@ -4078,48 +4001,25 @@ static PyMethodDef filterfalse_methods[] = {
     {NULL,              NULL}   /* sentinel */
 };
 
-static PyTypeObject filterfalse_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "itertools.filterfalse",            /* tp_name */
-    sizeof(filterfalseobject),          /* tp_basicsize */
-    0,                                  /* tp_itemsize */
-    /* methods */
-    (destructor)filterfalse_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 */
-    itertools_filterfalse__doc__,       /* tp_doc */
-    (traverseproc)filterfalse_traverse, /* tp_traverse */
-    0,                                  /* tp_clear */
-    0,                                  /* tp_richcompare */
-    0,                                  /* tp_weaklistoffset */
-    PyObject_SelfIter,                  /* tp_iter */
-    (iternextfunc)filterfalse_next,     /* tp_iternext */
-    filterfalse_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_filterfalse,              /* tp_new */
-    PyObject_GC_Del,                    /* tp_free */
+static PyType_Slot filterfalse_slots[] = {
+    {Py_tp_dealloc, filterfalse_dealloc},
+    {Py_tp_getattro, PyObject_GenericGetAttr},
+    {Py_tp_doc, (void *)itertools_filterfalse__doc__},
+    {Py_tp_traverse, filterfalse_traverse},
+    {Py_tp_iter, PyObject_SelfIter},
+    {Py_tp_iternext, filterfalse_next},
+    {Py_tp_methods, filterfalse_methods},
+    {Py_tp_new, itertools_filterfalse},
+    {Py_tp_free, PyObject_GC_Del},
+    {0, NULL},
+};
+
+static PyType_Spec filterfalse_spec = {
+    .name = "itertools.filterfalse",
+    .basicsize = sizeof(filterfalseobject),
+    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
+              Py_TPFLAGS_IMMUTABLETYPE),
+    .slots = filterfalse_slots,
 };
 
 
@@ -4245,15 +4145,18 @@ itertools_count_impl(PyTypeObject *type, PyObject *long_cnt,
 static void
 count_dealloc(countobject *lz)
 {
+    PyTypeObject *tp = Py_TYPE(lz);
     PyObject_GC_UnTrack(lz);
     Py_XDECREF(lz->long_cnt);
     Py_XDECREF(lz->long_step);
-    Py_TYPE(lz)->tp_free(lz);
+    tp->tp_free(lz);
+    Py_DECREF(tp);
 }
 
 static int
 count_traverse(countobject *lz, visitproc visit, void *arg)
 {
+    Py_VISIT(Py_TYPE(lz));
     Py_VISIT(lz->long_cnt);
     Py_VISIT(lz->long_step);
     return 0;
@@ -4327,48 +4230,26 @@ static PyMethodDef count_methods[] = {
     {NULL,              NULL}   /* sentinel */
 };
 
-static PyTypeObject count_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "itertools.count",                  /* tp_name */
-    sizeof(countobject),                /* tp_basicsize */
-    0,                                  /* tp_itemsize */
-    /* methods */
-    (destructor)count_dealloc,          /* tp_dealloc */
-    0,                                  /* tp_vectorcall_offset */
-    0,                                  /* tp_getattr */
-    0,                                  /* tp_setattr */
-    0,                                  /* tp_as_async */
-    (reprfunc)count_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 */
-    itertools_count__doc__,             /* tp_doc */
-    (traverseproc)count_traverse,       /* tp_traverse */
-    0,                                  /* tp_clear */
-    0,                                  /* tp_richcompare */
-    0,                                  /* tp_weaklistoffset */
-    PyObject_SelfIter,                  /* tp_iter */
-    (iternextfunc)count_next,           /* tp_iternext */
-    count_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_count,                    /* tp_new */
-    PyObject_GC_Del,                    /* tp_free */
+static PyType_Slot count_slots[] = {
+    {Py_tp_dealloc, count_dealloc},
+    {Py_tp_repr, count_repr},
+    {Py_tp_getattro, PyObject_GenericGetAttr},
+    {Py_tp_doc, (void *)itertools_count__doc__},
+    {Py_tp_traverse, count_traverse},
+    {Py_tp_iter, PyObject_SelfIter},
+    {Py_tp_iternext, count_next},
+    {Py_tp_methods, count_methods},
+    {Py_tp_new, itertools_count},
+    {Py_tp_free, PyObject_GC_Del},
+    {0, NULL},
+};
+
+static PyType_Spec count_spec = {
+    .name = "itertools.count",
+    .basicsize = sizeof(countobject),
+    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
+              Py_TPFLAGS_IMMUTABLETYPE),
+    .slots = count_slots,
 };
 
 
@@ -4536,8 +4417,6 @@ typedef struct {
     PyObject *fillvalue;
 } ziplongestobject;
 
-static PyTypeObject ziplongest_type;
-
 static PyObject *
 zip_longest_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
@@ -4609,16 +4488,19 @@ zip_longest_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 static void
 zip_longest_dealloc(ziplongestobject *lz)
 {
+    PyTypeObject *tp = Py_TYPE(lz);
     PyObject_GC_UnTrack(lz);
     Py_XDECREF(lz->ittuple);
     Py_XDECREF(lz->result);
     Py_XDECREF(lz->fillvalue);
-    Py_TYPE(lz)->tp_free(lz);
+    tp->tp_free(lz);
+    Py_DECREF(tp);
 }
 
 static int
 zip_longest_traverse(ziplongestobject *lz, visitproc visit, void *arg)
 {
+    Py_VISIT(Py_TYPE(lz));
     Py_VISIT(lz->ittuple);
     Py_VISIT(lz->result);
     Py_VISIT(lz->fillvalue);
@@ -4752,48 +4634,25 @@ are exhausted, the fillvalue is substituted in their place.  The fillvalue\n\
 defaults to None or can be specified by a keyword argument.\n\
 ");
 
-static PyTypeObject ziplongest_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "itertools.zip_longest",            /* tp_name */
-    sizeof(ziplongestobject),           /* tp_basicsize */
-    0,                                  /* tp_itemsize */
-    /* methods */
-    (destructor)zip_longest_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 */
-    zip_longest_doc,                    /* tp_doc */
-    (traverseproc)zip_longest_traverse, /* tp_traverse */
-    0,                                  /* tp_clear */
-    0,                                  /* tp_richcompare */
-    0,                                  /* tp_weaklistoffset */
-    PyObject_SelfIter,                  /* tp_iter */
-    (iternextfunc)zip_longest_next,     /* tp_iternext */
-    zip_longest_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 */
-    zip_longest_new,                    /* tp_new */
-    PyObject_GC_Del,                    /* tp_free */
+static PyType_Slot ziplongest_slots[] = {
+    {Py_tp_dealloc, zip_longest_dealloc},
+    {Py_tp_getattro, PyObject_GenericGetAttr},
+    {Py_tp_doc, (void *)zip_longest_doc},
+    {Py_tp_traverse, zip_longest_traverse},
+    {Py_tp_iter, PyObject_SelfIter},
+    {Py_tp_iternext, zip_longest_next},
+    {Py_tp_methods, zip_longest_methods},
+    {Py_tp_new, zip_longest_new},
+    {Py_tp_free, PyObject_GC_Del},
+    {0, NULL},
+};
+
+static PyType_Spec ziplongest_spec = {
+    .name = "itertools.zip_longest",
+    .basicsize = sizeof(ziplongestobject),
+    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
+              Py_TPFLAGS_IMMUTABLETYPE),
+    .slots = ziplongest_slots,
 };
 
 
@@ -4835,15 +4694,22 @@ static int
 itertoolsmodule_traverse(PyObject *mod, visitproc visit, void *arg)
 {
     itertools_state *state = get_module_state(mod);
+    Py_VISIT(state->accumulate_type);
     Py_VISIT(state->combinations_type);
+    Py_VISIT(state->compress_type);
+    Py_VISIT(state->count_type);
     Py_VISIT(state->cwr_type);
     Py_VISIT(state->cycle_type);
     Py_VISIT(state->dropwhile_type);
+    Py_VISIT(state->filterfalse_type);
     Py_VISIT(state->groupby_type);
     Py_VISIT(state->_grouper_type);
+    Py_VISIT(state->pairwise_type);
     Py_VISIT(state->permutations_type);
+    Py_VISIT(state->product_type);
     Py_VISIT(state->starmap_type);
     Py_VISIT(state->takewhile_type);
+    Py_VISIT(state->ziplongest_type);
     return 0;
 }
 
@@ -4851,15 +4717,22 @@ static int
 itertoolsmodule_clear(PyObject *mod)
 {
     itertools_state *state = get_module_state(mod);
+    Py_CLEAR(state->accumulate_type);
     Py_CLEAR(state->combinations_type);
+    Py_CLEAR(state->compress_type);
+    Py_CLEAR(state->count_type);
     Py_CLEAR(state->cwr_type);
     Py_CLEAR(state->cycle_type);
     Py_CLEAR(state->dropwhile_type);
+    Py_CLEAR(state->filterfalse_type);
     Py_CLEAR(state->groupby_type);
     Py_CLEAR(state->_grouper_type);
+    Py_CLEAR(state->pairwise_type);
     Py_CLEAR(state->permutations_type);
+    Py_CLEAR(state->product_type);
     Py_CLEAR(state->starmap_type);
     Py_CLEAR(state->takewhile_type);
+    Py_CLEAR(state->ziplongest_type);
     return 0;
 }
 
@@ -4884,27 +4757,27 @@ static int
 itertoolsmodule_exec(PyObject *mod)
 {
     itertools_state *state = get_module_state(mod);
+    ADD_TYPE(mod, state->accumulate_type, &accumulate_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);
     ADD_TYPE(mod, state->cwr_type, &cwr_spec);
     ADD_TYPE(mod, state->cycle_type, &cycle_spec);
     ADD_TYPE(mod, state->dropwhile_type, &dropwhile_spec);
+    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->pairwise_type, &pairwise_spec);
     ADD_TYPE(mod, state->permutations_type, &permutations_spec);
+    ADD_TYPE(mod, state->product_type, &product_spec);
     ADD_TYPE(mod, state->starmap_type, &starmap_spec);
     ADD_TYPE(mod, state->takewhile_type, &takewhile_spec);
+    ADD_TYPE(mod, state->ziplongest_type, &ziplongest_spec);
 
     PyTypeObject *typelist[] = {
-        &accumulate_type,
         &batched_type,
         &islice_type,
         &chain_type,
-        &compress_type,
-        &filterfalse_type,
-        &count_type,
-        &ziplongest_type,
-        &pairwise_type,
-        &product_type,
         &repeat_type,
         &tee_type,
         &teedataobject_type



More information about the Python-checkins mailing list