summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Dahlin <johan@src.gnome.org>2006-07-13 17:26:56 +0000
committerJohan Dahlin <johan@src.gnome.org>2006-07-13 17:26:56 +0000
commite26921db6615d6ab766ecb10049af254e43eeaa3 (patch)
tree65cf78bda92ddf9f68f243bea929853f24bf873f
parentf80b6b9f96a027d926c9ee3d31f0ca8eb05272bf (diff)
downloadpygobject-e26921db6615d6ab766ecb10049af254e43eeaa3.tar.gz
pygobject-e26921db6615d6ab766ecb10049af254e43eeaa3.tar.xz
pygobject-e26921db6615d6ab766ecb10049af254e43eeaa3.zip
Add infrastructure for lazy type registration, fixes #
* gobject/gobjectmodule.c: (pyg_type_from_name), (get_type_name_for_class): * gobject/pygobject-private.h: * gobject/pygobject.c: (pygobject_new_with_interfaces), (pygobject_lookup_class), (pygobject_emit): * gobject/pygobject.h: * gobject/pygtype.c: (_wrap_g_type_from_name), (pyg_type_from_object), (pyg_type_register_custom_callback), (pyg_type_get_custom), (_pyg_type_from_name): Add infrastructure for lazy type registration, fixes #
-rw-r--r--ChangeLog14
-rw-r--r--gobject/gobjectmodule.c8
-rw-r--r--gobject/pygobject-private.h7
-rw-r--r--gobject/pygobject.c11
-rw-r--r--gobject/pygobject.h8
-rw-r--r--gobject/pygtype.c79
6 files changed, 116 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 6f6b23f..4b65f88 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2006-07-13 Johan Dahlin <jdahlin@async.com.br>
+
+ reviewed by: <delete if not using a buddy>
+
+ * gobject/gobjectmodule.c: (pyg_type_from_name),
+ (get_type_name_for_class):
+ * gobject/pygobject-private.h:
+ * gobject/pygobject.c: (pygobject_new_with_interfaces),
+ (pygobject_lookup_class), (pygobject_emit):
+ * gobject/pygobject.h:
+ * gobject/pygtype.c: (_wrap_g_type_from_name),
+ (pyg_type_from_object), (pyg_type_register_custom_callback),
+ (pyg_type_get_custom), (_pyg_type_from_name):
+
2006-07-13 Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
* m4/python.m4: Properly quote AM_CHECK_PYMOD definition.
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index d4909a9..0004f43 100644
--- a/gobject/gobjectmodule.c
+++ b/gobject/gobjectmodule.c
@@ -277,7 +277,7 @@ pyg_type_from_name (PyObject *self, PyObject *args)
#endif
if (!PyArg_ParseTuple(args, "s:gobject.type_from_name", &name))
return NULL;
- type = g_type_from_name(name);
+ type = _pyg_type_from_name(name);
if (type != 0)
return pyg_type_wrapper_new(type);
PyErr_Format(PyExc_RuntimeError, "%s: unknown type name: %s",
@@ -1136,7 +1136,7 @@ get_type_name_for_class(PyTypeObject *class)
for (i = 0; type_name[i] != '\0'; i++)
if (type_name[i] == '.')
type_name[i] = '+';
- if (g_type_from_name(type_name) == 0)
+ if (_pyg_type_from_name(type_name) == 0)
break; /* we now have a unique name */
++name_serial;
}
@@ -3241,7 +3241,9 @@ struct _PyGObject_Functions pygobject_api_functions = {
pyg_set_object_has_new_constructor,
add_warning_redirection,
- disable_warning_redirections
+ disable_warning_redirections,
+
+ pyg_type_register_custom_callback
};
#define REGISTER_TYPE(d, type, name) \
diff --git a/gobject/pygobject-private.h b/gobject/pygobject-private.h
index 2b6ac73..9553600 100644
--- a/gobject/pygobject-private.h
+++ b/gobject/pygobject-private.h
@@ -253,4 +253,11 @@ PyObject * pyg_option_context_new (GOptionContext * context);
PyObject * pyg_option_group_new (GOptionGroup * group);
GOptionGroup *pyg_option_group_transfer_group(PyGOptionGroup *self);
+extern GHashTable *custom_type_registration;
+void pyg_type_register_custom_callback(const gchar *typename,
+ PyGTypeRegistrationFunction callback,
+ gpointer data);
+PyTypeObject * pyg_type_get_custom(const gchar *name);
+GType _pyg_type_from_name(const gchar *name);
+
#endif
diff --git a/gobject/pygobject.c b/gobject/pygobject.c
index 1451148..5660296 100644
--- a/gobject/pygobject.c
+++ b/gobject/pygobject.c
@@ -34,6 +34,8 @@ typedef struct {
} SinkFunc;
static GArray *sink_funcs = NULL;
+GHashTable *custom_type_registration = NULL;
+
PyTypeObject *PyGObject_MetaType = NULL;
/**
@@ -636,7 +638,7 @@ pygobject_new_with_interfaces(GType gtype)
PyDict_SetItemString(dict, "__doc__", pyg_object_descr_doc_get());
/* generate the pygtk module name and extract the base type name */
- gtype_name = (gchar *)g_type_name(gtype);
+ gtype_name = (gchar*)g_type_name(gtype);
if (g_str_has_prefix(gtype_name, "Gtk")) {
mod_name = "gtk";
gtype_name += 3;
@@ -725,6 +727,10 @@ pygobject_lookup_class(GType gtype)
if (gtype == G_TYPE_INTERFACE)
return &PyGInterface_Type;
+
+ py_type = pyg_type_get_custom(g_type_name(gtype));
+ if (py_type)
+ return py_type;
py_type = g_type_get_qdata(gtype, pygobject_class_key);
if (py_type == NULL) {
@@ -1513,7 +1519,8 @@ pygobject_emit(PyGObject *self, PyObject *args)
g_free(params);
return NULL;
}
- }
+ }
+
if (query.return_type != G_TYPE_NONE)
g_value_init(&ret, query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
diff --git a/gobject/pygobject.h b/gobject/pygobject.h
index 8eeb818..3e928c7 100644
--- a/gobject/pygobject.h
+++ b/gobject/pygobject.h
@@ -65,6 +65,8 @@ typedef struct {
#define PyGParamSpec_Check(v) (PyObject_TypeCheck(v, &PyGParamSpec_Type))
typedef int (*PyGClassInitFunc) (gpointer gclass, PyTypeObject *pyclass);
+typedef PyTypeObject * (*PyGTypeRegistrationFunction) (const gchar *name,
+ gpointer data);
struct _PyGObject_Functions {
/*
@@ -176,6 +178,10 @@ struct _PyGObject_Functions {
void (*add_warning_redirection) (const char *domain,
PyObject *warning);
void (*disable_warning_redirections) (void);
+ void (*type_register_custom)(const gchar *typename,
+ PyGTypeRegistrationFunction callback,
+ gpointer data);
+
};
#ifndef _INSIDE_PYGOBJECT_
@@ -237,7 +243,7 @@ struct _PyGObject_Functions *_PyGObject_API;
#define pyg_set_object_has_new_constructor (_PyGObject_API->set_object_has_new_constructor)
#define pyg_add_warning_redirection (_PyGObject_API->add_warning_redirection)
#define pyg_disable_warning_redirections (_PyGObject_API->disable_warning_redirections)
-
+#define pyg_type_register_custom_callback (_PyGObject_API->type_register_custom)
#define pyg_block_threads() G_STMT_START { \
if (_PyGObject_API->block_threads != NULL) \
diff --git a/gobject/pygtype.c b/gobject/pygtype.c
index 3315b29..efbabb7 100644
--- a/gobject/pygtype.c
+++ b/gobject/pygtype.c
@@ -206,7 +206,7 @@ _wrap_g_type_from_name(PyGTypeWrapper *_, PyObject *args)
if (!PyArg_ParseTuple(args, "s:GType.from_name", &type_name))
return NULL;
- type = g_type_from_name(type_name);
+ type = _pyg_type_from_name(type_name);
if (type == 0) {
PyErr_SetString(PyExc_RuntimeError, "unknown type name");
return NULL;
@@ -373,14 +373,17 @@ pyg_type_from_object(PyObject *obj)
/* handle strings */
if (PyString_Check(obj)) {
- type = g_type_from_name(PyString_AsString(obj));
- if (type == 0)
- PyErr_SetString(PyExc_TypeError, "could not find named typecode");
- return type;
+ gchar *name = PyString_AsString(obj);
+
+ type = _pyg_type_from_name(name);
+ if (type != 0) {
+ return type;
+ }
}
/* finally, look for a __gtype__ attribute on the object */
gtype = PyObject_GetAttrString(obj, "__gtype__");
+
if (gtype) {
if (gtype->ob_type == &PyGTypeWrapper_Type) {
type = ((PyGTypeWrapper *)gtype)->type;
@@ -1637,3 +1640,69 @@ pyg_param_gvalue_as_pyobject(const GValue* gvalue,
return pyg_value_as_pyobject(gvalue, copy_boxed);
}
}
+
+/**
+ * pyg_type_registration_callback
+ * @gtypename: type name
+ * @callback: function to run
+ *
+ */
+typedef struct {
+ PyGTypeRegistrationFunction callback;
+ gpointer data;
+} CustomTypeData;
+
+void
+pyg_type_register_custom_callback(const gchar *typename,
+ PyGTypeRegistrationFunction callback,
+ gpointer user_data)
+{
+ CustomTypeData *data;
+
+ if (!custom_type_registration)
+ custom_type_registration = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_free);
+
+ data = g_new (CustomTypeData, 1);
+ data->callback = callback;
+ data->data = user_data;
+
+ g_hash_table_insert(custom_type_registration,
+ g_strdup(typename),
+ data);
+}
+
+PyTypeObject *
+pyg_type_get_custom(const gchar *name)
+{
+ CustomTypeData *data;
+ PyTypeObject *retval;
+
+ if (!custom_type_registration)
+ return NULL;
+
+ data = g_hash_table_lookup(custom_type_registration, name);
+ if (!data)
+ return NULL;
+
+ retval = data->callback(name, data->data);
+
+ g_hash_table_remove(custom_type_registration, name);
+
+ return retval;
+}
+
+GType
+_pyg_type_from_name(const gchar *name)
+{
+ GType type;
+
+ type = g_type_from_name(name);
+ if (type == G_TYPE_INVALID) {
+ pyg_type_get_custom(name);
+ type = g_type_from_name(name);
+ }
+
+ return type;
+}
+