summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Pogonyshev <pogonyshev@gmx.net>2008-08-11 20:15:20 +0000
committerPaul Pogonyshev <paulp@src.gnome.org>2008-08-11 20:15:20 +0000
commitbc1a275dedc30f56face403118699ebf9aafa846 (patch)
tree12120a93b4903081958a9287d2da20adec9e8420
parent41194973be3d0974521c86f18affa4e53904f10e (diff)
downloadpygobject-bc1a275dedc30f56face403118699ebf9aafa846.tar.gz
pygobject-bc1a275dedc30f56face403118699ebf9aafa846.tar.xz
pygobject-bc1a275dedc30f56face403118699ebf9aafa846.zip
Bug 547104 – improve type wrapper creation
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. svn path=/trunk/; revision=940
-rw-r--r--ChangeLog18
-rw-r--r--gio/gicon.override44
-rw-r--r--gobject/pygobject.c54
3 files changed, 64 insertions, 52 deletions
diff --git a/ChangeLog b/ChangeLog
index 1cc6502..a24749b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+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.
+
2008-08-10 Paul Pogonyshev <pogonyshev@gmx.net>
Bug 546120 – make gio.File more Pythonic
diff --git a/gio/gicon.override b/gio/gicon.override
index 8da8d74..6cbe180 100644
--- a/gio/gicon.override
+++ b/gio/gicon.override
@@ -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 @@ ignore-glob
%%
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 @@ pygio_do_icon_richcompare(PyGObject *self, PyGObject *other, int op)
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 @@ _wrap_g_loadable_icon_load_finish(PyGObject *self,
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 @@ _wrap_g_themed_icon_get_names(PyGObject *self)
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)
diff --git a/gobject/pygobject.c b/gobject/pygobject.c
index d0546fa..15ddc47 100644
--- a/gobject/pygobject.c
+++ b/gobject/pygobject.c
@@ -38,7 +38,10 @@ static inline int pygobject_clear(PyGObject *self);
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 @@ pygobject_register_class(PyObject *dict, const gchar *type_name,
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 @@ pygobject_new_with_interfaces(GType gtype)
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 @@ pygobject_new_with_interfaces(GType gtype)
* 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 @@ pygobject_find_slot_for(PyTypeObject *type, PyObject *bases, int slot_offset)
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);