After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 128765 - GObject metaclass
GObject metaclass
Status: RESOLVED FIXED
Product: pygobject
Classification: Bindings
Component: gobject
2.9.0
Other Linux
: Normal enhancement
: ---
Assigned To: Gustavo Carneiro
Python bindings maintainers
Depends on:
Blocks:
 
 
Reported: 2003-12-08 01:00 UTC by Gustavo Carneiro
Modified: 2006-01-09 14:11 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
the patch (5.54 KB, patch)
2003-12-08 01:01 UTC, Gustavo Carneiro
none Details | Review
Allow registering multiple classes with the same name in same module (3.12 KB, patch)
2004-04-18 11:34 UTC, Gustavo Carneiro
committed Details | Review
Updated metaclass patch (6.74 KB, patch)
2004-06-20 11:52 UTC, Gustavo Carneiro
none Details | Review
new patch, now really works solidly (6.76 KB, patch)
2005-04-25 14:50 UTC, Gustavo Carneiro
none Details | Review
improved metaclass patch (10.38 KB, patch)
2005-04-25 15:33 UTC, Gustavo Carneiro
none Details | Review
minor correction: forgot to check return value of PyErr_Warn() (10.41 KB, patch)
2005-04-25 15:38 UTC, Gustavo Carneiro
none Details | Review
cleaned up patch (10.63 KB, patch)
2005-05-22 22:21 UTC, Gustavo Carneiro
committed Details | Review

Description Gustavo Carneiro 2003-12-08 01:00:40 UTC
The following patch adds a metaclass to all GObject types.   [Although
the patch looks simple, I actually spent almost 5 hours getting this to
work...]

  At the moment, the only useful thing that the metaclass does is to
automatically call gobject.type_register for new GObject-derived python
classes, but more equally interesting uses can be given in the future. 
Such as declaring GInterfaces as base types of a class... ;)
Comment 1 Gustavo Carneiro 2003-12-08 01:01:11 UTC
Created attachment 22203 [details] [review]
the patch
Comment 2 James Henstridge 2003-12-13 14:25:07 UTC
This is related to bug 80915.

In order to feel fully comfortable with something like this, I would
prefer if derived GObjects acted a bit more like Python objects, so
that we don't surprise people.

What I am referring to is the requirement to call
self.__gobject_init__() on classes that have been registered with
gobject.type_register().  I have some ideas on how to solve this, but
it would require changes to all the GObject constructors in
pygtk+friends (it is probably doable though).

In essence, make things like gtk.HBox.__init__ actually call
g_object_init() with the GType of the instance being created.  This
way, if you subclass gtk.HBox in the way a Python programmer would
expect to, you would end up with instances of the correct class. 
Without a change like this, the metaclass will probably create
problems/questions rather than solving them.


It is worth noting that a patch like this would only deprecate
gobject.type_register() -- gobject.signal_new() is still necessary to
create some signals.  Consider the "parent_set" signal on GtkWidget,
for instance.  It couldn't be defined til after the GType for
GtkWidget had been registered.
Comment 3 James Henstridge 2003-12-13 14:31:47 UTC
It is also worth noting that if types are registered automatically,
some code that previously functioned may now fail.  Consider this:
    import gobject

    class C(gobject.GObject):
        pass
    class C(gobject.GObject):
        pass

The second class definition will fail to register, due to the type
name conflict.  We would need some form of conflict resolution to
handle this case.
Comment 4 Gustavo Carneiro 2003-12-13 14:56:32 UTC
  I agree with you that gobject.signal_new() is still required.  I had
already discussed with Johan about this.

  I also completely agree that the g_object_init() hack needs to be
resolved.  I hate that too...

  However, I disagree that the metaclass creates any new problems if
the g_object_init() issues is not resolved.  But, fine, you're trying
to put pressure on resolving g_object_init() too, I understand ;-) 
But resolving g_object_init() should be in a different bug report.  It
is better to take one step at a time, imho.

  But, by any chance, does your enivisoned solution involve calling
g_object_newv(), passing arguments as properties, in the python
constructor, and passing the correct GType as well?  If so, then
that's one more point we agree in ;)  And I believe it's very much
worth doing, even if it means changing all constructors.
Comment 5 James Henstridge 2003-12-14 07:04:46 UTC
Yeah, the plan was that eg. _wrap_gtk_hbox_new() would be changed to
look something like this:

