@@ -410,8 +410,11 @@ static PyObject *
410
410
PyCursesPanel_New (_curses_panel_state * state , PANEL * pan ,
411
411
PyCursesWindowObject * wo )
412
412
{
413
- PyCursesPanelObject * po = PyObject_New (PyCursesPanelObject ,
414
- state -> PyCursesPanel_Type );
413
+ assert (state != NULL );
414
+ PyTypeObject * type = state -> PyCursesPanel_Type ;
415
+ assert (type != NULL );
416
+ assert (type -> tp_alloc != NULL );
417
+ PyCursesPanelObject * po = (PyCursesPanelObject * )type -> tp_alloc (type , 0 );
415
418
if (po == NULL ) {
416
419
return NULL ;
417
420
}
@@ -426,20 +429,31 @@ PyCursesPanel_New(_curses_panel_state *state, PANEL *pan,
426
429
return (PyObject * )po ;
427
430
}
428
431
432
+ static int
433
+ PyCursesPanel_Clear (PyObject * op )
434
+ {
435
+ PyCursesPanelObject * self = _PyCursesPanelObject_CAST (op );
436
+ PyObject * extra = (PyObject * )panel_userptr (self -> pan );
437
+ if (extra != NULL ) {
438
+ Py_DECREF (extra );
439
+ if (set_panel_userptr (self -> pan , NULL ) == ERR ) {
440
+ curses_panel_panel_set_error (self , "set_panel_userptr" , NULL );
441
+ return -1 ;
442
+ }
443
+ }
444
+ // self->wo should not be cleared because an associated WINDOW may exist
445
+ return 0 ;
446
+ }
447
+
429
448
static void
430
449
PyCursesPanel_Dealloc (PyObject * self )
431
450
{
432
- PyObject * tp , * obj ;
433
- PyCursesPanelObject * po = _PyCursesPanelObject_CAST (self );
451
+ PyTypeObject * tp = Py_TYPE ( self ) ;
452
+ PyObject_GC_UnTrack (self );
434
453
435
- tp = (PyObject * ) Py_TYPE (po );
436
- obj = (PyObject * ) panel_userptr (po -> pan );
437
- if (obj ) {
438
- Py_DECREF (obj );
439
- if (set_panel_userptr (po -> pan , NULL ) == ERR ) {
440
- curses_panel_panel_set_error (po , "set_panel_userptr" , "__del__" );
441
- PyErr_FormatUnraisable ("Exception ignored in PyCursesPanel_Dealloc()" );
442
- }
454
+ PyCursesPanelObject * po = _PyCursesPanelObject_CAST (self );
455
+ if (PyCursesPanel_Clear (self ) < 0 ) {
456
+ PyErr_FormatUnraisable ("Exception ignored in PyCursesPanel_Dealloc()" );
443
457
}
444
458
if (del_panel (po -> pan ) == ERR && !PyErr_Occurred ()) {
445
459
curses_panel_panel_set_error (po , "del_panel" , "__del__" );
@@ -452,10 +466,20 @@ PyCursesPanel_Dealloc(PyObject *self)
452
466
PyErr_FormatUnraisable ("Exception ignored in PyCursesPanel_Dealloc()" );
453
467
}
454
468
}
455
- PyObject_Free (po );
469
+ tp -> tp_free (po );
456
470
Py_DECREF (tp );
457
471
}
458
472
473
+ static int
474
+ PyCursesPanel_Traverse (PyObject * op , visitproc visit , void * arg )
475
+ {
476
+ PyCursesPanelObject * self = _PyCursesPanelObject_CAST (op );
477
+ Py_VISIT (Py_TYPE (op ));
478
+ Py_VISIT (panel_userptr (self -> pan ));
479
+ Py_VISIT (self -> wo );
480
+ return 0 ;
481
+ }
482
+
459
483
/* panel_above(NULL) returns the bottom panel in the stack. To get
460
484
this behaviour we use curses.panel.bottom_panel(). */
461
485
/*[clinic input]
@@ -647,15 +671,21 @@ static PyMethodDef PyCursesPanel_Methods[] = {
647
671
/* -------------------------------------------------------*/
648
672
649
673
static PyType_Slot PyCursesPanel_Type_slots [] = {
674
+ {Py_tp_clear , PyCursesPanel_Clear },
650
675
{Py_tp_dealloc , PyCursesPanel_Dealloc },
676
+ {Py_tp_traverse , PyCursesPanel_Traverse },
651
677
{Py_tp_methods , PyCursesPanel_Methods },
652
678
{0 , 0 },
653
679
};
654
680
655
681
static PyType_Spec PyCursesPanel_Type_spec = {
656
682
.name = "_curses_panel.panel" ,
657
683
.basicsize = sizeof (PyCursesPanelObject ),
658
- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION ,
684
+ .flags = (
685
+ Py_TPFLAGS_DEFAULT
686
+ | Py_TPFLAGS_DISALLOW_INSTANTIATION
687
+ | Py_TPFLAGS_HAVE_GC
688
+ ),
659
689
.slots = PyCursesPanel_Type_slots
660
690
};
661
691
0 commit comments