]> git.draconx.ca Git - gentoo-fixes.git/blobdiff - 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
diff --git a/dev-python/pygobject/files/pygobject-2.28.6-glib-2.36-class_init.patch b/dev-python/pygobject/files/pygobject-2.28.6-glib-2.36-class_init.patch
new file mode 100644 (file)
index 0000000..b2f9b14
--- /dev/null
@@ -0,0 +1,315 @@
+From 9456ba70fdb98b3a4eb7ee2f630182387a54ca00 Mon Sep 17 00:00:00 2001
+From: Martin Pitt <martinpitt@gnome.org>
+Date: Tue, 19 Feb 2013 15:39:56 +0100
+Subject: [PATCH] Move property and signal creation into _class_init()
+
+We must not add class interfaces after g_type_class_ref() has been called the
+first time. Move signal and property creation from pyg_type_register() into
+pyg_object_class_init(), and drop the hack of registering interfaces twice.
+
+This is a backport of commit efcb0f9fd for 2.28.x. This allows old pygtk
+applications to work with pygobject 2.28.x and glib 2.35.x.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=694108
+---
+ gobject/gobjectmodule.c | 177 +++++++++++++++++++-----------------------------
+ 1 file changed, 70 insertions(+), 107 deletions(-)
+
+diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
+index 2a84606..91f7315 100644
+--- a/gobject/gobjectmodule.c
++++ b/gobject/gobjectmodule.c
+@@ -312,13 +312,6 @@ pyg_object_get_property (GObject *object, guint property_id,
+     pyglib_gil_state_release(state);
+ }
+-static void
+-pyg_object_class_init(GObjectClass *class, PyObject *py_class)
+-{
+-    class->set_property = pyg_object_set_property;
+-    class->get_property = pyg_object_get_property;
+-}
+-
+ typedef struct _PyGSignalAccumulatorData {
+     PyObject *callable;
+     PyObject *user_data;
+@@ -484,15 +477,14 @@ override_signal(GType instance_type, const gchar *signal_name)
+ }
+ static PyObject *
+-add_signals (GType instance_type, PyObject *signals)
++add_signals (GObjectClass *klass, PyObject *signals)
+ {
+     gboolean ret = TRUE;
+-    GObjectClass *oclass;
+     Py_ssize_t pos = 0;
+     PyObject *key, *value, *overridden_signals = NULL;
++    GType instance_type = G_OBJECT_CLASS_TYPE (klass);
+     overridden_signals = PyDict_New();
+-    oclass = g_type_class_ref(instance_type);
+     while (PyDict_Next(signals, &pos, &key, &value)) {
+       const gchar *signal_name;
+         gchar *signal_name_canon, *c;
+@@ -530,7 +522,6 @@ add_signals (GType instance_type, PyObject *signals)
+       if (!ret)
+           break;
+     }
+-    g_type_class_unref(oclass);
+     if (ret)
+         return overridden_signals;
+     else {
+@@ -800,14 +791,12 @@ pyg_param_spec_from_object (PyObject *tuple)
+ }
+ static gboolean
+-add_properties (GType instance_type, PyObject *properties)
++add_properties (GObjectClass *klass, PyObject *properties)
+ {
+     gboolean ret = TRUE;
+-    GObjectClass *oclass;
+     Py_ssize_t pos = 0;
+     PyObject *key, *value;
+-    oclass = g_type_class_ref(instance_type);
+     while (PyDict_Next(properties, &pos, &key, &value)) {
+       const gchar *prop_name;
+       GType prop_type;
+@@ -873,7 +862,7 @@ add_properties (GType instance_type, PyObject *properties)
+       Py_DECREF(slice);
+       if (pspec) {
+-          g_object_class_install_property(oclass, 1, pspec);
++          g_object_class_install_property(klass, 1, pspec);
+       } else {
+             PyObject *type, *value, *traceback;
+           ret = FALSE;
+@@ -883,7 +872,7 @@ add_properties (GType instance_type, PyObject *properties)
+                 g_snprintf(msg, 256,
+                          "%s (while registering property '%s' for GType '%s')",
+                PYGLIB_PyUnicode_AsString(value),
+-                         prop_name, g_type_name(instance_type));
++                         prop_name, G_OBJECT_CLASS_NAME(klass));
+                 Py_DECREF(value);
+                 value = PYGLIB_PyUnicode_FromString(msg);
+             }
+@@ -892,11 +881,63 @@ add_properties (GType instance_type, PyObject *properties)
+       }
+     }
+-    g_type_class_unref(oclass);
+     return ret;
+ }
+ static void
++pyg_object_class_init(GObjectClass *class, PyObject *py_class)
++{
++    PyObject *gproperties, *gsignals, *overridden_signals;
++    PyObject *class_dict = ((PyTypeObject*) py_class)->tp_dict;
++
++    class->set_property = pyg_object_set_property;
++    class->get_property = pyg_object_get_property;
++
++    /* install signals */
++    /* we look this up in the instance dictionary, so we don't
++     * accidentally get a parent type's __gsignals__ attribute. */
++    gsignals = PyDict_GetItemString(class_dict, "__gsignals__");
++    if (gsignals) {
++      if (!PyDict_Check(gsignals)) {
++          PyErr_SetString(PyExc_TypeError,
++                          "__gsignals__ attribute not a dict!");
++          return;
++      }
++      if (!(overridden_signals = add_signals(class, gsignals))) {
++          return;
++      }
++        if (PyDict_SetItemString(class_dict, "__gsignals__",
++                               overridden_signals)) {
++            return;
++        }
++        Py_DECREF(overridden_signals);
++
++        PyDict_DelItemString(class_dict, "__gsignals__");
++    } else {
++      PyErr_Clear();
++    }
++
++    /* install properties */
++    /* we look this up in the instance dictionary, so we don't
++     * accidentally get a parent type's __gproperties__ attribute. */
++    gproperties = PyDict_GetItemString(class_dict, "__gproperties__");
++    if (gproperties) {
++      if (!PyDict_Check(gproperties)) {
++          PyErr_SetString(PyExc_TypeError,
++                          "__gproperties__ attribute not a dict!");
++          return;
++      }
++      if (!add_properties(class, gproperties)) {
++          return;
++      }
++      PyDict_DelItemString(class_dict, "__gproperties__");
++      /* Borrowed reference. Py_DECREF(gproperties); */
++    } else {
++      PyErr_Clear();
++    }
++}
++
++static void
+ pyg_register_class_init(GType gtype, PyGClassInitFunc class_init)
+ {
+     GSList *list;
+@@ -1068,7 +1109,7 @@ pygobject__g_instance_init(GTypeInstance   *instance,
+  */
+ static void
+ pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
+-                        PyObject *bases, gboolean new_interfaces,
++                        PyObject *bases,
+                         GType *parent_interfaces, guint n_parent_interfaces)
+ {
+     int i;
+@@ -1082,7 +1123,6 @@ pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
+         guint k;
+         PyObject *base = PyTuple_GET_ITEM(bases, i);
+         GType itype;
+-        gboolean is_new = TRUE;
+         const GInterfaceInfo *iinfo;
+         GInterfaceInfo iinfo_copy;
+@@ -1099,16 +1139,6 @@ pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
+         if (!G_TYPE_IS_INTERFACE(itype))
+             continue;
+-        for (k = 0; k < n_parent_interfaces; ++k) {
+-            if (parent_interfaces[k] == itype) {
+-                is_new = FALSE;
+-                break;
+-            }
+-        }
+-
+-        if ((new_interfaces && !is_new) || (!new_interfaces && is_new))
+-            continue;
+-
+         iinfo = pyg_lookup_interface_info(itype);
+         if (!iinfo) {
+             gchar *error;
+@@ -1129,7 +1159,7 @@ pyg_type_add_interfaces(PyTypeObject *class, GType instance_type,
+ int
+ pyg_type_register(PyTypeObject *class, const char *type_name)
+ {
+-    PyObject *gtype, *gsignals, *gproperties, *overridden_signals;
++    PyObject *gtype;
+     GType parent_type, instance_type;
+     GType *parent_interfaces;
+     guint n_parent_interfaces;
+@@ -1216,88 +1246,22 @@ pyg_type_register(PyTypeObject *class, const char *type_name)
+     }
+     /*
+-     * Note: Interfaces to be implemented are searched twice.  First
+-     * we register interfaces that are already implemented by a parent
+-     * type.  The second time, the remaining interfaces are
+-     * registered, i.e. the ones that are not implemented by a parent
+-     * type.  In between these two loops, properties and signals are
+-     * registered.  It has to be done this way, in two steps,
+-     * otherwise glib will complain.  If registering all interfaces
+-     * always before properties, you get an error like:
+-     *
+-     *    ../gobject:121: Warning: Object class
+-     *    test_interface+MyObject doesn't implement property
+-     *    'some-property' from interface 'TestInterface'
+-     *
+-     * If, on the other hand, you register interfaces after
+-     * registering the properties, you get something like:
+-     *
+-     *     ../gobject:121: Warning: cannot add interface type
+-     *    `TestInterface' to type `test_interface+MyUnknown', since
+-     *    type `test_interface+MyUnknown' already conforms to
+-     *    interface
+-     *
+-     * This looks like a GLib quirk, but no bug has been filed
+-     * upstream.  However we have a unit test for this particular
+-     * problem, which can be found in test_interfaces.py, class
+-     * TestInterfaceImpl.
++     * Note, all interfaces need to be registered before the first
++     * g_type_class_ref(), see bug #686149.
+      *
+      * See also comment above pyg_type_add_interfaces().
+      */
+-    pyg_type_add_interfaces(class, instance_type, class->tp_bases, FALSE,
++    pyg_type_add_interfaces(class, instance_type, class->tp_bases,
+                             parent_interfaces, n_parent_interfaces);
+-    /* we look this up in the instance dictionary, so we don't
+-     * accidentally get a parent type's __gsignals__ attribute. */
+-    gsignals = PyDict_GetItemString(class->tp_dict, "__gsignals__");
+-    if (gsignals) {
+-      if (!PyDict_Check(gsignals)) {
+-          PyErr_SetString(PyExc_TypeError,
+-                          "__gsignals__ attribute not a dict!");
+-            g_free(parent_interfaces);
+-          return -1;
+-      }
+-      if (!(overridden_signals = add_signals(instance_type, gsignals))) {
+-            g_free(parent_interfaces);
+-          return -1;
+-      }
+-        if (PyDict_SetItemString(class->tp_dict, "__gsignals__",
+-                               overridden_signals)) {
+-            g_free(parent_interfaces);
+-            return -1;
+-        }
+-        Py_DECREF(overridden_signals);
+-    } else {
+-      PyErr_Clear();
+-    }
+-    /* we look this up in the instance dictionary, so we don't
+-     * accidentally get a parent type's __gsignals__ attribute. */
+-    gproperties = PyDict_GetItemString(class->tp_dict, "__gproperties__");
+-    if (gproperties) {
+-      if (!PyDict_Check(gproperties)) {
+-          PyErr_SetString(PyExc_TypeError,
+-                          "__gproperties__ attribute not a dict!");
+-            g_free(parent_interfaces);
+-          return -1;
+-      }
+-      if (!add_properties(instance_type, gproperties)) {
+-            g_free(parent_interfaces);
+-          return -1;
+-      }
+-      PyDict_DelItemString(class->tp_dict, "__gproperties__");
+-      /* Borrowed reference. Py_DECREF(gproperties); */
+-    } else {
+-      PyErr_Clear();
++    gclass = g_type_class_ref(instance_type);
++    if (PyErr_Occurred() != NULL) {
++        g_type_class_unref(gclass);
++        g_free(parent_interfaces);
++        return -1;
+     }
+-    /* Register new interfaces, that are _not_ already defined by
+-     * the parent type.  FIXME: See above.
+-     */
+-    pyg_type_add_interfaces(class, instance_type, class->tp_bases, TRUE,
+-                            parent_interfaces, n_parent_interfaces);
+-
+-    gclass = g_type_class_ref(instance_type);
+     if (pyg_run_class_init(instance_type, gclass, class)) {
+         g_type_class_unref(gclass);
+         g_free(parent_interfaces);
+@@ -1306,9 +1270,8 @@ pyg_type_register(PyTypeObject *class, const char *type_name)
+     g_type_class_unref(gclass);
+     g_free(parent_interfaces);
+-    if (gsignals)
+-        PyDict_DelItemString(class->tp_dict, "__gsignals__");
+-
++    if (PyErr_Occurred() != NULL)
++        return -1;
+     return 0;
+ }
+-- 
+1.8.3.2
+