diff options
-rw-r--r-- | gobject/gobjectmodule.c | 86 | ||||
-rw-r--r-- | gobject/pygobject-private.h | 3 | ||||
-rw-r--r-- | gobject/pygobject.c | 35 | ||||
-rw-r--r-- | tests/test_gtype.py | 9 |
4 files changed, 87 insertions, 46 deletions
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index d0701ce4..e24313ee 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -946,7 +946,7 @@ _wrap_pyg_type_register(PyObject *self, PyObject *args) if (gtype == NULL) { PyErr_Clear(); /* not registered */ - if (pyg_type_register(class)) + if (pyg_type_register(class, NULL)) return NULL; } else /* already registered */ @@ -956,13 +956,54 @@ _wrap_pyg_type_register(PyObject *self, PyObject *args) return (PyObject *) class; } +static char * +get_type_name_for_class(PyTypeObject *class) +{ + gint i, name_serial; + char name_serial_str[16]; + PyObject *module; + char *type_name = NULL; + + /* make name for new GType */ + name_serial = 1; + /* give up after 1000 tries, just in case.. */ + while (name_serial < 1000) + { + snprintf(name_serial_str, 16, "-v%i", name_serial); + module = PyObject_GetAttrString((PyObject *)class, "__module__"); + if (module && PyString_Check(module)) { + type_name = g_strconcat(PyString_AsString(module), ".", + class->tp_name, + name_serial > 1 ? name_serial_str : NULL, + NULL); + Py_DECREF(module); + } else { + if (module) + Py_DECREF(module); + else + PyErr_Clear(); + type_name = g_strconcat(class->tp_name, + name_serial > 1 ? name_serial_str : NULL, + NULL); + } + /* convert '.' in type name to '+', which isn't banned (grumble) */ + for (i = 0; type_name[i] != '\0'; i++) + if (type_name[i] == '.') + type_name[i] = '+'; + if (g_type_from_name(type_name) == 0) + break; /* we now have a unique name */ + ++name_serial; + } + + return type_name; +} + int -pyg_type_register(PyTypeObject *class) +pyg_type_register(PyTypeObject *class, char *type_name) { - PyObject *gtype, *module, *gsignals, *gproperties, *overridden_signals; + PyObject *gtype, *gsignals, *gproperties, *overridden_signals; GType parent_type, instance_type; - gchar *type_name = NULL; - gint i, name_serial; + gint i; GTypeQuery query; gpointer gclass; GTypeInfo type_info = { @@ -987,38 +1028,9 @@ pyg_type_register(PyTypeObject *class) return -1; } - /* make name for new GType */ - name_serial = 1; - while (name_serial < 1000) /* give up after 1000 tries, just in case.. */ - { - char name_serial_str[16]; - - snprintf(name_serial_str, 16, "-v%i", name_serial); - module = PyObject_GetAttrString((PyObject *)class, "__module__"); - if (module && PyString_Check(module)) { - type_name = g_strconcat(PyString_AsString(module), ".", - class->tp_name, - name_serial > 1? name_serial_str : NULL, - NULL); - Py_DECREF(module); - } else { - if (module) - Py_DECREF(module); - else - PyErr_Clear(); - type_name = g_strconcat(class->tp_name, - name_serial > 1? name_serial_str : NULL, - NULL); - } - /* convert '.' in type name to '+', which isn't banned (grumble) */ - for (i = 0; type_name[i] != '\0'; i++) - if (type_name[i] == '.') - type_name[i] = '+'; - if (g_type_from_name(type_name) == 0) - break; /* we now have a unique name */ - ++name_serial; - } - + if (!type_name) + type_name = get_type_name_for_class(class); + /* set class_data that will be passed to the class_init function. */ type_info.class_data = class; diff --git a/gobject/pygobject-private.h b/gobject/pygobject-private.h index fb6f4192..50264ff0 100644 --- a/gobject/pygobject-private.h +++ b/gobject/pygobject-private.h @@ -104,7 +104,8 @@ PyTypeObject *pygobject_lookup_class (GType gtype); void pygobject_watch_closure (PyObject *self, GClosure *closure); void pygobject_register_sinkfunc(GType type, void (* sinkfunc)(GObject *object)); -int pyg_type_register (PyTypeObject *class); +int pyg_type_register (PyTypeObject *class, + char *typename); /* from pygboxed.c */ extern PyTypeObject PyGBoxed_Type; diff --git a/gobject/pygobject.c b/gobject/pygobject.c index 2c7913d9..2b2b2c4b 100644 --- a/gobject/pygobject.c +++ b/gobject/pygobject.c @@ -1244,21 +1244,42 @@ PyTypeObject PyGObject_Type = { }; +static int +pygobjectmeta_register(PyTypeObject *subtype, PyObject *instance_dict) +{ + PyObject *pytype_name; + char *type_name = NULL; + int retval = 0; + + if (!instance_dict) { + PyErr_Clear(); + goto out; + } + + /* If it's already registered, skip registration */ + if (PyDict_GetItemString(instance_dict, "__gtype__")) + goto out; + + pytype_name = PyDict_GetItemString(instance_dict, "__gtype_name__"); + if (pytype_name) + type_name = g_strdup(PyString_AsString(pytype_name)); + retval = pyg_type_register(subtype, type_name); - /* -------- GObject MetaClass -----------*/ +out: + return retval; +} + +/* -------- GObject MetaClass -----------*/ static int pygobjectmeta_init(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) { PyObject *instance_dict; + if (PyType_Type.tp_init((PyObject *) subtype, args, kwargs)) return -1; + instance_dict = PyTuple_GetItem(args, 2); - if (instance_dict) { - if (PyDict_GetItemString(instance_dict, "__gtype__") == NULL) - return pyg_type_register(subtype); - } else - PyErr_Clear(); - return 0; + return pygobjectmeta_register(subtype, instance_dict); } diff --git a/tests/test_gtype.py b/tests/test_gtype.py index a891ba2c..bdaa2d16 100644 --- a/tests/test_gtype.py +++ b/tests/test_gtype.py @@ -55,6 +55,13 @@ class GTypeTest(unittest.TestCase): self.checkType(gobject.TYPE_OBJECT, 'PyObject') # XXX: Flags, Enums - + +class MyObject(gobject.GObject): + __gtype_name__ = 'MyObject' + +class TypeNameTest(unittest.TestCase): + def testTypeName(self): + self.assertEqual(gobject.type_name(MyObject), 'MyObject') + if __name__ == '__main__': unittest.main() |