[pygobject] Remove PyGObjectWeakRef now that g_binding_unbind exists
- From: Simon Feltman <sfeltman src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Remove PyGObjectWeakRef now that g_binding_unbind exists
- Date: Mon, 14 Oct 2013 22:22:55 +0000 (UTC)
commit 799989ada2f6b1d729f078f204445651c808a2c7
Author: Simon Feltman <sfeltman src gnome org>
Date: Fri May 3 04:37:13 2013 -0700
Remove PyGObjectWeakRef now that g_binding_unbind exists
Remove the static code for managing GBinding weak references now that GLib
has a method (unbind) for clearing out bindings.
https://bugzilla.gnome.org/show_bug.cgi?id=699571
gi/_gobject/pygobject.c | 59 +----------------------------------------------
gi/overrides/GObject.py | 19 +++++++++++++++
tests/test_gobject.py | 41 +++++++++++++++++++-------------
3 files changed, 44 insertions(+), 75 deletions(-)
---
diff --git a/gi/_gobject/pygobject.c b/gi/_gobject/pygobject.c
index 65d5de9..c107a17 100644
--- a/gi/_gobject/pygobject.c
+++ b/gi/_gobject/pygobject.c
@@ -38,7 +38,6 @@ static int pygobject_clear(PyGObject *self);
static PyObject * pyg_type_get_bases(GType gtype);
static inline int pygobject_clear(PyGObject *self);
static PyObject * pygobject_weak_ref_new(GObject *obj, PyObject *callback, PyObject *user_data);
-static PyObject * pygbinding_weak_ref_new(GObject *obj);
static inline PyGObjectData * pyg_object_peek_inst_data(GObject *obj);
static void pygobject_inherit_slots(PyTypeObject *type, PyObject *bases,
gboolean check_for_present);
@@ -1637,7 +1636,7 @@ pygobject_bind_property(PyGObject *self, PyObject *args)
return NULL;
}
- return pygbinding_weak_ref_new(G_OBJECT (binding));
+ return pygobject_new (G_OBJECT (binding));
}
static PyObject *
@@ -2341,54 +2340,6 @@ pygobject_weak_ref_call(PyGObjectWeakRef *self, PyObject *args, PyObject *kw)
}
}
-
-/* -------------- GBinding Weak Reference ----------------- */
-
-/**
- * BindingWeakRef
- *
- * The BindingWeakRef object is used to manage GBinding objects within python
- * created through GObject.bind_property. It is a sub-class PyGObjectWeakRef so
- * that we can maintain the same reference counting semantics between Python
- * and GObject Binding objects. This gives explicit direct control of the
- * binding lifetime by using the "unbind" method on the BindingWeakRef object
- * along with implicit management based on the lifetime of the source or
- * target objects.
- */
-
-PYGLIB_DEFINE_TYPE("gi._gobject.GBindingWeakRef", PyGBindingWeakRef_Type, PyGObjectWeakRef);
-
-static PyObject *
-pygbinding_weak_ref_new(GObject *obj)
-{
- PyGObjectWeakRef *self;
-
- self = PyObject_GC_New(PyGObjectWeakRef, &PyGBindingWeakRef_Type);
- self->callback = NULL;
- self->user_data = NULL;
- self->obj = obj;
- g_object_weak_ref(self->obj, (GWeakNotify) pygobject_weak_ref_notify, self);
- return (PyObject *) self;
-}
-
-static PyObject *
-pygbinding_weak_ref_unbind(PyGObjectWeakRef *self, PyObject *args)
-{
- if (!self->obj) {
- PyErr_SetString(PyExc_ValueError, "weak binding ref already unreffed");
- return NULL;
- }
- g_object_unref(self->obj);
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef pygbinding_weak_ref_methods[] = {
- { "unbind", (PyCFunction)pygbinding_weak_ref_unbind, METH_NOARGS},
- { NULL, NULL, 0}
-};
-
-
static gpointer
pyobject_copy(gpointer boxed)
{
@@ -2494,12 +2445,4 @@ pygobject_object_register_types(PyObject *d)
if (PyType_Ready(&PyGObjectWeakRef_Type) < 0)
return;
PyDict_SetItemString(d, "GObjectWeakRef", (PyObject *) &PyGObjectWeakRef_Type);
-
- PyGBindingWeakRef_Type.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
- PyGBindingWeakRef_Type.tp_doc = "A GBinding weak reference";
- PyGBindingWeakRef_Type.tp_methods = pygbinding_weak_ref_methods;
- PyGBindingWeakRef_Type.tp_base = &PyGObjectWeakRef_Type;
- if (PyType_Ready(&PyGBindingWeakRef_Type) < 0)
- return;
- PyDict_SetItemString(d, "GBindingWeakRef", (PyObject *) &PyGBindingWeakRef_Type);
}
diff --git a/gi/overrides/GObject.py b/gi/overrides/GObject.py
index b3aad47..07cb5bb 100644
--- a/gi/overrides/GObject.py
+++ b/gi/overrides/GObject.py
@@ -685,6 +685,25 @@ GObject = Object
__all__ += ['Object', 'GObject']
+class Binding(GObjectModule.Binding):
+ def __call__(self):
+ warnings.warn('Using parentheses (binding()) to retrieve the Binding object is no '
+ 'longer needed because the binding is returned directly from "bind_property.',
+ PyGIDeprecationWarning, stacklevel=2)
+ return self
+
+ def unbind(self):
+ if hasattr(self, '_unbound'):
+ raise ValueError('binding has already been cleared out')
+ else:
+ setattr(self, '_unbound', True)
+ super(Binding, self).unbind()
+
+
+Binding = override(Binding)
+__all__.append('Binding')
+
+
Property = propertyhelper.Property
Signal = signalhelper.Signal
SignalOverride = signalhelper.SignalOverride
diff --git a/tests/test_gobject.py b/tests/test_gobject.py
index 57d3822..d49011f 100644
--- a/tests/test_gobject.py
+++ b/tests/test_gobject.py
@@ -415,6 +415,8 @@ class TestContextManagers(unittest.TestCase):
self.assertEqual(self.tracking, [2])
+ unittest skipUnless(hasattr(GObject.Binding, 'unbind'),
+ 'Requires newer GLib which has g_binding_unbind')
class TestPropertyBindings(unittest.TestCase):
class TestObject(GObject.GObject):
int_prop = GObject.Property(default=0, type=int)
@@ -509,8 +511,8 @@ class TestPropertyBindings(unittest.TestCase):
GObject.BindingFlags.BIDIRECTIONAL,
transform_to, transform_from, test_data)
binding = binding # PyFlakes
- binding_ref_count = sys.getrefcount(binding())
- binding_gref_count = binding().__grefcount__
+ binding_ref_count = sys.getrefcount(binding)
+ binding_gref_count = binding.__grefcount__
self.source.int_prop = 1
self.assertEqual(self.source.int_prop, 1)
@@ -520,8 +522,8 @@ class TestPropertyBindings(unittest.TestCase):
self.assertEqual(self.source.int_prop, 2)
self.assertEqual(self.target.int_prop, 4)
- self.assertEqual(sys.getrefcount(binding()), binding_ref_count)
- self.assertEqual(binding().__grefcount__, binding_gref_count)
+ self.assertEqual(sys.getrefcount(binding), binding_ref_count)
+ self.assertEqual(binding.__grefcount__, binding_gref_count)
# test_data ref count increases by 2, once for each callback.
self.assertEqual(sys.getrefcount(test_data), test_data_ref_count + 2)
@@ -530,9 +532,6 @@ class TestPropertyBindings(unittest.TestCase):
# Unbind should clear out the binding and its transforms
binding.unbind()
- self.assertEqual(binding(), None)
- del binding
- gc.collect()
# Setting source or target should not change the other.
self.target.int_prop = 3
@@ -554,8 +553,9 @@ class TestPropertyBindings(unittest.TestCase):
self.assertEqual(self.source.int_prop, 1)
self.assertEqual(self.target.int_prop, 1)
+ # unbind should clear out the bindings self reference
binding.unbind()
- self.assertEqual(binding(), None)
+ self.assertEqual(binding.__grefcount__, 1)
self.source.int_prop = 10
self.assertEqual(self.source.int_prop, 10)
@@ -572,7 +572,7 @@ class TestPropertyBindings(unittest.TestCase):
# the act of binding and the ref incurred by using __call__ to generate
# a wrapper from the weak binding ref within python.
binding = self.source.bind_property('int_prop', self.target, 'int_prop')
- self.assertEqual(binding().__grefcount__, 2)
+ self.assertEqual(binding.__grefcount__, 2)
# Creating a binding does not inc refs on source and target (they are weak
# on the binding object itself)
@@ -581,18 +581,25 @@ class TestPropertyBindings(unittest.TestCase):
# Use GObject.get_property because the "props" accessor leaks.
# Note property names are canonicalized.
- self.assertEqual(binding().get_property('source'), self.source)
- self.assertEqual(binding().get_property('source_property'), 'int-prop')
- self.assertEqual(binding().get_property('target'), self.target)
- self.assertEqual(binding().get_property('target_property'), 'int-prop')
- self.assertEqual(binding().get_property('flags'), GObject.BindingFlags.DEFAULT)
-
- # Delete reference to source or target and the binding should listen.
+ self.assertEqual(binding.get_property('source'), self.source)
+ self.assertEqual(binding.get_property('source_property'), 'int-prop')
+ self.assertEqual(binding.get_property('target'), self.target)
+ self.assertEqual(binding.get_property('target_property'), 'int-prop')
+ self.assertEqual(binding.get_property('flags'), GObject.BindingFlags.DEFAULT)
+
+ # Delete reference to source or target and the binding will remove its own
+ # "self reference".
ref = self.source.weak_ref()
del self.source
gc.collect()
self.assertEqual(ref(), None)
- self.assertEqual(binding(), None)
+ self.assertEqual(binding.__grefcount__, 1)
+
+ # Finally clear out the last ref held by the python wrapper
+ ref = binding.weak_ref()
+ del binding
+ gc.collect()
+ self.assertEqual(ref(), None)
class TestGValue(unittest.TestCase):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]