allow old pygtk applications to work with pygobject 2.28.x and glib 2.35.x
This commit is contained in:
parent
e48dcb2f1c
commit
ae1702ce23
311
pygobject-2.28.6-historyentry.patch
Normal file
311
pygobject-2.28.6-historyentry.patch
Normal file
@ -0,0 +1,311 @@
|
||||
From 9456ba70fdb98b3a4eb7ee2f630182387a54ca00 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Pitt <martinpitt@gnome.org>
|
||||
Date: Tue, 19 Feb 2013 14:39:56 +0000
|
||||
Subject: 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
|
||||
---
|
||||
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;
|
||||
}
|
||||
|
||||
--
|
||||
cgit v0.9.2
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
Name: pygobject2
|
||||
Version: 2.28.6
|
||||
Release: 10%{?dist}
|
||||
Release: 11%{?dist}
|
||||
License: LGPLv2+
|
||||
Group: Development/Languages
|
||||
Summary: Python 2 bindings for GObject
|
||||
@ -18,6 +18,7 @@ Source: http://ftp.gnome.org/pub/GNOME/sources/pygobject/2.28/pygobject-%{versio
|
||||
# using upstream patch (rhbz#790053)
|
||||
Patch1: fix-gio-flags.patch
|
||||
Patch2: 0001-Fix-set_qdata-warning-on-accessing-NULL-gobject-prop.patch
|
||||
Patch3: pygobject-2.28.6-historyentry.patch
|
||||
|
||||
### Build Dependencies ###
|
||||
|
||||
@ -65,6 +66,7 @@ This package contains documentation files for %{name}.
|
||||
%setup -q -n pygobject-%{version}
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%patch3 -p1
|
||||
|
||||
find -name '*.py' | xargs sed -i '1s|^#!python|#!%{__python}|'
|
||||
|
||||
@ -123,6 +125,9 @@ rm examples/Makefile*
|
||||
%{_datadir}/pygobject/xsl
|
||||
|
||||
%changelog
|
||||
* Thu Sep 19 2013 Tomáš Mráz <tmraz@redhat.com> - 2.28.6-11
|
||||
- allow old pygtk applications to work with pygobject 2.28.x and glib 2.35.x
|
||||
|
||||
* Sun Aug 04 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.28.6-10
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user