diff options
author | Bilal Elmoussaoui <belmouss@redhat.com> | 2022-02-15 15:02:54 +0100 |
---|---|---|
committer | Bilal Elmoussaoui <belmouss@redhat.com> | 2022-07-26 19:27:09 +0200 |
commit | ae542670ac9f0899e54ca907199b4489571a869f (patch) | |
tree | a0eae51b1dfce13bbff8b4eea6636eb318ac8975 | |
parent | 3e46d7c47b218056b136db8e95eb04f4e5338ef7 (diff) | |
download | pygobject-ae542670ac9f0899e54ca907199b4489571a869f.tar.gz |
object: Allow overriding dispose implementation
In GTK4 people are expected to unparent their custom GtkWidget
implementation
in the object's dispose method which is the main motivation behind this
patch
-rw-r--r-- | gi/gimodule.c | 41 | ||||
-rw-r--r-- | tests/test_gobject.py | 15 |
2 files changed, 56 insertions, 0 deletions
diff --git a/gi/gimodule.c b/gi/gimodule.c index 766fd341..0e735872 100644 --- a/gi/gimodule.c +++ b/gi/gimodule.c @@ -938,6 +938,46 @@ pyg_object_set_property (GObject *object, guint property_id, } static void +pyg_object_dispose (GObject *object) +{ + PyObject *object_wrapper, *retval; + PyGILState_STATE state; + GObjectClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_FROM_INSTANCE (object))); + if (parent_class == NULL) + return; + state = PyGILState_Ensure(); + + object_wrapper = g_object_get_qdata(object, pygobject_wrapper_key); + + if (object_wrapper) + Py_INCREF (object_wrapper); + else + object_wrapper = pygobject_new(object); + + if (object_wrapper == NULL) { + PyGILState_Release(state); + return; + } + // Chain up only if the object override dispose + if (PyObject_HasAttrString (object_wrapper, "do_dispose")) { + retval = PyObject_CallMethod(object_wrapper, "do_dispose", NULL); + if (retval) { + Py_DECREF(retval); + } else { + PyErr_Print(); + } + + // Chain up the dispose call + if (parent_class->dispose) { + parent_class->dispose(object); + } + } + Py_DECREF(object_wrapper); + + PyGILState_Release(state); +} + +static void pyg_object_class_init(GObjectClass *class, PyObject *py_class) { PyObject *gproperties, *gsignals, *overridden_signals; @@ -945,6 +985,7 @@ pyg_object_class_init(GObjectClass *class, PyObject *py_class) class->set_property = pyg_object_set_property; class->get_property = pyg_object_get_property; + class->dispose = pyg_object_dispose; /* install signals */ /* we look this up in the instance dictionary, so we don't diff --git a/tests/test_gobject.py b/tests/test_gobject.py index fbc3bb79..6a4f52ab 100644 --- a/tests/test_gobject.py +++ b/tests/test_gobject.py @@ -775,6 +775,21 @@ class TestGValue(unittest.TestCase): value = GObject.Value(GObject.TYPE_OBJECT, obj) self.assertEqual(value.get_value(), obj) + def test_dispose_object(self): + class TestObject(GObject.Object): + def __init__(self): + super().__init__() + self.child = "Some Child" + def do_dispose(self): + print("running dispose") + self.child = None + return True + obj = TestObject() + print(obj) + obj.run_dispose() + print("test") + self.assertEqual(obj.child, None) + def test_value_array(self): value = GObject.Value(GObject.ValueArray) self.assertEqual(value.g_type, GObject.type_from_name('GValueArray')) |