10
10
by Raymond D. Hettinger <[email protected] >
11
11
*/
12
12
13
+ typedef struct {
14
+ PyTypeObject * groupby_type ;
15
+ PyTypeObject * _grouper_type ;
16
+ } itertools_state ;
17
+
18
+ static inline itertools_state *
19
+ get_module_state (PyObject * mod )
20
+ {
21
+ void * state = PyModule_GetState (mod );
22
+ assert (state != NULL );
23
+ return (itertools_state * )state ;
24
+ }
25
+
26
+ static struct PyModuleDef itertoolsmodule ;
27
+ static inline itertools_state *
28
+ find_state_by_type (PyTypeObject * tp )
29
+ {
30
+ PyObject * mod = PyType_GetModuleByDef (tp , & itertoolsmodule );
31
+ assert (mod != NULL );
32
+ return get_module_state (mod );
33
+ }
34
+ #define clinic_state () (find_state_by_type(type))
35
+
13
36
/*[clinic input]
14
37
module itertools
15
- class itertools.groupby "groupbyobject *" "& groupby_type"
16
- class itertools._grouper "_grouperobject *" "& _grouper_type"
38
+ class itertools.groupby "groupbyobject *" "clinic_state()-> groupby_type"
39
+ class itertools._grouper "_grouperobject *" "clinic_state()-> _grouper_type"
17
40
class itertools.teedataobject "teedataobject *" "&teedataobject_type"
18
41
class itertools._tee "teeobject *" "&tee_type"
19
42
class itertools.batched "batchedobject *" "&batched_type"
@@ -31,10 +54,8 @@ class itertools.filterfalse "filterfalseobject *" "&filterfalse_type"
31
54
class itertools.count "countobject *" "&count_type"
32
55
class itertools.pairwise "pairwiseobject *" "&pairwise_type"
33
56
[clinic start generated code]*/
34
- /*[clinic end generated code: output=da39a3ee5e6b4b0d input=1168b274011ce21b ]*/
57
+ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=424108522584b55b ]*/
35
58
36
- static PyTypeObject groupby_type ;
37
- static PyTypeObject _grouper_type ;
38
59
static PyTypeObject teedataobject_type ;
39
60
static PyTypeObject tee_type ;
40
61
static PyTypeObject batched_type ;
@@ -51,14 +72,8 @@ static PyTypeObject filterfalse_type;
51
72
static PyTypeObject count_type ;
52
73
static PyTypeObject pairwise_type ;
53
74
54
- typedef struct {
55
- } itertools_state ;
56
-
57
- static itertools_state global_state ;
58
-
59
- #define GLOBAL_STATE (&global_state)
60
-
61
75
#include "clinic/itertoolsmodule.c.h"
76
+ #undef clinic_state
62
77
63
78
/* batched object ************************************************************/
64
79
@@ -421,18 +436,21 @@ itertools_groupby_impl(PyTypeObject *type, PyObject *it, PyObject *keyfunc)
421
436
static void
422
437
groupby_dealloc (groupbyobject * gbo )
423
438
{
439
+ PyTypeObject * tp = Py_TYPE (gbo );
424
440
PyObject_GC_UnTrack (gbo );
425
441
Py_XDECREF (gbo -> it );
426
442
Py_XDECREF (gbo -> keyfunc );
427
443
Py_XDECREF (gbo -> tgtkey );
428
444
Py_XDECREF (gbo -> currkey );
429
445
Py_XDECREF (gbo -> currvalue );
430
- Py_TYPE (gbo )-> tp_free (gbo );
446
+ tp -> tp_free (gbo );
447
+ Py_DECREF (tp );
431
448
}
432
449
433
450
static int
434
451
groupby_traverse (groupbyobject * gbo , visitproc visit , void * arg )
435
452
{
453
+ Py_VISIT (Py_TYPE (gbo ));
436
454
Py_VISIT (gbo -> it );
437
455
Py_VISIT (gbo -> keyfunc );
438
456
Py_VISIT (gbo -> tgtkey );
@@ -553,50 +571,26 @@ static PyMethodDef groupby_methods[] = {
553
571
{NULL , NULL } /* sentinel */
554
572
};
555
573
556
- static PyTypeObject groupby_type = {
557
- PyVarObject_HEAD_INIT (NULL , 0 )
558
- "itertools.groupby" , /* tp_name */
559
- sizeof (groupbyobject ), /* tp_basicsize */
560
- 0 , /* tp_itemsize */
561
- /* methods */
562
- (destructor )groupby_dealloc , /* tp_dealloc */
563
- 0 , /* tp_vectorcall_offset */
564
- 0 , /* tp_getattr */
565
- 0 , /* tp_setattr */
566
- 0 , /* tp_as_async */
567
- 0 , /* tp_repr */
568
- 0 , /* tp_as_number */
569
- 0 , /* tp_as_sequence */
570
- 0 , /* tp_as_mapping */
571
- 0 , /* tp_hash */
572
- 0 , /* tp_call */
573
- 0 , /* tp_str */
574
- PyObject_GenericGetAttr , /* tp_getattro */
575
- 0 , /* tp_setattro */
576
- 0 , /* tp_as_buffer */
577
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
578
- Py_TPFLAGS_BASETYPE , /* tp_flags */
579
- itertools_groupby__doc__ , /* tp_doc */
580
- (traverseproc )groupby_traverse , /* tp_traverse */
581
- 0 , /* tp_clear */
582
- 0 , /* tp_richcompare */
583
- 0 , /* tp_weaklistoffset */
584
- PyObject_SelfIter , /* tp_iter */
585
- (iternextfunc )groupby_next , /* tp_iternext */
586
- groupby_methods , /* tp_methods */
587
- 0 , /* tp_members */
588
- 0 , /* tp_getset */
589
- 0 , /* tp_base */
590
- 0 , /* tp_dict */
591
- 0 , /* tp_descr_get */
592
- 0 , /* tp_descr_set */
593
- 0 , /* tp_dictoffset */
594
- 0 , /* tp_init */
595
- 0 , /* tp_alloc */
596
- itertools_groupby , /* tp_new */
597
- PyObject_GC_Del , /* tp_free */
574
+ static PyType_Slot groupby_slots [] = {
575
+ {Py_tp_dealloc , groupby_dealloc },
576
+ {Py_tp_getattro , PyObject_GenericGetAttr },
577
+ {Py_tp_doc , (void * )itertools_groupby__doc__ },
578
+ {Py_tp_traverse , groupby_traverse },
579
+ {Py_tp_iter , PyObject_SelfIter },
580
+ {Py_tp_iternext , groupby_next },
581
+ {Py_tp_methods , groupby_methods },
582
+ {Py_tp_new , itertools_groupby },
583
+ {Py_tp_free , PyObject_GC_Del },
584
+ {0 , NULL },
598
585
};
599
586
587
+ static PyType_Spec groupby_spec = {
588
+ .name = "itertools.groupby" ,
589
+ .basicsize = sizeof (groupbyobject ),
590
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE |
591
+ Py_TPFLAGS_IMMUTABLETYPE ),
592
+ .slots = groupby_slots ,
593
+ };
600
594
601
595
/* _grouper object (internal) ************************************************/
602
596
@@ -610,25 +604,25 @@ typedef struct {
610
604
@classmethod
611
605
itertools._grouper.__new__
612
606
613
- parent: object(subclass_of='& groupby_type')
607
+ parent: object(subclass_of='clinic_state()-> groupby_type')
614
608
tgtkey: object
615
609
/
616
610
[clinic start generated code]*/
617
611
618
612
static PyObject *
619
613
itertools__grouper_impl (PyTypeObject * type , PyObject * parent ,
620
614
PyObject * tgtkey )
621
- /*[clinic end generated code: output=462efb1cdebb5914 input=dc180d7771fc8c59 ]*/
615
+ /*[clinic end generated code: output=462efb1cdebb5914 input=626b30a78e38cf7d ]*/
622
616
{
623
617
return _grouper_create ((groupbyobject * ) parent , tgtkey );
624
618
}
625
619
626
620
static PyObject *
627
621
_grouper_create (groupbyobject * parent , PyObject * tgtkey )
628
622
{
629
- _grouperobject * igo ;
630
-
631
- igo = PyObject_GC_New (_grouperobject , & _grouper_type );
623
+ PyTypeObject * tp = Py_TYPE ( parent ) ;
624
+ itertools_state * state = find_state_by_type ( tp );
625
+ _grouperobject * igo = PyObject_GC_New (_grouperobject , state -> _grouper_type );
632
626
if (igo == NULL )
633
627
return NULL ;
634
628
igo -> parent = Py_NewRef (parent );
@@ -642,15 +636,18 @@ _grouper_create(groupbyobject *parent, PyObject *tgtkey)
642
636
static void
643
637
_grouper_dealloc (_grouperobject * igo )
644
638
{
639
+ PyTypeObject * tp = Py_TYPE (igo );
645
640
PyObject_GC_UnTrack (igo );
646
641
Py_DECREF (igo -> parent );
647
642
Py_DECREF (igo -> tgtkey );
648
643
PyObject_GC_Del (igo );
644
+ Py_DECREF (tp );
649
645
}
650
646
651
647
static int
652
648
_grouper_traverse (_grouperobject * igo , visitproc visit , void * arg )
653
649
{
650
+ Py_VISIT (Py_TYPE (igo ));
654
651
Py_VISIT (igo -> parent );
655
652
Py_VISIT (igo -> tgtkey );
656
653
return 0 ;
@@ -698,48 +695,24 @@ static PyMethodDef _grouper_methods[] = {
698
695
{NULL , NULL } /* sentinel */
699
696
};
700
697
698
+ static PyType_Slot _grouper_slots [] = {
699
+ {Py_tp_dealloc , _grouper_dealloc },
700
+ {Py_tp_getattro , PyObject_GenericGetAttr },
701
+ {Py_tp_traverse , _grouper_traverse },
702
+ {Py_tp_iter , PyObject_SelfIter },
703
+ {Py_tp_iternext , _grouper_next },
704
+ {Py_tp_methods , _grouper_methods },
705
+ {Py_tp_new , itertools__grouper },
706
+ {Py_tp_free , PyObject_GC_Del },
707
+ {0 , NULL },
708
+ };
701
709
702
- static PyTypeObject _grouper_type = {
703
- PyVarObject_HEAD_INIT (NULL , 0 )
704
- "itertools._grouper" , /* tp_name */
705
- sizeof (_grouperobject ), /* tp_basicsize */
706
- 0 , /* tp_itemsize */
707
- /* methods */
708
- (destructor )_grouper_dealloc , /* tp_dealloc */
709
- 0 , /* tp_vectorcall_offset */
710
- 0 , /* tp_getattr */
711
- 0 , /* tp_setattr */
712
- 0 , /* tp_as_async */
713
- 0 , /* tp_repr */
714
- 0 , /* tp_as_number */
715
- 0 , /* tp_as_sequence */
716
- 0 , /* tp_as_mapping */
717
- 0 , /* tp_hash */
718
- 0 , /* tp_call */
719
- 0 , /* tp_str */
720
- PyObject_GenericGetAttr , /* tp_getattro */
721
- 0 , /* tp_setattro */
722
- 0 , /* tp_as_buffer */
723
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC , /* tp_flags */
724
- 0 , /* tp_doc */
725
- (traverseproc )_grouper_traverse , /* tp_traverse */
726
- 0 , /* tp_clear */
727
- 0 , /* tp_richcompare */
728
- 0 , /* tp_weaklistoffset */
729
- PyObject_SelfIter , /* tp_iter */
730
- (iternextfunc )_grouper_next , /* tp_iternext */
731
- _grouper_methods , /* tp_methods */
732
- 0 , /* tp_members */
733
- 0 , /* tp_getset */
734
- 0 , /* tp_base */
735
- 0 , /* tp_dict */
736
- 0 , /* tp_descr_get */
737
- 0 , /* tp_descr_set */
738
- 0 , /* tp_dictoffset */
739
- 0 , /* tp_init */
740
- 0 , /* tp_alloc */
741
- itertools__grouper , /* tp_new */
742
- PyObject_GC_Del , /* tp_free */
710
+ static PyType_Spec _grouper_spec = {
711
+ .name = "itertools._grouper" ,
712
+ .basicsize = sizeof (_grouperobject ),
713
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
714
+ Py_TPFLAGS_IMMUTABLETYPE ),
715
+ .slots = _grouper_slots ,
743
716
};
744
717
745
718
@@ -4986,8 +4959,47 @@ combinations_with_replacement(p, r)\n\
4986
4959
" );
4987
4960
4988
4961
static int
4989
- itertoolsmodule_exec (PyObject * m )
4962
+ itertoolsmodule_traverse (PyObject * mod , visitproc visit , void * arg )
4963
+ {
4964
+ itertools_state * state = get_module_state (mod );
4965
+ Py_VISIT (state -> groupby_type );
4966
+ Py_VISIT (state -> _grouper_type );
4967
+ return 0 ;
4968
+ }
4969
+
4970
+ static int
4971
+ itertoolsmodule_clear (PyObject * mod )
4972
+ {
4973
+ itertools_state * state = get_module_state (mod );
4974
+ Py_CLEAR (state -> groupby_type );
4975
+ Py_CLEAR (state -> _grouper_type );
4976
+ return 0 ;
4977
+ }
4978
+
4979
+ static void
4980
+ itertoolsmodule_free (void * mod )
4981
+ {
4982
+ (void )itertoolsmodule_clear ((PyObject * )mod );
4983
+ }
4984
+
4985
+ #define ADD_TYPE (module , type , spec ) \
4986
+ do { \
4987
+ type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \
4988
+ if (type == NULL) { \
4989
+ return -1; \
4990
+ } \
4991
+ if (PyModule_AddType(module, type) < 0) { \
4992
+ return -1; \
4993
+ } \
4994
+ } while (0)
4995
+
4996
+ static int
4997
+ itertoolsmodule_exec (PyObject * mod )
4990
4998
{
4999
+ itertools_state * state = get_module_state (mod );
5000
+ ADD_TYPE (mod , state -> groupby_type , & groupby_spec );
5001
+ ADD_TYPE (mod , state -> _grouper_type , & _grouper_spec );
5002
+
4991
5003
PyTypeObject * typelist [] = {
4992
5004
& accumulate_type ,
4993
5005
& batched_type ,
@@ -5007,16 +5019,14 @@ itertoolsmodule_exec(PyObject *m)
5007
5019
& permutations_type ,
5008
5020
& product_type ,
5009
5021
& repeat_type ,
5010
- & groupby_type ,
5011
- & _grouper_type ,
5012
5022
& tee_type ,
5013
5023
& teedataobject_type
5014
5024
};
5015
5025
5016
5026
Py_SET_TYPE (& teedataobject_type , & PyType_Type );
5017
5027
5018
5028
for (size_t i = 0 ; i < Py_ARRAY_LENGTH (typelist ); i ++ ) {
5019
- if (PyModule_AddType (m , typelist [i ]) < 0 ) {
5029
+ if (PyModule_AddType (mod , typelist [i ]) < 0 ) {
5020
5030
return -1 ;
5021
5031
}
5022
5032
}
@@ -5042,6 +5052,9 @@ static struct PyModuleDef itertoolsmodule = {
5042
5052
.m_size = sizeof (itertools_state ),
5043
5053
.m_methods = module_methods ,
5044
5054
.m_slots = itertoolsmodule_slots ,
5055
+ .m_traverse = itertoolsmodule_traverse ,
5056
+ .m_clear = itertoolsmodule_clear ,
5057
+ .m_free = itertoolsmodule_free ,
5045
5058
};
5046
5059
5047
5060
PyMODINIT_FUNC
0 commit comments