pygobject r940 - in trunk: . gio gobject



Author: paulp
Date: Mon Aug 11 20:15:20 2008
New Revision: 940
URL: http://svn.gnome.org/viewvc/pygobject?rev=940&view=rev

Log:
2008-08-11  Paul Pogonyshev  <pogonyshev gmx net>

	Bug 547104 â improve type wrapper creation

	* gobject/pygobject.c (pygobject_register_class): Use new
	pygobject_inherit_slots() to propagate custom slots in normal
	types too.
	(pygobject_inherit_slots): New function, break out of
	pygobject_new_with_interfaces() and rewrite a bit.
	(pygobject_find_slot_for): Add new argument that can forbid
	overriding non-NULL slots.

	* gio/gicon.override (pygio_do_icon_richcompare): Remove, the code
	is now directly in _wrap_g_icon_tp_richcompare().
	(_wrap_g_file_icon_tp_richcompare, _wrap_g_file_icon_tp_hash)
	(_wrap_g_themed_icon_tp_richcompare, _wrap_g_themed_icon_tp_hash):
	Remove, duplicating code in this way is not needed anymore.


Modified:
   trunk/ChangeLog
   trunk/gio/gicon.override
   trunk/gobject/pygobject.c

Modified: trunk/gio/gicon.override
==============================================================================
--- trunk/gio/gicon.override	(original)
+++ trunk/gio/gicon.override	Mon Aug 11 20:15:20 2008
@@ -20,11 +20,6 @@
  * USA
  */
 %%
-headers
-
-static PyObject *  pygio_do_icon_richcompare(PyGObject *self, PyGObject *other, int op);
-
-%%
 ignore-glob
   g_icon_hash
   g_themed_icon_new_from_names
@@ -32,7 +27,7 @@
 %%
 override-slot GIcon.tp_richcompare
 static PyObject *
-pygio_do_icon_richcompare(PyGObject *self, PyGObject *other, int op)
+_wrap_g_icon_tp_richcompare(PyGObject *self, PyGObject *other, int op)
 {
     PyObject *result;
 
@@ -60,11 +55,6 @@
     Py_INCREF(result);
     return result;
 }
-static PyObject *
-_wrap_g_icon_tp_richcompare(PyGObject *self, PyGObject *other, int op)
-{
-    return pygio_do_icon_richcompare(self, other, op);
-}
 %%
 override-slot GIcon.tp_hash
 static long
@@ -180,22 +170,6 @@
     return result;
 }
 %%
-override-slot GFileIcon.tp_richcompare
-/* We need to duplicate, because GIcon is an interface, not a class. */
-static PyObject *
-_wrap_g_file_icon_tp_richcompare(PyGObject *self, PyGObject *other, int op)
-{
-    return pygio_do_icon_richcompare(self, other, op);
-}
-%%
-override-slot GFileIcon.tp_hash
-/* We need to duplicate, because GIcon is an interface, not a class. */
-static long
-_wrap_g_file_icon_tp_hash(PyGObject *self)
-{
-    return g_icon_hash(G_ICON(self->obj));
-}
-%%
 override-slot GFileIcon.tp_repr
 static PyObject *
 _wrap_g_file_icon_tp_repr(PyGObject *self)
@@ -296,22 +270,6 @@
     return ret;
 }
 %%
-override-slot GThemedIcon.tp_richcompare
-/* We need to duplicate, because GIcon is an interface, not a class. */
-static PyObject *
-_wrap_g_themed_icon_tp_richcompare(PyGObject *self, PyGObject *other, int op)
-{
-    return pygio_do_icon_richcompare(self, other, op);
-}
-%%
-override-slot GThemedIcon.tp_hash
-/* We need to duplicate, because GIcon is an interface, not a class. */
-static long
-_wrap_g_themed_icon_tp_hash(PyGObject *self)
-{
-    return g_icon_hash(G_ICON(self->obj));
-}
-%%
 override-slot GThemedIcon.tp_repr
 static PyObject *
 _wrap_g_themed_icon_tp_repr(PyGObject *self)

Modified: trunk/gobject/pygobject.c
==============================================================================
--- trunk/gobject/pygobject.c	(original)
+++ trunk/gobject/pygobject.c	Mon Aug 11 20:15:20 2008
@@ -38,7 +38,10 @@
 static PyObject * pygobject_weak_ref_new(GObject *obj, PyObject *callback, PyObject *user_data);
 static inline PyGObjectData * pyg_object_peek_inst_data(GObject *obj);
 static PyObject * pygobject_weak_ref_new(GObject *obj, PyObject *callback, PyObject *user_data);
