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 129843 - Make all constructors work through g_object_new()
Make all constructors work through g_object_new()
Status: RESOLVED FIXED
Product: pygobject
Classification: Bindings
Component: gobject
2.9.0
Other All
: Normal normal
: ---
Assigned To: Gustavo Carneiro
Python bindings maintainers
: 80915 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2003-12-22 16:14 UTC by James Henstridge
Modified: 2006-01-09 14:11 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Generate constructors that use g_object_newv (12.44 KB, patch)
2004-07-03 18:07 UTC, Gustavo Carneiro
none Details | Review
Example metaclass that excepts arbitrary properties via keyword arguments (6.72 KB, text/plain)
2004-07-04 19:04 UTC, John Ehresman
  Details
defs parameters <-> properties checker (1.32 KB, application/x-python)
2004-07-06 21:28 UTC, Gustavo Carneiro
  Details
Patch to support argname != propname (already in cvs) (4.83 KB, patch)
2004-07-08 21:01 UTC, Gustavo Carneiro
none Details | Review

Description James Henstridge 2003-12-22 16:14:39 UTC
One of the warts in pygtk w.r.t. defining new widget types is that the
standard way of chaining up to the superclass's constructor does not act as
expected.  The following code creates a C level instance of GtkHBox rather
than MyBox:
  class MyBox(gtk.HBox):
    def __init__(self):
      gtk.HBox.__init__(self)
  gobject.type_register(MyBox)

To get the desired behaviour, the gtk.HBox.__init__(self) call needs to be
replaced with self.__gobject_init__() or gobject.GObject.__init__(self).

To get rid of this inconsistency, we would need to modify all GObject
constructors to create C level instances of the wrapper class's type.  This
would require using g_object_new() rather than eg. gtk_hbox_new().

This might make it impossible to auto-generate constructors for GObjects,
but it is probably worth it.  An example constructor can be found in the
comments of bug 128765 (GObject metaclass).
Comment 1 Erik Grinaker 2004-02-24 12:40:45 UTC
*** Bug 80915 has been marked as a duplicate of this bug. ***
Comment 2 Erik Grinaker 2004-02-24 12:42:46 UTC
*** Bug 128765 has been marked as a duplicate of this bug. ***
Comment 3 Christian Reis (not reading bugmail) 2004-03-28 21:37:10 UTC
This needs to get on the radar.
Comment 4 Johan (not receiving bugmail) Dahlin 2004-03-29 09:20:21 UTC
For reference: HBox.__init__

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;
}
Comment 5 Johan (not receiving bugmail) Dahlin 2004-03-29 09:22:36 UTC
Which is different from the current one:

-    self->obj = (GObject *)gtk_hbox_new(homogeneous, spacing);
+    obj_type = pyg_type_from_object(self);
+    self->obj = g_object_new(obj_type,
+                             "homogeneous", homogeneous,
+                             "spacing", spacing,
+                              NULL);

Shouldn't be too difficult to modify the code generator.
Comment 6 Gustavo Carneiro 2004-07-03 18:07:07 UTC
Created attachment 29186 [details] [review]
Generate constructors that use g_object_newv

Basically this patch makes the code generator generate constructors that use
g_object_newv, thus fixing this bug.  The defs will have to be slightly
changed.  Take a look at the sample change in HBox constructor.   Only the
property names are necessary, not their types, nor default values.  Currently,
argument names and property names must be the same, but the infrastructure is
there to support argument names different from the properties.
Of course, overriden code is not affected, but I guess we can fix that code
with time...
Some minor cleanup required, but basically I'm happy with this patch.  Feedback
most welcome.
Comment 7 Johan (not receiving bugmail) Dahlin 2004-07-04 17:33:32 UTC
Thanks a lot for working on this.

Patch looks good, some minor comments:

pyg_parse_constructor_args is quite complicated, this is fine because it does
quite a bit. But a more verbose documentation/doc comment would be nice.

Is it possible to do a map over a GParameter*, instead of creating an extra
variable (counter) and just call this function with the number of arguments? If
there isn't something in glib (similar to g_list_foreach), then it's fine as it
is right now

We're changing the output of the code generator slightly (on stderr, progress
output), not sure if it's a good ide.

new-style is a bad name, property-style is better, to avoid confusion with
new-style classes.

I hate "if foo: bar".

