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 559746 - gtk.Widget.set_sensitive should accept None or ""
gtk.Widget.set_sensitive should accept None or ""
Status: RESOLVED OBSOLETE
Product: pygobject
Classification: Bindings
Component: codegen
Git master
Other Linux
: Normal minor
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
Depends on:
Blocks:
 
 
Reported: 2008-11-07 13:23 UTC by Marco Túlio Gontijo e Silva
Modified: 2012-02-10 08:22 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Patch to correct the bug (1.46 KB, patch)
2009-06-21 23:54 UTC, Marco Túlio Gontijo e Silva
none Details | Review

Description Marco Túlio Gontijo e Silva 2008-11-07 13:23:18 UTC
To do something as:

        self.ok.set_sensitive(
                self.name.get_text().strip()
                and self.architecture.get_text().strip()
                and file
                and exists(file))

I need to add bool().  It'd be good to be able to do this without using bool().
Comment 1 Gian Mario Tagliaretti 2008-11-07 13:30:04 UTC
set_sensitive() it's a wrapper around the sensitive property od gtk.Widget which   accepts a gboolean value, not a bug.
Comment 2 Gustavo Carneiro 2008-11-07 14:25:10 UTC
I think I know what Marco means.  The generated wrapper looks like this:

static PyObject *
_wrap_gtk_widget_set_sensitive(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "sensitive", NULL };
    int sensitive;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"i:GtkWidget.set_sensitive", kwlist, &sensitive))
        return NULL;
    
    gtk_widget_set_sensitive(GTK_WIDGET(self->obj), sensitive);
    
    Py_INCREF(Py_None);
    return Py_None;
}

While the defs look like:

(define-method set_sensitive
  (of-object "GtkWidget")
  (c-name "gtk_widget_set_sensitive")
  (return-type "none")
  (parameters
    '("gboolean" "sensitive")
  )
)

So, codegen is treating gboolean as int, which is wrong.  Every object has a boolean value, not just integers.  "" is false, and None is false.  The generated wrapper should look like this instead:

static PyObject *
_wrap_gtk_widget_set_sensitive(PyGObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = { "sensitive", NULL };
    PyObject *py_sensitive;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O:GtkWidget.set_sensitive", kwlist, &sensitive))
        return NULL;
    
    gtk_widget_set_sensitive(GTK_WIDGET(self->obj), PyObject_IsTrue(py_sensitive));
    
    Py_INCREF(Py_None);
    return Py_None;
}

codegen/argtypes.py:

class BoolArg(IntArg):
    def write_return(self, ptype, ownsreturn, info):
        info.varlist.add('int', 'ret')
        info.codeafter.append('    return PyBool_FromLong(ret);\n')

To fix the bug, a write_param method needs to be written for BoolArg that does the right thing.
Comment 3 Gian Mario Tagliaretti 2008-11-07 16:14:04 UTC
Gustavo in my opionion it should accept only True|False and not an emtpy string or None, does GTK+ itself accept an empty string or NULL? (rhetorical question)
Comment 4 Gustavo Carneiro 2008-11-07 16:49:12 UTC
It is not a question of gtk+, it is a language issue.  A simple 'if' statement in Python accepts any object, not just True|False.  For example:

if "":
   print "xxx"
else:
   print "yyyy"

This prints yyy.  Same with None, (), and [].
Comment 5 Gian Mario Tagliaretti 2008-11-07 20:24:51 UTC
I know that True|False are not the only possible choice in this case, we can modify (not fix imho) the method to accept other pseudo boolean objects, I just don't think we should do that, but of course I have nothing against it.

I still think it's not a bug :)
Comment 6 Gustavo Carneiro 2008-11-08 11:03:03 UTC
It is debatable either way.  On one hand, by only allowing int type as boolean you are catching some programming errors.  On the other hand, if you do that you are being incoherent with the Python language.

I'm +0.5 for aligning gboolean with the Python language (i.e. use PyObject_IsTrue), but also understand if people want to stick to the existing behaviour.
Comment 7 Paul Pogonyshev 2008-11-08 23:41:25 UTC
I'm -1 on this.  I think it is too error-prone for minor convenience of not requiring bool().  If we go this path, why not make gtk.Window.set_title accept anything and use __str__ on it, and so on?
Comment 8 Marco Túlio Gontijo e Silva 2009-06-17 21:39:31 UTC
I'm +1 on this.

Comment #7 from Paul Pogonyshev:
> If we go this path, why not make gtk.Window.set_title accept
> anything and use __str__ on it, and so on?

Because that's not how the Python language works in other situations.  That would make sense in another languages, but not in Python.  I Perl, for instance, you can pass an integer where a string is expected:

$ perl -e 'print length "abc"'
3
$ perl -e 'print length 123'
3

On the other way, accepting only bool() makes sense in other languages, but not in Python.  In Python, you can pass "" or None when a bool() is expected:

Comment #4 from Gustavo Carneiro:
> if "":
>    print "xxx"
> else:
>    print "yyyy"

Comment #3 from Gian Mario Tagliaretti:
> does GTK+ itself accept an empty string or NULL?

GTK+ is written in C, and in this language this behaviour makes sense.  In this language, writing 1 for True, and 0 for False, makes sense.  In Ruby, for instance, 0 is treated as True, since only nil and false are False.

My conclusion is that there's no point in keeping the library exact behaviour in all bindings, specially when this behaviour was defined by something that only makes sense in the language that the library was written, in this case, C.

Good night.
Comment 9 Lincoln de Sousa 2009-06-17 23:00:19 UTC
I'm +1 on this too.

As Marco and Gustavo said, this change will make gtk bindings fit better with python concepts. It is common to call such a thing as "Pythonic".

I see a very closer case in the way that GtkListStore is binded [0]. A simple C to python binding can be used to append new entries to a model, like this:

    iter = model.append()
    model.set(iter, 0, “foobar”)
    model.set(iter, 1, 1138)
    model.set(iter, 2, 3.14)

But a more pythonic way was added too:

    model.append(["foobar", 1138, 3.14])

There are other examples that try to make gtk python bindings more natural to a python programmer.

So I think it would be really nice to have another thing to make it closer.

[0] http://blogs.gnome.org/johan/2008/05/06/using-gtkliststore-in-python/
Comment 10 Paul Pogonyshev 2009-06-19 21:06:08 UTC
OK, I change my vote to +0.  I agree that booleans are "special" in that e.g. 'if' and similar operators auto-convert anything with __nonzero__/__bool__, but I don't remember any built-in string auto-conversions.  Patches are welcome.
Comment 11 Marco Túlio Gontijo e Silva 2009-06-21 23:54:45 UTC
Created attachment 137146 [details] [review]
Patch to correct the bug

This code was based on the IntArg and the UInt64Arg classes.
Comment 12 Martin Pitt 2012-02-10 08:22:11 UTC
codegen and the static bindings are obsolete since pygobject 3.0, which is GI only.

Thanks!