summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Dahlin <zilch@src.gnome.org>2004-04-10 22:03:46 +0000
committerJohan Dahlin <zilch@src.gnome.org>2004-04-10 22:03:46 +0000
commite886c978845ddffff0e39ca1cf33b31c467aab2c (patch)
tree9e220872a986645b3d30d8681984708875fea9ed
parent01eb05a5e5cd38b35814b3f9780ed48f2b95a769 (diff)
downloadpygobject-e886c978845ddffff0e39ca1cf33b31c467aab2c.tar.gz
pygobject-e886c978845ddffff0e39ca1cf33b31c467aab2c.tar.xz
pygobject-e886c978845ddffff0e39ca1cf33b31c467aab2c.zip
New function. (pygobject_lookup_class): Modify so we're not traversing
* pygobject.c (pygobject_new_with_interfaces): New function. (pygobject_lookup_class): Modify so we're not traversing parents for unknown types but instead creating new types when they're not registered. We're also using pygobject_new_with_interfaces so interfaces gets attached correctly. Partial fix for bug 129032 * gobjectmodule.c: Add quark and attach the PyTypeObject for GInterfaces. * pygobject-private.h: Make PyGInterface_Type and pyginterface_type_key public
-rw-r--r--gobject/gobjectmodule.c10
-rw-r--r--gobject/pygobject-private.h2
-rw-r--r--gobject/pygobject.c110
3 files changed, 107 insertions, 15 deletions
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index bea061e..5bf7242 100644
--- a/gobject/gobjectmodule.c
+++ b/gobject/gobjectmodule.c
@@ -27,6 +27,8 @@
#include "pygobject-private.h"
static PyObject *gerror_exc = NULL;
+static const gchar *pyginterface_type_id = "PyGInterface::type";
+GQuark pyginterface_type_key = 0;
static void pyg_flags_add_constants(PyObject *module, GType flags_type,
const gchar *strip_prefix);
@@ -234,7 +236,7 @@ pyg_interface_init(PyObject *self, PyObject *args, PyObject *kwargs)
return -1;
}
-static PyTypeObject PyGInterface_Type = {
+PyTypeObject PyGInterface_Type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"gobject.GInterface", /* tp_name */
@@ -300,6 +302,9 @@ pyg_register_interface(PyObject *dict, const gchar *class_name,
type->ob_type = &PyType_Type;
type->tp_base = &PyGInterface_Type;
+ if (!pyginterface_type_key)
+ pyginterface_type_key = g_quark_from_static_string(pyginterface_type_id);
+
if (PyType_Ready(type) < 0) {
g_warning("could not ready `%s'", type->tp_name);
return;
@@ -311,7 +316,10 @@ pyg_register_interface(PyObject *dict, const gchar *class_name,
Py_DECREF(o);
}
+ g_type_set_qdata(gtype, pyginterface_type_key, type);
+
PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type);
+
}
/* -------------- GMainContext objects ---------------------------- */
diff --git a/gobject/pygobject-private.h b/gobject/pygobject-private.h
index 42509e1..6de2d02 100644
--- a/gobject/pygobject-private.h
+++ b/gobject/pygobject-private.h
@@ -70,6 +70,8 @@ PyObject *pyg_object_descr_doc_get(void);
/* from pygobject.h */
extern PyTypeObject PyGObject_Type;
+extern PyTypeObject PyGInterface_Type;
+extern GQuark pyginterface_type_key;
void pygobject_register_class (PyObject *dict,
const gchar *type_name,
diff --git a/gobject/pygobject.c b/gobject/pygobject.c
index efa51b2..cf016fa 100644
--- a/gobject/pygobject.c
+++ b/gobject/pygobject.c
@@ -108,7 +108,7 @@ pygobject_register_class(PyObject *dict, const gchar *type_name,
s = strrchr(class_name, '.');
if (s != NULL)
class_name = s + 1;
-
+
type->ob_type = &PyType_Type;
if (bases) {
type->tp_bases = bases;
@@ -169,28 +169,110 @@ pygobject_register_wrapper(PyObject *self)
}
/**
+ * pygobject_new_with_interfaces
+ * @gtype: the GType of the GObject subclass.
+ *
+ * Creates a new PyTypeObject from the given GType with interfaces attached in
+ * bases. It will currently not filter out interfaces already implemented by
+ * it parents.
+ *
+ * Returns: a PyTypeObject for the new type of NULL if it couldn't be created
+ */
+PyTypeObject *
+pygobject_new_with_interfaces(GType gtype)
+{
+ PyObject *o;
+ PyTypeObject *type;
+ PyObject *dict;
+ PyTypeObject *py_parent_type, *py_interface_type;
+ GType *interfaces;
+ guint n_interfaces;
+ int i;
+ PyObject *bases;
+ GType parent_type, interface_type;
+
+ interfaces = g_type_interfaces (gtype, &n_interfaces);
+ bases = PyTuple_New(n_interfaces+1);
+
+ /* Lookup the parent type */
+ parent_type = g_type_parent(gtype);
+ py_parent_type = pygobject_lookup_class(parent_type);
+
+ /* We will always put the parent at the first position in bases */
+ PyTuple_SetItem(bases, 0, (PyObject*)py_parent_type);
+
+ /* And traverse interfaces */
+ if (n_interfaces) {
+ for (i = 0; i < n_interfaces; i++) {
+ interface_type = interfaces[i];
+ py_interface_type = pygobject_lookup_class(interface_type);
+ PyTuple_SetItem(bases, i+1, (PyObject*)py_interface_type);
+ }
+
+ g_free(interfaces);
+ }
+
+ dict = PyDict_New();
+
+ o = pyg_type_wrapper_new(gtype);
+ PyDict_SetItemString(dict, "__gtype__", o);
+ Py_DECREF(o);
+
+ /* set up __doc__ descriptor on type */
+ PyDict_SetItemString(dict, "__doc__", pyg_object_descr_doc_get());
+
+ type = (PyTypeObject*)PyObject_CallFunction((PyObject*)&PyType_Type,
+ "sOO", g_type_name(gtype), bases, dict);
+ if (type == NULL) {
+ PyErr_Print();
+ return NULL;
+ }
+
+ if (PyType_Ready(type) < 0) {
+ g_warning ("couldn't make the type `%s' ready", type->tp_name);
+ return NULL;
+ }
+
+ if (!pygobject_class_key)
+ pygobject_class_key = g_quark_from_static_string(pygobject_class_id);
+
+ /* stash a pointer to the python class with the GType */
+ Py_INCREF(type);
+ g_type_set_qdata(gtype, pygobject_class_key, type);
+
+ return type;
+}
+
+/**
* pygobject_lookup_class:
* @gtype: the GType of the GObject subclass.
*
* This function looks up the wrapper class used to represent
* instances of a GObject represented by @gtype. If no wrapper class
- * has been registered for the given GType, then the parent GType will
- * be checked. Since a wrapper has been registered for "GObject",
- * this function will always succeed.
+ * or interface has been registered for the given GType, then a new
+ * type will be created.
*
- * Returns: The wrapper class for the GObject.
+ * Returns: The wrapper class for the GObject or NULL if the
+ * GType has no registered type and a new type couldn't be created
*/
PyTypeObject *
pygobject_lookup_class(GType gtype)
{
- PyTypeObject *type = NULL;
+ PyTypeObject *py_type;
- /* find the python type for this object. If not found, use parent. */
- while (gtype != G_TYPE_INVALID &&
- (type = g_type_get_qdata(gtype, pygobject_class_key)) == NULL)
- gtype = g_type_parent(gtype);
- g_assert(type != NULL);
- return type;
+ if (gtype == G_TYPE_INTERFACE)
+ return &PyGInterface_Type;
+
+ py_type = g_type_get_qdata(gtype, pygobject_class_key);
+ if (py_type == NULL) {
+ py_type = g_type_get_qdata(gtype, pyginterface_type_key);
+ if (py_type == NULL) {
+ py_type = pygobject_new_with_interfaces(gtype);
+ g_type_set_qdata(gtype, pyginterface_type_key, py_type);
+ }
+ }
+
+ return py_type;
}
/**
@@ -210,13 +292,13 @@ pygobject_new(GObject *obj)
PyGObject *self;
if (!pygobject_wrapper_key)
- pygobject_wrapper_key=g_quark_from_static_string(pygobject_wrapper_id);
+ pygobject_wrapper_key = g_quark_from_static_string(pygobject_wrapper_id);
if (obj == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
-
+
/* we already have a wrapper for this object -- return it. */
self = (PyGObject *)g_object_get_qdata(obj, pygobject_wrapper_key);
if (self != NULL) {