-static void pygobject_find_slot_for(PyTypeObject *type, PyObject *bases, int slot_offset);
+static void pygobject_inherit_slots(PyTypeObject *type, PyObject *bases,
+				    gboolean check_for_present);
+static void pygobject_find_slot_for(PyTypeObject *type, PyObject *bases, int slot_offset,
+				    gboolean check_for_present);
 GType PY_TYPE_OBJECT = 0;
 GQuark pygobject_class_key;
 GQuark pygobject_class_init_key;
@@ -505,6 +508,8 @@
         Py_INCREF(type->tp_base);
     }
 
+    pygobject_inherit_slots(type, bases, TRUE);
+
     if (PyType_Ready(type) < 0) {
 	g_warning ("couldn't make the type `%s' ready", type->tp_name);
 	return;
@@ -722,13 +727,7 @@
     type->tp_traverse = py_parent_type->tp_traverse;
     type->tp_clear = py_parent_type->tp_clear;
 
-    pygobject_find_slot_for(type, bases, offsetof(PyTypeObject, tp_richcompare));
-    pygobject_find_slot_for(type, bases, offsetof(PyTypeObject, tp_compare));
-    pygobject_find_slot_for(type, bases, offsetof(PyTypeObject, tp_hash));
-    pygobject_find_slot_for(type, bases, offsetof(PyTypeObject, tp_iter));
-    pygobject_find_slot_for(type, bases, offsetof(PyTypeObject, tp_repr));
-    pygobject_find_slot_for(type, bases, offsetof(PyTypeObject, tp_str));
-    pygobject_find_slot_for(type, bases, offsetof(PyTypeObject, tp_print));
+    pygobject_inherit_slots(type, bases, FALSE);
 
     if (PyType_Ready(type) < 0) {
 	g_warning ("couldn't make the type `%s' ready", type->tp_name);
@@ -766,9 +765,38 @@
  * wrappers created at runtime when appropriate.  We prefer to be on
  * the safe side, so if there is potential collision (more than one
  * custom slot value), we discard custom overrides altogether.
+ *
+ * When registering type with pygobject_register_class(), i.e. a type
+ * that has been manually created (likely with Codegen help),
+ * `check_for_present' should be set to TRUE.  In this case, the
+ * function will never overwrite any non-NULL slots already present in
+ * the type.  If `check_for_present' is FALSE, such non-NULL slots are
+ * though to be set by Python interpreter and so will be overwritten
+ * if heuristic above says so.
  */
 static void
-pygobject_find_slot_for(PyTypeObject *type, PyObject *bases, int slot_offset)
+pygobject_inherit_slots(PyTypeObject *type, PyObject *bases, gboolean check_for_present)
+{
+    static int slot_offsets[] = { offsetof(PyTypeObject, tp_richcompare),
+				  offsetof(PyTypeObject, tp_compare),
+				  offsetof(PyTypeObject, tp_hash),
+				  offsetof(PyTypeObject, tp_iter),
+				  offsetof(PyTypeObject, tp_repr),
+				  offsetof(PyTypeObject, tp_str),
+				  offsetof(PyTypeObject, tp_print) };
+    int i;
+
+    /* Happens when registering gobject.GObject itself, at least. */
+    if (!bases)
+	return;
+
+    for (i = 0; i < G_N_ELEMENTS(slot_offsets); ++i)
+	pygobject_find_slot_for(type, bases, slot_offsets[i], check_for_present);
+}
+
+static void
+pygobject_find_slot_for(PyTypeObject *type, PyObject *bases, int slot_offset,
+			gboolean check_for_present)
 {
 #define TYPE_SLOT(type)  (* (void **) (((char *) (type)) + slot_offset))
 
@@ -776,6 +804,14 @@
     int num_bases = PyTuple_Size(bases);
     int i;
 
+    if (check_for_present && TYPE_SLOT(type) != NULL) {
+	/* We are requested to check if there is any custom slot value
+	 * in this type already and there actually is.  Don't
+	 * overwrite it.
+	 */
+	return;
+    }
+
     for (i = 0; i < num_bases; ++i) {
 	PyTypeObject *base_type = (PyTypeObject *) PyTuple_GetItem(bases, i);
 	void *slot = TYPE_SLOT(base_type);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]