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 620912 - Correctly handle functions with out args and bool return value.
Correctly handle functions with out args and bool return value.
Status: RESOLVED WONTFIX
Product: pygobject
Classification: Bindings
Component: introspection
unspecified
Other All
: Normal normal
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
: 656872 (view as bug list)
Depends on: 626721
Blocks: 622963
 
 
Reported: 2010-06-07 22:27 UTC by Steve Frécinaux
Modified: 2012-04-20 13:09 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Correctly handle functions with out args and bool return value. (2.91 KB, patch)
2010-06-07 22:27 UTC, Steve Frécinaux
needs-work Details | Review

Description Steve Frécinaux 2010-06-07 22:27:42 UTC
This way we can handle correctly stuff like Gdk.Event.get_state()
Comment 1 Steve Frécinaux 2010-06-07 22:27:44 UTC
Created attachment 162984 [details] [review]
Correctly handle functions with out args and bool return value.

Functions with out args which return a boolean value usually return
false if the out args could not be set.

We handle those by discarding the boolean value if it is True, and by
returning None instead of a tuple if the C function returns False.
Comment 2 johnp 2010-06-08 16:43:05 UTC
Review of attachment 162984 [details] [review]:

You have a number of unrelated patches in here
Comment 3 Steve Frécinaux 2010-06-08 17:01:46 UTC
What unrelated patches? Should I split the python and C parts?
Comment 4 johnp 2010-06-08 17:12:39 UTC
Comment on attachment 162984 [details] [review]
Correctly handle functions with out args and bool return value.

>From 36dc7c1ac9c98975abf39f536f237fcd2229a93d Mon Sep 17 00:00:00 2001
>From: =?UTF-8?q?Steve=20Fr=C3=A9cinaux?= <code@istique.net>
>Date: Tue, 8 Jun 2010 00:24:30 +0200
>Subject: [PATCH] Correctly handle functions with out args and bool return value.
>
>Functions with out args which return a boolean value usually return
>false if the out args could not be set.
>
>We handle those by discarding the boolean value if it is True, and by
>returning None instead of a tuple if the C function returns False.
>
>https://bugzilla.gnome.org/show_bug.cgi?id=620912
>---
> gi/overrides/Gdk.py |    4 ++--
> gi/overrides/Gtk.py |    6 +++---
> gi/pygi-invoke.c    |   14 +++++++++++++-
> 3 files changed, 18 insertions(+), 6 deletions(-)
>

* snip *

>diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
>index 8dc3d26..74248c0 100644
>--- a/gi/pygi-invoke.c
>+++ b/gi/pygi-invoke.c
>@@ -218,7 +218,7 @@ _prepare_invocation_state (struct invocation_state *state,
>     }
> 
>     state->n_return_values = state->n_out_args - state->n_aux_out_args;
>-    if (state->return_type_tag != GI_TYPE_TAG_VOID) {
>+    if (state->return_type_tag != GI_TYPE_TAG_VOID && state->return_type_tag != GI_TYPE_TAG_BOOLEAN) {
>         state->n_return_values += 1;
>     }

This isn't true for actual boolean returns such as gdk_pixbuf_format_is_writable

>@@ -748,6 +748,18 @@ _process_invocation_state (struct invocation_state *state,
>             if (state->return_type_tag == GI_TYPE_TAG_VOID) {
>                 /* The current return value is None. */
>                 Py_DECREF (state->return_value);
>+            } else if (state->return_type_tag == GI_TYPE_TAG_BOOLEAN) {
>+                if (state->return_value == Py_False) {
>+                    /* The function returned false. We must return None */
>+                    Py_DECREF (state->return_value);
>+                    Py_DECREF (return_values);
>+                    state->return_value = Py_None;
>+                    Py_INCREF (state->return_value);
>+                    return TRUE;
>+                }
>+                else {
>+                    Py_DECREF (state->return_value);
>+                }

So this isn't complete.  We can't assume that all boolean returns indicate success.  We either need to add an annotation to GObject-introspection (such as a success return type) or use some sort of heuristic.  I would say only do this for methods which have one out variable.  This is because returning None for something that returns a tuple would break something like (key, val) = success_func().  I would also process this right before we return as it should be easy to pop the boolean off the return stack and at that point you will have all the information needed to perform the correct heuristic. Good start though.

>             } else {
>                 /* Put the return value first. */
>                 g_assert (state->return_value != NULL);
>-- 
>1.7.1
Comment 5 johnp 2010-06-08 17:20:21 UTC
Comment on attachment 162984 [details] [review]
Correctly handle functions with out args and bool return value.

>From 36dc7c1ac9c98975abf39f536f237fcd2229a93d Mon Sep 17 00:00:00 2001
>From: =?UTF-8?q?Steve=20Fr=C3=A9cinaux?= <code@istique.net>
>Date: Tue, 8 Jun 2010 00:24:30 +0200
>Subject: [PATCH] Correctly handle functions with out args and bool return value.
>
>Functions with out args which return a boolean value usually return
>false if the out args could not be set.
>
>We handle those by discarding the boolean value if it is True, and by
>returning None instead of a tuple if the C function returns False.
>
>https://bugzilla.gnome.org/show_bug.cgi?id=620912
>---
> gi/overrides/Gdk.py |    4 ++--
> gi/overrides/Gtk.py |    6 +++---
> gi/pygi-invoke.c    |   14 +++++++++++++-
> 3 files changed, 18 insertions(+), 6 deletions(-)
>
>diff --git a/gi/overrides/Gdk.py b/gi/overrides/Gdk.py
>index de35870..b4ad4e7 100644
>--- a/gi/overrides/Gdk.py
>+++ b/gi/overrides/Gdk.py
>@@ -72,6 +72,6 @@ __all__ = ['Rectangle', 'Color', 'Drawable']
> 
> import sys
> 
>-initialized, argv = Gdk.init_check(sys.argv)
>-if not initialized:
>+argv = Gdk.init_check(sys.argv)
>+if argv is None:
>     raise RuntimeError("Gdk couldn't be initialized")
>diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py
>index 38b0dfa..916b340 100644
>--- a/gi/overrides/Gtk.py
>+++ b/gi/overrides/Gtk.py
>@@ -244,7 +244,7 @@ __all__ = ['ActionGroup', 'Builder', 'UIManager']
> 
> import sys
> 
>-initialized, argv = Gtk.init_check(sys.argv)
>-sys.argv = argv
>-if not initialized:
>+argv = Gtk.init_check(sys.argv)
>+if argv is None:
>     raise RuntimeError("Gtk couldn't be initialized")
>+sys.argv = argv


Oh, I see.  I wasn't quite sure what you were doing here but you were just fixing this up if the patch went in.  No need to split it out.
Comment 6 Steve Frécinaux 2010-06-08 17:46:59 UTC
(In reply to comment #4)
> This isn't true for actual boolean returns such as
> gdk_pixbuf_format_is_writable

Right, I miss the checks for the number of out args

> So this isn't complete.  We can't assume that all boolean returns indicate
> success.  We either need to add an annotation to GObject-introspection (such as
> a success return type) or use some sort of heuristic.  I would say only do this
> for methods which have one out variable.

Actually, there is this "state->n_return_values > 1" check around that bit of code, which I think implements what you say at the end.

> This is because returning None for
> something that returns a tuple would break something like (key, val) =
> success_func().

Isn't that what pygtk used to do?
Comment 7 Tomeu Vizoso 2010-07-26 16:13:03 UTC
Taking out from the queue as we need tests (will ping J5 when I see him around).
Comment 8 Simon van der Linden 2010-08-12 10:01:00 UTC
Steve, handling such functions the way you propose may prevent other functions to be used correctly, since there is no indication that the boolean is about the successful completion of the function. We need annotations first.
Comment 9 Martin Pitt 2012-04-04 12:32:22 UTC
We have had the current behaviour for at least two GNOME release cycles now. By now we have overrides and annotations which deal with the problem on a per-case basis, and programs which expect the current API. Special-casing this would IMHO be unexpected, an API break, and also not in line with GI's aim at keeping the original API.

So I'm tempted to just close this as wontfix at this point. Steve, what do you think?
Comment 10 Steve Frécinaux 2012-04-04 12:41:50 UTC
What do the annotations look like?

As long as the behaviour is the one a python programmer would expect (ie, the one described here and used in pygtk) then fine by me. At the time of the patch there were no such annotations...
Comment 11 Martin Pitt 2012-04-04 12:59:08 UTC
One instance which I'm aware of is that gdbus-codegen generates them that way. E. g. in udisks2:

/**
 * udisks_manager_call_loop_setup_sync:
[...]
 * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
 */

Otherwise, with PyGI most people now expect the C API, i. e. (return value, out arg1, out arg2, ...) as return value. After 1.5 years this should now be considered an API which we shouldn't deliberately break, and it's also helpful for consistency. Also, as Simon already said, there might well be functions which return a boolean which isn't mutually exclusive with the out argument.
Comment 12 Martin Pitt 2012-04-09 12:57:18 UTC
Closing for now, as this would be quite a significant API break, introduce an inconsistency, and is potentially wrong for some methods.

Please feel free to reopen if you still think this is relevant. But I unmark the "patch" flag to get this off the patch review queue.
Comment 13 Martin Pitt 2012-04-20 13:09:00 UTC
*** Bug 656872 has been marked as a duplicate of this bug. ***