static int
_wrap_gtk_hbox_new(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "homogeneous", "spacing", NULL };
    GType obj_type;
    int homogeneous = FALSE, spacing = 0;
 
    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"|ii:GtkHBox.__init__", kwlist, &homogeneous, &spacing))
        return -1;

    obj_type = pyg_type_from_object(self);
    self->obj = g_object_new(obj_type,
                             "homogeneous", homogeneous,
                             "spacing", spacing,
                             NULL);
    if (!self->obj) {
        PyErr_SetString(PyExc_RuntimeError,
                        "could not create GtkHBox object");
        return -1;
    }
    pygobject_register_wrapper((PyObject *)self);
    return 0;
}

From what I hear from the C++ developers, gtkmm essentially does this
in all their constructors, so it should be possible to reimplement all
the constructors.  This is really a separate problem to the metaclass
one though.

Anyway, the main place where this is likely to cause problems is where
two GObject subclasses with the same name get defined (like I
mentioned earlier).  Some of the places I can imagine this occuring are:
 1) define a class within a function, then call the function
    multiple times.
 2) calling reload() on a module that defines some GObject subclasses.
Comment 6 Erik Grinaker 2004-02-24 12:42:49 UTC

*** This bug has been marked as a duplicate of 129843 ***
Comment 7 Gustavo Carneiro 2004-03-28 21:42:13 UTC
This is not a duplicate. It is a slightly different issue.  We just deviated
from the topic a bit in the discussion, but the metaclass issue is completely
orthogonal to the __init__ problem.
Comment 8 Christian Reis (not reading bugmail) 2004-04-02 00:48:51 UTC
Over to patch author. Gustavo, reassign to nobody if this falls off your plate,
thanks.
Comment 9 Gustavo Carneiro 2004-04-02 22:10:46 UTC
I won't commit unless I get some positive feedback on this.
Personally, I think this is very useful patch, because calling
gobject.type_register(MyClass) seems a bit ugly and un-pythonic to me.  And
unlike the __init__ problem (bug 129843), this is a simple fix.
Comment 10 Gustavo Carneiro 2004-04-18 11:34:33 UTC
Created attachment 26768 [details] [review]
Allow registering multiple classes with the same name in same module

This patch solves the following problem pointed out by James:
    class C(gobject.GObject):
	pass
    class C(gobject.GObject):
	pass

It adds -v<n> to the type name.  Example:
class MyObject(gobject.GObject): pass
gobject.type_register(MyObject)
print MyObject.__gtype__

class MyObject(gobject.GObject): pass
gobject.type_register(MyObject)
print MyObject.__gtype__

Output is:
<GType __main__+MyObject (135076320)>
<GType __main__+MyObject-v2 (134521112)>

With this problem solved, I reapply the metaclass patch for inclusion in pygtk.
What say you?
Comment 11 Gustavo Carneiro 2004-04-18 11:39:17 UTC
One thing worth noting is that if we include metaclass + gtype "uniquification"
patch, we should make gobject.type_register() a no-op and give deprecation
warning.  Otherwise, this legacy code registers the same type twice, once
because of the metaclass, and another time by explicit call to
gobject.type_register:
    class MyObject(gobject.GObject): pass
    gobject.type_register(MyObject)
Comment 12 Gustavo Carneiro 2004-04-18 12:16:48 UTC
This last patch is useful by itself, for example when you reload() a module, as
James pointed out, so I committed it to cvs head.
Comment 13 Gustavo Carneiro 2004-06-20 11:52:32 UTC
Created attachment 28879 [details] [review]
Updated metaclass patch

Here's an updated patch.  Unfortunately, no matter what I do, python crashes in
an apparently unrelated function with some programs.  While
examples/gobject/signal.py works just fine, pygtk-demo crashes.  I've given up
for now.  This patch shouldn't be included in pygtk 2.4, but I'll try again
when python 2.4 comes out.
Comment 14 Gustavo Carneiro 2005-04-25 14:50:03 UTC
Created attachment 45652 [details] [review]
new patch, now really works solidly
Comment 15 Gustavo Carneiro 2005-04-25 15:33:46 UTC
Created attachment 45653 [details] [review]
improved metaclass patch

Changes:
  - A bit of refactoring;
  - gobject.type_register now gives a deprecation warning and only registers
the class if it wasn't already registered (doesn't contain a __gtype__
attribute).
Comment 16 Gustavo Carneiro 2005-04-25 15:38:36 UTC
Created attachment 45654 [details] [review]
minor correction: forgot to check return value of PyErr_Warn()
Comment 17 Gustavo Carneiro 2005-05-22 15:15:22 UTC
It is time to commit this patch.  Any objections?
Comment 18 Gustavo Carneiro 2005-05-22 22:21:58 UTC
Created attachment 46771 [details] [review]
cleaned up patch