summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo J. A. M. Carneiro <gjc@src.gnome.org>2006-08-26 17:06:25 +0000
committerGustavo J. A. M. Carneiro <gjc@src.gnome.org>2006-08-26 17:06:25 +0000
commit6c0b030393f51f1ca65708cc6620e0f2456b8779 (patch)
tree57a2babba9869673e98e5a3ec64d652d6847848c
parent01561230b271ddd16fb650b53e2ed6cc40e99d35 (diff)
downloadpygobject-6c0b030393f51f1ca65708cc6620e0f2456b8779.tar.gz
pygobject-6c0b030393f51f1ca65708cc6620e0f2456b8779.tar.xz
pygobject-6c0b030393f51f1ca65708cc6620e0f2456b8779.zip
type registration fix
-rw-r--r--ChangeLog10
-rw-r--r--gobject/gobjectmodule.c76
2 files changed, 84 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index d05bbf1..d632195 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2006-08-26 Gustavo J. A. M. Carneiro <gjc@gnome.org>
+
+ * gobject/gobjectmodule.c (pyg_type_register): Fix type
+ registration once more to account for all corner cases. This time
+ we register interfaces in two stages: first, before properties and
+ signals are registered, we register the interfaces that are
+ already implemented in the parent type and are being overridden;
+ second, after registration of properties and signals, we register
+ the remaining interfaces.
+
2006-08-21 Johan Dahlin <jdahlin@async.com.br>
* docs/Makefile.am (EXTRA_DIST): Remove build_stamp, include generated .html
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index 8374c44..dabff01 100644
--- a/gobject/gobjectmodule.c
+++ b/gobject/gobjectmodule.c
@@ -1200,6 +1200,8 @@ pyg_type_register(PyTypeObject *class, const char *type_name)
{
PyObject *gtype, *gsignals, *gproperties, *overridden_signals;
GType parent_type, instance_type;
+ GType *parent_interfaces;
+ guint n_parent_interfaces;
gint i;
GTypeQuery query;
gpointer gclass;
@@ -1226,6 +1228,8 @@ pyg_type_register(PyTypeObject *class, const char *type_name)
return -1;
}
+ parent_interfaces = g_type_interfaces(parent_type, &n_parent_interfaces);
+
if (type_name)
/* care is taken below not to free this */
new_type_name = (gchar *) type_name;
@@ -1274,7 +1278,8 @@ pyg_type_register(PyTypeObject *class, const char *type_name)
pyg_object_descr_doc_get());
}
- /* Register interface implementations */
+ /* Register interfaces that are already defined by the parent
+ * type and are going to be reimplemented */
if (class->tp_bases) {
for (i = 0; i < PyTuple_GET_SIZE(class->tp_bases); ++i)
{
@@ -1283,11 +1288,25 @@ pyg_type_register(PyTypeObject *class, const char *type_name)
GType itype;
const GInterfaceInfo *iinfo;
GInterfaceInfo iinfo_copy;
+ guint parent_interface_iter;
if (((PyTypeObject *) base)->tp_base != &PyGInterface_Type)
continue;
itype = pyg_type_from_object((PyObject *) base);
+ /* ignore interface unless defined in parent type */
+ if (n_parent_interfaces == 0)
+ continue;
+ for (parent_interface_iter = 0;
+ parent_interface_iter < n_parent_interfaces;
+ ++parent_interface_iter)
+ {
+ if (parent_interfaces[parent_interface_iter] == itype)
+ break;
+ }
+ if (parent_interface_iter != n_parent_interfaces)
+ continue;
+
iinfo = pyg_lookup_interface_info(itype);
iinfo_copy = *iinfo;
iinfo_copy.interface_data = class;
@@ -1312,14 +1331,18 @@ pyg_type_register(PyTypeObject *class, const char *type_name)
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))
+ overridden_signals)) {
+ g_free(parent_interfaces);
return -1;
+ }
Py_DECREF(overridden_signals);
} else {
PyErr_Clear();
@@ -1332,9 +1355,11 @@ pyg_type_register(PyTypeObject *class, const char *type_name)
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__");
@@ -1343,12 +1368,59 @@ pyg_type_register(PyTypeObject *class, const char *type_name)
PyErr_Clear();
}
+ /* Register new interfaces, that are _not_ already defined by
+ * the parent type */
+ if (class->tp_bases) {
+ for (i = 0; i < PyTuple_GET_SIZE(class->tp_bases); ++i)
+ {
+ PyTypeObject *base =
+ (PyTypeObject *) PyTuple_GET_ITEM(class->tp_bases, i);
+ GType itype;
+ const GInterfaceInfo *iinfo;
+ GInterfaceInfo iinfo_copy;
+ guint parent_interface_iter;
+
+ if (((PyTypeObject *) base)->tp_base != &PyGInterface_Type)
+ continue;
+
+ itype = pyg_type_from_object((PyObject *) base);
+
+ /* ignore interface if already defined in parent type */
+ if (n_parent_interfaces != 0) {
+ for (parent_interface_iter = 0;
+ parent_interface_iter < n_parent_interfaces;
+ ++parent_interface_iter)
+ {
+ if (parent_interfaces[parent_interface_iter] == itype)
+ continue;
+ }
+ }
+
+ iinfo = pyg_lookup_interface_info(itype);
+ iinfo_copy = *iinfo;
+ iinfo_copy.interface_data = class;
+ if (!iinfo) {
+ char *msg;
+ msg = g_strdup_printf("Interface type %s "
+ "has no python implementation support",
+ base->tp_name);
+ PyErr_Warn(PyExc_RuntimeWarning, msg);
+ g_free(msg);
+ continue;
+ }
+ g_type_add_interface_static(instance_type, itype, &iinfo_copy);
+ }
+ } else
+ g_warning("type has no tp_bases");
+
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);
return -1;
}
g_type_class_unref(gclass);
+ g_free(parent_interfaces);
if (gsignals)
PyDict_DelItemString(class->tp_dict, "__gsignals__");