@@ -105,8 +105,9 @@ static const char PyCursesVersion[] = "2.2";
105
105
#endif
106
106
107
107
#include "Python.h"
108
- #include "pycore_long.h" // _PyLong_GetZero()
109
- #include "pycore_structseq.h" // _PyStructSequence_NewType()
108
+ #include "pycore_capsule.h" // _PyCapsule_SetTraverse()
109
+ #include "pycore_long.h" // _PyLong_GetZero()
110
+ #include "pycore_structseq.h" // _PyStructSequence_NewType()
110
111
111
112
#ifdef __hpux
112
113
#define STRICT_SYSV_CURSES
@@ -173,6 +174,12 @@ get_cursesmodule_state(PyObject *Py_UNUSED(module))
173
174
return & curses_global_state ;
174
175
}
175
176
177
+ static inline _cursesmodule_state *
178
+ get_cursesmodule_state_by_cls (PyTypeObject * Py_UNUSED (cls ))
179
+ {
180
+ return & curses_global_state ;
181
+ }
182
+
176
183
static inline _cursesmodule_state *
177
184
get_cursesmodule_state_by_win (PyCursesWindowObject * Py_UNUSED (win ))
178
185
{
@@ -181,9 +188,9 @@ get_cursesmodule_state_by_win(PyCursesWindowObject *Py_UNUSED(win))
181
188
182
189
/*[clinic input]
183
190
module _curses
184
- class _curses.window "PyCursesWindowObject *" "&PyCursesWindow_Type "
191
+ class _curses.window "PyCursesWindowObject *" "clinic_state()->window_type "
185
192
[clinic start generated code]*/
186
- /*[clinic end generated code: output=da39a3ee5e6b4b0d input=43265c372c2887d6 ]*/
193
+ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ae6cb623018f2cbc ]*/
187
194
188
195
/* Tells whether setupterm() has been called to initialise terminfo. */
189
196
static int curses_setupterm_called = FALSE;
@@ -630,10 +637,6 @@ class component_converter(CConverter):
630
637
The Window Object
631
638
******************************************************************************/
632
639
633
- /* Definition of the window type */
634
-
635
- PyTypeObject PyCursesWindow_Type ;
636
-
637
640
/* Function prototype macros for Window object
638
641
639
642
X - function name
@@ -743,10 +746,9 @@ Window_TwoArgNoReturnFunction(wresize, int, "ii;lines,columns")
743
746
/* Allocation and deallocation of Window Objects */
744
747
745
748
static PyObject *
746
- PyCursesWindow_New (WINDOW * win , const char * encoding )
749
+ PyCursesWindow_New (_cursesmodule_state * state ,
750
+ WINDOW * win , const char * encoding )
747
751
{
748
- PyCursesWindowObject * wo ;
749
-
750
752
if (encoding == NULL ) {
751
753
#if defined(MS_WINDOWS )
752
754
char * buffer [100 ];
@@ -758,36 +760,53 @@ PyCursesWindow_New(WINDOW *win, const char *encoding)
758
760
}
759
761
#elif defined(CODESET )
760
762
const char * codeset = nl_langinfo (CODESET );
761
- if (codeset != NULL && codeset [0 ] != 0 )
763
+ if (codeset != NULL && codeset [0 ] != 0 ) {
762
764
encoding = codeset ;
765
+ }
763
766
#endif
764
- if (encoding == NULL )
767
+ if (encoding == NULL ) {
765
768
encoding = "utf-8" ;
769
+ }
766
770
}
767
771
768
- wo = PyObject_New (PyCursesWindowObject , & PyCursesWindow_Type );
769
- if (wo == NULL ) return NULL ;
772
+ PyCursesWindowObject * wo = PyObject_GC_New (PyCursesWindowObject ,
773
+ state -> window_type );
774
+ if (wo == NULL ) {
775
+ return NULL ;
776
+ }
770
777
wo -> win = win ;
771
778
wo -> encoding = _PyMem_Strdup (encoding );
772
779
if (wo -> encoding == NULL ) {
773
780
Py_DECREF (wo );
774
781
PyErr_NoMemory ();
775
782
return NULL ;
776
783
}
784
+ PyObject_GC_Track ((PyObject * )wo );
777
785
return (PyObject * )wo ;
778
786
}
779
787
780
788
static void
781
- PyCursesWindow_Dealloc ( PyCursesWindowObject * wo )
789
+ PyCursesWindow_dealloc ( PyObject * self )
782
790
{
791
+ PyTypeObject * window_type = Py_TYPE (self );
792
+ PyObject_GC_UnTrack (self );
793
+ PyCursesWindowObject * wo = (PyCursesWindowObject * )self ;
783
794
if (wo -> win != stdscr && wo -> win != NULL ) {
784
795
// silently ignore errors in delwin(3)
785
796
(void )delwin (wo -> win );
786
797
}
787
798
if (wo -> encoding != NULL ) {
788
799
PyMem_Free (wo -> encoding );
789
800
}
790
- PyObject_Free (wo );
801
+ window_type -> tp_free (self );
802
+ Py_DECREF (window_type );
803
+ }
804
+
805
+ static int
806
+ PyCursesWindow_traverse (PyObject * self , visitproc visit , void * arg )
807
+ {
808
+ Py_VISIT (Py_TYPE (self ));
809
+ return 0 ;
791
810
}
792
811
793
812
/* Addch, Addstr, Addnstr */
@@ -1391,7 +1410,8 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1,
1391
1410
return NULL ;
1392
1411
}
1393
1412
1394
- return (PyObject * )PyCursesWindow_New (win , NULL );
1413
+ _cursesmodule_state * state = get_cursesmodule_state_by_win (self );
1414
+ return PyCursesWindow_New (state , win , NULL );
1395
1415
}
1396
1416
1397
1417
/*[clinic input]
@@ -2140,7 +2160,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self)
2140
2160
/*[clinic input]
2141
2161
_curses.window.overlay
2142
2162
2143
- destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type ")
2163
+ destwin: object(type="PyCursesWindowObject *", subclass_of="clinic_state()->window_type ")
2144
2164
2145
2165
[
2146
2166
sminrow: int
@@ -2169,7 +2189,7 @@ _curses_window_overlay_impl(PyCursesWindowObject *self,
2169
2189
PyCursesWindowObject * destwin , int group_right_1 ,
2170
2190
int sminrow , int smincol , int dminrow ,
2171
2191
int dmincol , int dmaxrow , int dmaxcol )
2172
- /*[clinic end generated code: output=82bb2c4cb443ca58 input=7edd23ad22cc1984 ]*/
2192
+ /*[clinic end generated code: output=82bb2c4cb443ca58 input=6e4b32a7c627a356 ]*/
2173
2193
{
2174
2194
int rtn ;
2175
2195
@@ -2187,7 +2207,7 @@ _curses_window_overlay_impl(PyCursesWindowObject *self,
2187
2207
/*[clinic input]
2188
2208
_curses.window.overwrite
2189
2209
2190
- destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type ")
2210
+ destwin: object(type="PyCursesWindowObject *", subclass_of="clinic_state()->window_type ")
2191
2211
2192
2212
[
2193
2213
sminrow: int
@@ -2217,7 +2237,7 @@ _curses_window_overwrite_impl(PyCursesWindowObject *self,
2217
2237
int group_right_1 , int sminrow , int smincol ,
2218
2238
int dminrow , int dmincol , int dmaxrow ,
2219
2239
int dmaxcol )
2220
- /*[clinic end generated code: output=12ae007d1681be28 input=ea5de1b35cd948e0 ]*/
2240
+ /*[clinic end generated code: output=12ae007d1681be28 input=d83dd8b24ff2bcc9 ]*/
2221
2241
{
2222
2242
int rtn ;
2223
2243
@@ -2426,7 +2446,8 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1,
2426
2446
return NULL ;
2427
2447
}
2428
2448
2429
- return (PyObject * )PyCursesWindow_New (win , self -> encoding );
2449
+ _cursesmodule_state * state = get_cursesmodule_state_by_win (self );
2450
+ return PyCursesWindow_New (state , win , self -> encoding );
2430
2451
}
2431
2452
2432
2453
/*[clinic input]
@@ -2564,9 +2585,11 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value, void *P
2564
2585
return 0 ;
2565
2586
}
2566
2587
2588
+ #define clinic_state () (get_cursesmodule_state_by_cls(Py_TYPE(self)))
2567
2589
#include "clinic/_cursesmodule.c.h"
2590
+ #undef clinic_state
2568
2591
2569
- static PyMethodDef PyCursesWindow_Methods [] = {
2592
+ static PyMethodDef PyCursesWindow_methods [] = {
2570
2593
_CURSES_WINDOW_ADDCH_METHODDEF
2571
2594
_CURSES_WINDOW_ADDNSTR_METHODDEF
2572
2595
_CURSES_WINDOW_ADDSTR_METHODDEF
@@ -2660,42 +2683,27 @@ static PyGetSetDef PyCursesWindow_getsets[] = {
2660
2683
{NULL , NULL , NULL , NULL } /* sentinel */
2661
2684
};
2662
2685
2663
- /* -------------------------------------------------------*/
2686
+ static PyType_Slot PyCursesWindow_Type_slots [] = {
2687
+ {Py_tp_methods , PyCursesWindow_methods },
2688
+ {Py_tp_getset , PyCursesWindow_getsets },
2689
+ {Py_tp_dealloc , PyCursesWindow_dealloc },
2690
+ {Py_tp_traverse , PyCursesWindow_traverse },
2691
+ {0 , NULL }
2692
+ };
2664
2693
2665
- PyTypeObject PyCursesWindow_Type = {
2666
- PyVarObject_HEAD_INIT (NULL , 0 )
2667
- "_curses.window" , /*tp_name*/
2668
- sizeof (PyCursesWindowObject ), /*tp_basicsize*/
2669
- 0 , /*tp_itemsize*/
2670
- /* methods */
2671
- (destructor )PyCursesWindow_Dealloc , /*tp_dealloc*/
2672
- 0 , /*tp_vectorcall_offset*/
2673
- (getattrfunc )0 , /*tp_getattr*/
2674
- (setattrfunc )0 , /*tp_setattr*/
2675
- 0 , /*tp_as_async*/
2676
- 0 , /*tp_repr*/
2677
- 0 , /*tp_as_number*/
2678
- 0 , /*tp_as_sequence*/
2679
- 0 , /*tp_as_mapping*/
2680
- 0 , /*tp_hash*/
2681
- 0 , /*tp_call*/
2682
- 0 , /*tp_str*/
2683
- 0 , /*tp_getattro*/
2684
- 0 , /*tp_setattro*/
2685
- 0 , /*tp_as_buffer*/
2686
- Py_TPFLAGS_DEFAULT , /*tp_flags*/
2687
- 0 , /*tp_doc*/
2688
- 0 , /*tp_traverse*/
2689
- 0 , /*tp_clear*/
2690
- 0 , /*tp_richcompare*/
2691
- 0 , /*tp_weaklistoffset*/
2692
- 0 , /*tp_iter*/
2693
- 0 , /*tp_iternext*/
2694
- PyCursesWindow_Methods , /*tp_methods*/
2695
- 0 , /* tp_members */
2696
- PyCursesWindow_getsets , /* tp_getset */
2694
+ static PyType_Spec PyCursesWindow_Type_spec = {
2695
+ .name = "_curses.window" ,
2696
+ .basicsize = sizeof (PyCursesWindowObject ),
2697
+ .flags = Py_TPFLAGS_DEFAULT
2698
+ | Py_TPFLAGS_DISALLOW_INSTANTIATION
2699
+ | Py_TPFLAGS_IMMUTABLETYPE
2700
+ | Py_TPFLAGS_HEAPTYPE
2701
+ | Py_TPFLAGS_HAVE_GC ,
2702
+ .slots = PyCursesWindow_Type_slots
2697
2703
};
2698
2704
2705
+ /* -------------------------------------------------------*/
2706
+
2699
2707
/* Function Body Macros - They are ugly but very, very useful. ;-)
2700
2708
2701
2709
X - function name
@@ -3177,7 +3185,8 @@ _curses_getwin(PyObject *module, PyObject *file)
3177
3185
PyErr_SetString (state -> error , catchall_NULL );
3178
3186
goto error ;
3179
3187
}
3180
- res = PyCursesWindow_New (win , NULL );
3188
+ _cursesmodule_state * state = get_cursesmodule_state (module );
3189
+ res = PyCursesWindow_New (state , win , NULL );
3181
3190
3182
3191
error :
3183
3192
fclose (fp );
@@ -3349,7 +3358,8 @@ _curses_initscr_impl(PyObject *module)
3349
3358
3350
3359
if (curses_initscr_called ) {
3351
3360
wrefresh (stdscr );
3352
- return (PyObject * )PyCursesWindow_New (stdscr , NULL );
3361
+ _cursesmodule_state * state = get_cursesmodule_state (module );
3362
+ return PyCursesWindow_New (state , stdscr , NULL );
3353
3363
}
3354
3364
3355
3365
win = initscr ();
@@ -3452,12 +3462,13 @@ _curses_initscr_impl(PyObject *module)
3452
3462
SetDictInt ("COLS" , COLS );
3453
3463
#undef SetDictInt
3454
3464
3455
- PyCursesWindowObject * winobj = (PyCursesWindowObject * )PyCursesWindow_New (win , NULL );
3465
+ _cursesmodule_state * state = get_cursesmodule_state (module );
3466
+ PyObject * winobj = PyCursesWindow_New (state , win , NULL );
3456
3467
if (winobj == NULL ) {
3457
3468
return NULL ;
3458
3469
}
3459
- curses_screen_encoding = winobj -> encoding ;
3460
- return ( PyObject * ) winobj ;
3470
+ curses_screen_encoding = (( PyCursesWindowObject * ) winobj ) -> encoding ;
3471
+ return winobj ;
3461
3472
}
3462
3473
3463
3474
/*[clinic input]
@@ -3829,7 +3840,8 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols)
3829
3840
return NULL ;
3830
3841
}
3831
3842
3832
- return (PyObject * )PyCursesWindow_New (win , NULL );
3843
+ _cursesmodule_state * state = get_cursesmodule_state (module );
3844
+ return PyCursesWindow_New (state , win , NULL );
3833
3845
}
3834
3846
3835
3847
/*[clinic input]
@@ -3869,7 +3881,8 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols,
3869
3881
return NULL ;
3870
3882
}
3871
3883
3872
- return (PyObject * )PyCursesWindow_New (win , NULL );
3884
+ _cursesmodule_state * state = get_cursesmodule_state (module );
3885
+ return PyCursesWindow_New (state , win , NULL );
3873
3886
}
3874
3887
3875
3888
/*[clinic input]
@@ -4893,11 +4906,40 @@ curses_capi_capsule_destructor(PyObject *op)
4893
4906
curses_capi_free (capi );
4894
4907
}
4895
4908
4909
+ static int
4910
+ curses_capi_capsule_traverse (PyObject * op , visitproc visit , void * arg )
4911
+ {
4912
+ void * * capi_ptr = PyCapsule_GetPointer (op , PyCurses_CAPSULE_NAME );
4913
+ assert (capi_ptr != NULL );
4914
+ Py_VISIT (capi_ptr [0 ]); // visit curses window type
4915
+ return 0 ;
4916
+ }
4917
+
4918
+ static int
4919
+ curses_capi_capsule_clear (PyObject * op )
4920
+ {
4921
+ void * * capi_ptr = PyCapsule_GetPointer (op , PyCurses_CAPSULE_NAME );
4922
+ assert (capi_ptr != NULL );
4923
+ Py_CLEAR (capi_ptr [0 ]); // clear curses window type
4924
+ return 0 ;
4925
+ }
4926
+
4896
4927
static PyObject *
4897
4928
curses_capi_capsule_new (void * capi )
4898
4929
{
4899
- return PyCapsule_New (capi , PyCurses_CAPSULE_NAME ,
4900
- curses_capi_capsule_destructor );
4930
+ PyObject * capsule = PyCapsule_New (capi , PyCurses_CAPSULE_NAME ,
4931
+ curses_capi_capsule_destructor );
4932
+ if (capsule == NULL ) {
4933
+ return NULL ;
4934
+ }
4935
+ if (_PyCapsule_SetTraverse (capsule ,
4936
+ curses_capi_capsule_traverse ,
4937
+ curses_capi_capsule_clear ) < 0 )
4938
+ {
4939
+ Py_DECREF (capsule );
4940
+ return NULL ;
4941
+ }
4942
+ return capsule ;
4901
4943
}
4902
4944
4903
4945
/* Module initialization */
@@ -4907,13 +4949,14 @@ cursesmodule_exec(PyObject *module)
4907
4949
{
4908
4950
_cursesmodule_state * state = get_cursesmodule_state (module );
4909
4951
/* Initialize object type */
4910
- if (PyType_Ready (& PyCursesWindow_Type ) < 0 ) {
4952
+ state -> window_type = (PyTypeObject * )PyType_FromModuleAndSpec (
4953
+ module , & PyCursesWindow_Type_spec , NULL );
4954
+ if (state -> window_type == NULL ) {
4911
4955
return -1 ;
4912
4956
}
4913
- if (PyModule_AddType (module , & PyCursesWindow_Type ) < 0 ) {
4957
+ if (PyModule_AddType (module , state -> window_type ) < 0 ) {
4914
4958
return -1 ;
4915
4959
}
4916
- state -> window_type = & PyCursesWindow_Type ;
4917
4960
4918
4961
/* Add some symbolic constants to the module */
4919
4962
PyObject * module_dict = PyModule_GetDict (module );
0 commit comments