Which code requires Parameter/Property to be treated as a four sized tuple?
Comment 8 Gustavo Carneiro 2004-07-04 17:58:10 UTC
The stderr messages **writing new-style constructor** are just debugging
messages, will be removed.  The rest of style changes I will take care of.

Still, perhaps it is a good idea to generate warning when creating 'old-style'
constructors?  Because they trigger this bug and should be replaced sooner or
later--if not with property-style constructor, then with an override.

After the code is in, a major effort of changing all constructors in the .defs
awaits us... not to mention updating the manual constructors.. :-|
Comment 9 John Ehresman 2004-07-04 19:04:25 UTC
Created attachment 29221 [details]
Example metaclass that excepts arbitrary properties via keyword arguments

Example metaclass base class used to help implement gobject subclasses along
with a trivial example.  My suggestion is to allow any property to be set via
keyword arguments to the object constuctor, so the something like the following
can be used to create and init a widget:

w = gtk.Alignment(xscale = 1.0, yscale = 0.0,
		  xalign = 0.0, yalign = 0.5, visible = True,
		  child = gtk.HBox(visible = True, spacing = 2))

The file may not work as is because it was copied out of a larger file where it
does work.
Comment 10 Gustavo Carneiro 2004-07-04 22:08:44 UTC
Property based constructors patch committed, with some cleanup/fixes.  More work
required to convert all (parameter ...) to (property ...) of constructors.  Now
I need sleep..
Comment 11 Gustavo Carneiro 2004-07-06 21:28:53 UTC
Created attachment 29295 [details]
defs parameters <-> properties checker

I wrote a small script that scans .defs, finds all constructors, and compares
all parameters agains the list of properties of the corresponding object.  It
then warns about mismatches between param names and property names.

It seems to suggest that, in module gtk, a few constructors will require
different names between properties and parameters.  Also, a very small number
of constructors don't have corresponding properties, not even with different
name.  These need to be overriden, I'm afraid.
Comment 12 Gustavo Carneiro 2004-07-08 21:01:45 UTC
Created attachment 29363 [details] [review]
Patch to support argname != propname (already in cvs)
Comment 13 Gustavo Carneiro 2004-07-08 22:16:55 UTC
http://cvs.gnome.org/viewcvs/gnome-python/pygtk/gtk/gtk.defs?r1=1.183&r2=1.184&diff_format=u

So now we can subclass most widgets without calling self.__gobject_init__ ;-)

A couple of constructors could not be converted, due to missing properties. 
Also, the constructors in .override files (such as gtk.Dialog) need manual
changes, but those changes shouldn't be difficult.

The other modules, gdk and pango, don't need the same treatment, do they?  Who
would want to subclass gdk.Window or pango.Font?
Comment 15 Johan (not receiving bugmail) Dahlin 2004-07-17 13:08:32 UTC
Please revert the GtkTable. It breaks in gtk_table_resize (called from gazpacho
somewhere)

It's actually a Gtk+ bug, since it says that rows can be 0 to MAXUINT, but it
asserts in resize if it's not higher than 0.

Or is gazpacho perhaps doing something weird?
Comment 16 Gustavo Carneiro 2004-07-17 14:45:11 UTC
The problem is different defaults for n_rows and n_columns. PyGtk used to have
default=1, while gtk+ uses default=0, which is invalid.
IMHO, gtk+ is right, and the current pygtk API is wrong, because it makes no
sense to have n_rows and n_columns parameters optional, since there is no value
that can be considered a good default.  Certainly the 1x1 default is not useful
because a table with n_rows=1 is like an HBox, and n_columns=1 is like a VBox.
Can we break the API and make rows, cols mandatory arguments?  We _are_ allowed
to break the API for now, you know... ;-)
Comment 17 Johan (not receiving bugmail) Dahlin 2004-07-17 14:57:07 UTC
Perhaps we can throw a warning instead that not specifying any arguments is
deprecated?

One might otherwise argue that all classes/types in PyGTK should be able to be
created without specifying any arguments. (as long as it's possible of course)
Comment 18 Gustavo Carneiro 2004-07-17 15:32:21 UTC
Fixed gtk.Table defaults.  No warning given, though.  Maybe later..
Comment 19 Gustavo Carneiro 2004-10-07 13:23:57 UTC
I think this is generally fixed, unless I missed one or two objects...