1 From 9456ba70fdb98b3a4eb7ee2f630182387a54ca00 Mon Sep 17 00:00:00 2001
2 From: Martin Pitt <martinpitt@gnome.org>
3 Date: Tue, 19 Feb 2013 15:39:56 +0100
4 Subject: [PATCH] Move property and signal creation into _class_init()
6 We must not add class interfaces after g_type_class_ref() has been called the
7 first time. Move signal and property creation from pyg_type_register() into
8 pyg_object_class_init(), and drop the hack of registering interfaces twice.
10 This is a backport of commit efcb0f9fd for 2.28.x. This allows old pygtk
11 applications to work with pygobject 2.28.x and glib 2.35.x.
13 https://bugzilla.gnome.org/show_bug.cgi?id=694108
15 gobject/gobjectmodule.c | 177 +++++++++++++++++++-----------------------------
16 1 file changed, 70 insertions(+), 107 deletions(-)
18 diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
19 index 2a84606..91f7315 100644
20 --- a/gobject/gobjectmodule.c
21 +++ b/gobject/gobjectmodule.c
22 @@ -312,13 +312,6 @@ pyg_object_get_property (GObject *object, guint property_id,
23 pyglib_gil_state_release(state);
27 -pyg_object_class_init(GObjectClass *class, PyObject *py_class)
29 - class->set_property = pyg_object_set_property;
30 - class->get_property = pyg_object_get_property;
33 typedef struct _PyGSignalAccumulatorData {
36 @@ -484,15 +477,14 @@ override_signal(GType instance_type, const gchar *signal_name)
40 -add_signals (GType instance_type, PyObject *signals)
41 +add_signals (GObjectClass *klass, PyObject *signals)
44 - GObjectClass *oclass;
46 PyObject *key, *value, *overridden_signals = NULL;
47 + GType instance_type = G_OBJECT_CLASS_TYPE (klass);
49 overridden_signals = PyDict_New();
50 - oclass = g_type_class_ref(instance_type);
51 while (PyDict_Next(signals, &pos, &key, &value)) {
52 const gchar *signal_name;
53 gchar *signal_name_canon, *c;
54 @@ -530,7 +522,6 @@ add_signals (GType instance_type, PyObject *signals)
58 - g_type_class_unref(oclass);
60 return overridden_signals;
62 @@ -800,14 +791,12 @@ pyg_param_spec_from_object (PyObject *tuple)
66 -add_properties (GType instance_type, PyObject *properties)
67 +add_properties (GObjectClass *klass, PyObject *properties)
70 - GObjectClass *oclass;
72 PyObject *key, *value;
74 - oclass = g_type_class_ref(instance_type);
75 while (PyDict_Next(properties, &pos, &key, &value)) {
76 const gchar *prop_name;
78 @@ -873,7 +862,7 @@ add_properties (GType instance_type, PyObject *properties)
82 - g_object_class_install_property(oclass, 1, pspec);
83 + g_object_class_install_property(klass, 1, pspec);
85 PyObject *type, *value, *traceback;
87 @@ -883,7 +872,7 @@ add_properties (GType instance_type, PyObject *properties)
89 "%s (while registering property '%s' for GType '%s')",
90 PYGLIB_PyUnicode_AsString(value),
91 - prop_name, g_type_name(instance_type));
92 + prop_name, G_OBJECT_CLASS_NAME(klass));
94 value = PYGLIB_PyUnicode_FromString(msg);
96 @@ -892,11 +881,63 @@ add_properties (GType instance_type, PyObject *properties)
100 - g_type_class_unref(oclass);
105 +pyg_object_class_init(GObjectClass *class, PyObject *py_class)
107 + PyObject *gproperties, *gsignals, *overridden_signals;
108 + PyObject *class_dict = ((PyTypeObject*) py_class)->tp_dict;
110 + class->set_property = pyg_object_set_property;
111 + class->get_property = pyg_object_get_property;
113 + /* install signals */
114 + /* we look this up in the instance dictionary, so we don't
115 + * accidentally get a parent type's __gsignals__ attribute. */
116 + gsignals = PyDict_GetItemString(class_dict, "__gsignals__");
118 + if (!PyDict_Check(gsignals)) {
119 + PyErr_SetString(PyExc_TypeError,
120 + "__gsignals__ attribute not a dict!");
123 + if (!(overridden_signals = add_signals(class, gsignals))) {
126 + if (PyDict_SetItemString(class_dict, "__gsignals__",
127 + overridden_signals)) {
130 + Py_DECREF(overridden_signals);
132 + PyDict_DelItemString(class_dict, "__gsignals__");
137 + /* install properties */
138 + /* we look this up in the instance dictionary, so we don't
139 + * accidentally get a parent type's __gproperties__ attribute. */
140 + gproperties = PyDict_GetItemString(class_dict, "__gproperties__");
142 + if (!PyDict_Check(gproperties)) {
143 + PyErr_SetString(PyExc_TypeError,
144 + "__gproperties__ attribute not a dict!");
147 + if (!add_properties(class, gproperties)) {
150 + PyDict_DelItemString(class_dict, "__gproperties__");
151 + /* Borrowed reference. Py_DECREF(gproperties); */
158 pyg_register_class_init(GType gtype, PyGClassInitFunc class_init)
161 @@ -1068,7 +1109,7 @@ pygobject__g_instance_init(GTypeInstance *instance,
164 pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
165 - PyObject *bases, gboolean new_interfaces,
167 GType *parent_interfaces, guint n_parent_interfaces)
170 @@ -1082,7 +1123,6 @@ pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
172 PyObject *base = PyTuple_GET_ITEM(bases, i);
174 - gboolean is_new = TRUE;
175 const GInterfaceInfo *iinfo;
176 GInterfaceInfo iinfo_copy;
178 @@ -1099,16 +1139,6 @@ pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
179 if (!G_TYPE_IS_INTERFACE(itype))
182 - for (k = 0; k < n_parent_interfaces; ++k) {
183 - if (parent_interfaces[k] == itype) {
189 - if ((new_interfaces && !is_new) || (!new_interfaces && is_new))
192 iinfo = pyg_lookup_interface_info(itype);
195 @@ -1129,7 +1159,7 @@ pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
197 pyg_type_register(PyTypeObject *class, const char *type_name)
199 - PyObject *gtype, *gsignals, *gproperties, *overridden_signals;
201 GType parent_type, instance_type;
202 GType *parent_interfaces;
203 guint n_parent_interfaces;
204 @@ -1216,88 +1246,22 @@ pyg_type_register(PyTypeObject *class, const char *type_name)
208 - * Note: Interfaces to be implemented are searched twice. First
209 - * we register interfaces that are already implemented by a parent
210 - * type. The second time, the remaining interfaces are
211 - * registered, i.e. the ones that are not implemented by a parent
212 - * type. In between these two loops, properties and signals are
213 - * registered. It has to be done this way, in two steps,
214 - * otherwise glib will complain. If registering all interfaces
215 - * always before properties, you get an error like:
217 - * ../gobject:121: Warning: Object class
218 - * test_interface+MyObject doesn't implement property
219 - * 'some-property' from interface 'TestInterface'
221 - * If, on the other hand, you register interfaces after
222 - * registering the properties, you get something like:
224 - * ../gobject:121: Warning: cannot add interface type
225 - * `TestInterface' to type `test_interface+MyUnknown', since
226 - * type `test_interface+MyUnknown' already conforms to
229 - * This looks like a GLib quirk, but no bug has been filed
230 - * upstream. However we have a unit test for this particular
231 - * problem, which can be found in test_interfaces.py, class
232 - * TestInterfaceImpl.
233 + * Note, all interfaces need to be registered before the first
234 + * g_type_class_ref(), see bug #686149.
236 * See also comment above pyg_type_add_interfaces().
238 - pyg_type_add_interfaces(class, instance_type, class->tp_bases, FALSE,
239 + pyg_type_add_interfaces(class, instance_type, class->tp_bases,
240 parent_interfaces, n_parent_interfaces);
242 - /* we look this up in the instance dictionary, so we don't
243 - * accidentally get a parent type's __gsignals__ attribute. */
244 - gsignals = PyDict_GetItemString(class->tp_dict, "__gsignals__");
246 - if (!PyDict_Check(gsignals)) {
247 - PyErr_SetString(PyExc_TypeError,
248 - "__gsignals__ attribute not a dict!");
249 - g_free(parent_interfaces);
252 - if (!(overridden_signals = add_signals(instance_type, gsignals))) {
253 - g_free(parent_interfaces);
256 - if (PyDict_SetItemString(class->tp_dict, "__gsignals__",
257 - overridden_signals)) {
258 - g_free(parent_interfaces);
261 - Py_DECREF(overridden_signals);
266 - /* we look this up in the instance dictionary, so we don't
267 - * accidentally get a parent type's __gsignals__ attribute. */
268 - gproperties = PyDict_GetItemString(class->tp_dict, "__gproperties__");
270 - if (!PyDict_Check(gproperties)) {
271 - PyErr_SetString(PyExc_TypeError,
272 - "__gproperties__ attribute not a dict!");
273 - g_free(parent_interfaces);
276 - if (!add_properties(instance_type, gproperties)) {
277 - g_free(parent_interfaces);
280 - PyDict_DelItemString(class->tp_dict, "__gproperties__");
281 - /* Borrowed reference. Py_DECREF(gproperties); */
284 + gclass = g_type_class_ref(instance_type);
285 + if (PyErr_Occurred() != NULL) {
286 + g_type_class_unref(gclass);
287 + g_free(parent_interfaces);
291 - /* Register new interfaces, that are _not_ already defined by
292 - * the parent type. FIXME: See above.
294 - pyg_type_add_interfaces(class, instance_type, class->tp_bases, TRUE,
295 - parent_interfaces, n_parent_interfaces);
297 - gclass = g_type_class_ref(instance_type);
298 if (pyg_run_class_init(instance_type, gclass, class)) {
299 g_type_class_unref(gclass);
300 g_free(parent_interfaces);
301 @@ -1306,9 +1270,8 @@ pyg_type_register(PyTypeObject *class, const char *type_name)
302 g_type_class_unref(gclass);
303 g_free(parent_interfaces);
306 - PyDict_DelItemString(class->tp_dict, "__gsignals__");
308 + if (PyErr_Occurred() != NULL)