]> git.draconx.ca Git - gentoo-fixes.git/blob - dev-python/pygobject/files/pygobject-2.28.6-glib-2.36-class_init.patch
Resurrect dev-python/pygtk.
[gentoo-fixes.git] / dev-python / pygobject / files / pygobject-2.28.6-glib-2.36-class_init.patch
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()
5
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.
9
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.
12
13 https://bugzilla.gnome.org/show_bug.cgi?id=694108
14 ---
15  gobject/gobjectmodule.c | 177 +++++++++++++++++++-----------------------------
16  1 file changed, 70 insertions(+), 107 deletions(-)
17
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);
24  }
25  
26 -static void
27 -pyg_object_class_init(GObjectClass *class, PyObject *py_class)
28 -{
29 -    class->set_property = pyg_object_set_property;
30 -    class->get_property = pyg_object_get_property;
31 -}
32 -
33  typedef struct _PyGSignalAccumulatorData {
34      PyObject *callable;
35      PyObject *user_data;
36 @@ -484,15 +477,14 @@ override_signal(GType instance_type, const gchar *signal_name)
37  }
38  
39  static PyObject *
40 -add_signals (GType instance_type, PyObject *signals)
41 +add_signals (GObjectClass *klass, PyObject *signals)
42  {
43      gboolean ret = TRUE;
44 -    GObjectClass *oclass;
45      Py_ssize_t pos = 0;
46      PyObject *key, *value, *overridden_signals = NULL;
47 +    GType instance_type = G_OBJECT_CLASS_TYPE (klass);
48  
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)
55         if (!ret)
56             break;
57      }
58 -    g_type_class_unref(oclass);
59      if (ret)
60          return overridden_signals;
61      else {
62 @@ -800,14 +791,12 @@ pyg_param_spec_from_object (PyObject *tuple)
63  }
64  
65  static gboolean
66 -add_properties (GType instance_type, PyObject *properties)
67 +add_properties (GObjectClass *klass, PyObject *properties)
68  {
69      gboolean ret = TRUE;
70 -    GObjectClass *oclass;
71      Py_ssize_t pos = 0;
72      PyObject *key, *value;
73  
74 -    oclass = g_type_class_ref(instance_type);
75      while (PyDict_Next(properties, &pos, &key, &value)) {
76         const gchar *prop_name;
77         GType prop_type;
78 @@ -873,7 +862,7 @@ add_properties (GType instance_type, PyObject *properties)
79         Py_DECREF(slice);
80  
81         if (pspec) {
82 -           g_object_class_install_property(oclass, 1, pspec);
83 +           g_object_class_install_property(klass, 1, pspec);
84         } else {
85              PyObject *type, *value, *traceback;
86             ret = FALSE;
87 @@ -883,7 +872,7 @@ add_properties (GType instance_type, PyObject *properties)
88                  g_snprintf(msg, 256,
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));
93                  Py_DECREF(value);
94                  value = PYGLIB_PyUnicode_FromString(msg);
95              }
96 @@ -892,11 +881,63 @@ add_properties (GType instance_type, PyObject *properties)
97         }
98      }
99  
100 -    g_type_class_unref(oclass);
101      return ret;
102  }
103  
104  static void
105 +pyg_object_class_init(GObjectClass *class, PyObject *py_class)
106 +{
107 +    PyObject *gproperties, *gsignals, *overridden_signals;
108 +    PyObject *class_dict = ((PyTypeObject*) py_class)->tp_dict;
109 +
110 +    class->set_property = pyg_object_set_property;
111 +    class->get_property = pyg_object_get_property;
112 +
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__");
117 +    if (gsignals) {
118 +       if (!PyDict_Check(gsignals)) {
119 +           PyErr_SetString(PyExc_TypeError,
120 +                           "__gsignals__ attribute not a dict!");
121 +           return;
122 +       }
123 +       if (!(overridden_signals = add_signals(class, gsignals))) {
124 +           return;
125 +       }
126 +        if (PyDict_SetItemString(class_dict, "__gsignals__",
127 +                                overridden_signals)) {
128 +            return;
129 +        }
130 +        Py_DECREF(overridden_signals);
131 +
132 +        PyDict_DelItemString(class_dict, "__gsignals__");
133 +    } else {
134 +       PyErr_Clear();
135 +    }
136 +
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__");
141 +    if (gproperties) {
142 +       if (!PyDict_Check(gproperties)) {
143 +           PyErr_SetString(PyExc_TypeError,
144 +                           "__gproperties__ attribute not a dict!");
145 +           return;
146 +       }
147 +       if (!add_properties(class, gproperties)) {
148 +           return;
149 +       }
150 +       PyDict_DelItemString(class_dict, "__gproperties__");
151 +       /* Borrowed reference. Py_DECREF(gproperties); */
152 +    } else {
153 +       PyErr_Clear();
154 +    }
155 +}
156 +
157 +static void
158  pyg_register_class_init(GType gtype, PyGClassInitFunc class_init)
159  {
160      GSList *list;
161 @@ -1068,7 +1109,7 @@ pygobject__g_instance_init(GTypeInstance   *instance,
162   */
163  static void
164  pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
165 -                        PyObject *bases, gboolean new_interfaces,
166 +                        PyObject *bases,
167                          GType *parent_interfaces, guint n_parent_interfaces)
168  {
169      int i;
170 @@ -1082,7 +1123,6 @@ pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
171          guint k;
172          PyObject *base = PyTuple_GET_ITEM(bases, i);
173          GType itype;
174 -        gboolean is_new = TRUE;
175          const GInterfaceInfo *iinfo;
176          GInterfaceInfo iinfo_copy;
177  
178 @@ -1099,16 +1139,6 @@ pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
179          if (!G_TYPE_IS_INTERFACE(itype))
180              continue;
181  
182 -        for (k = 0; k < n_parent_interfaces; ++k) {
183 -            if (parent_interfaces[k] == itype) {
184 -                is_new = FALSE;
185 -                break;
186 -            }
187 -        }
188 -
189 -        if ((new_interfaces && !is_new) || (!new_interfaces && is_new))
190 -            continue;
191 -
192          iinfo = pyg_lookup_interface_info(itype);
193          if (!iinfo) {
194              gchar *error;
195 @@ -1129,7 +1159,7 @@ pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
196  int
197  pyg_type_register(PyTypeObject *class, const char *type_name)
198  {
199 -    PyObject *gtype, *gsignals, *gproperties, *overridden_signals;
200 +    PyObject *gtype;
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)
205      }
206  
207      /*
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:
216 -     *
217 -     *    ../gobject:121: Warning: Object class
218 -     *    test_interface+MyObject doesn't implement property
219 -     *    'some-property' from interface 'TestInterface'
220 -     *
221 -     * If, on the other hand, you register interfaces after
222 -     * registering the properties, you get something like:
223 -     *
224 -     *     ../gobject:121: Warning: cannot add interface type
225 -     *    `TestInterface' to type `test_interface+MyUnknown', since
226 -     *    type `test_interface+MyUnknown' already conforms to
227 -     *    interface
228 -     *
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.
235       *
236       * See also comment above pyg_type_add_interfaces().
237       */
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);
241  
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__");
245 -    if (gsignals) {
246 -       if (!PyDict_Check(gsignals)) {
247 -           PyErr_SetString(PyExc_TypeError,
248 -                           "__gsignals__ attribute not a dict!");
249 -            g_free(parent_interfaces);
250 -           return -1;
251 -       }
252 -       if (!(overridden_signals = add_signals(instance_type, gsignals))) {
253 -            g_free(parent_interfaces);
254 -           return -1;
255 -       }
256 -        if (PyDict_SetItemString(class->tp_dict, "__gsignals__",
257 -                                overridden_signals)) {
258 -            g_free(parent_interfaces);
259 -            return -1;
260 -        }
261 -        Py_DECREF(overridden_signals);
262 -    } else {
263 -       PyErr_Clear();
264 -    }
265  
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__");
269 -    if (gproperties) {
270 -       if (!PyDict_Check(gproperties)) {
271 -           PyErr_SetString(PyExc_TypeError,
272 -                           "__gproperties__ attribute not a dict!");
273 -            g_free(parent_interfaces);
274 -           return -1;
275 -       }
276 -       if (!add_properties(instance_type, gproperties)) {
277 -            g_free(parent_interfaces);
278 -           return -1;
279 -       }
280 -       PyDict_DelItemString(class->tp_dict, "__gproperties__");
281 -       /* Borrowed reference. Py_DECREF(gproperties); */
282 -    } else {
283 -       PyErr_Clear();
284 +    gclass = g_type_class_ref(instance_type);
285 +    if (PyErr_Occurred() != NULL) {
286 +        g_type_class_unref(gclass);
287 +        g_free(parent_interfaces);
288 +        return -1;
289      }
290  
291 -    /* Register new interfaces, that are _not_ already defined by
292 -     * the parent type.  FIXME: See above.
293 -     */
294 -    pyg_type_add_interfaces(class, instance_type, class->tp_bases, TRUE,
295 -                            parent_interfaces, n_parent_interfaces);
296 -
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);
304  
305 -    if (gsignals)
306 -        PyDict_DelItemString(class->tp_dict, "__gsignals__");
307 -
308 +    if (PyErr_Occurred() != NULL)
309 +        return -1;
310      return 0;
311  }
312  
313 -- 
314 1.8.3.2
315