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 647723 - GLib.Variant doesn't define bool() for any of its types
GLib.Variant doesn't define bool() for any of its types
Status: RESOLVED FIXED
Product: pygobject
Classification: Bindings
Component: introspection
2.28.x
Other Linux
: Normal normal
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
Depends on: 647944
Blocks:
 
 
Reported: 2011-04-13 22:03 UTC by Nirbheek Chauhan
Modified: 2012-02-04 14:45 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Define bool() for GLib.Variant objects (2.05 KB, patch)
2011-04-13 22:04 UTC, Nirbheek Chauhan
needs-work Details | Review
Define bool() for GLib.Variant objects, with tests! (4.69 KB, patch)
2012-01-25 04:01 UTC, Nirbheek Chauhan
none Details | Review
Define bool() for GLib.Variant objects, with tests and less deprecated API usage! (4.69 KB, patch)
2012-01-28 08:00 UTC, Nirbheek Chauhan
none Details | Review
Define bool() for GLib.Variant objects, with tests, less deprecated API, and less comments! (4.62 KB, patch)
2012-01-28 14:58 UTC, Nirbheek Chauhan
committed Details | Review

Description Nirbheek Chauhan 2011-04-13 22:03:10 UTC
Because GLib.Variant doesn't define __nonzero__ for python2 and __bool__ for python3, boolean operations on Variant objects fail for all objects that don't have __len__[1].

The attached patch defines both __bool__ and __nonzero__ so that we don't get things like:

  >>> from gi.repository import GLib
  >>> a = GLib.Variant("b", False)
  >>> if a: print 123
  ... 
  Traceback (most recent call last):
  • File "<stdin>", line 1 in <module>
  • File "/usr/lib64/python2.6/site-packages/gi/overrides/GLib.py", line 246 in __len__
    raise TypeError('GVariant type %s does not have a length' % self.get_type_string())   TypeError: GVariant type b does not have a length

However, note that __eq__ *still* doesn't work properly because __hash__ on Variant doesn't return the same number for identical objects. I'll be opening a separate bug for that.

1. http://docs.python.org/reference/datamodel.html#object.__nonzero__
Comment 1 Nirbheek Chauhan 2011-04-13 22:04:46 UTC
Created attachment 185913 [details] [review]
Define bool() for GLib.Variant objects
Comment 2 Sebastian Pölsterl 2011-04-15 14:08:55 UTC
You might consider wrapping g_variant_equal and g_variant_compare as well.
Comment 3 Nirbheek Chauhan 2011-04-16 07:03:49 UTC
(In reply to comment #2)
> You might consider wrapping g_variant_equal and g_variant_compare as well.

I'd try that, but the equivalent GLib.variant_{equal,compare} cause a segfault for me here :(

I'll try to investigate this soon.
Comment 4 Tomeu Vizoso 2012-01-24 15:43:16 UTC
Comment on attachment 185913 [details] [review]
Define bool() for GLib.Variant objects

Can we get test cases as well? Thanks!
Comment 5 Nirbheek Chauhan 2012-01-25 04:01:10 UTC
Created attachment 206049 [details] [review]
Define bool() for GLib.Variant objects, with tests!

(In reply to comment #4)
> (From update of attachment 185913 [details] [review])
> Can we get test cases as well? Thanks!

Tests added, see patch! The current behaviour is to pretend as though the the Variant() wrapper doesn't exist at all. This is applied recursively, so that Variant('v', Variant('v', Variant('v', 0)) is False (mimicking Variant.unpack())

BTW, a bug closely related to this is bug 647725

--
As an aside, in the process of doing all this, I discovered a small bug:

Variant('ay', [0]) is shown as Variant(b'') by __repr__, which is a bug in the print function. Unfortunately, I couldn't figure out where to fix that...
Comment 6 Nirbheek Chauhan 2012-01-28 08:00:49 UTC
Created attachment 206312 [details] [review]
Define bool() for GLib.Variant objects, with tests and less deprecated API usage!

The new revision uses assertEqual instead of assertEquals (which is deprecated).

(In reply to comment #5)
> BTW, a bug closely related to this is bug 647725

I've attached a patch to that bug. The two patches on the two bugs should preferably be committed together.
Comment 7 Sebastian Pölsterl 2012-01-28 10:37:55 UTC
Review of attachment 206312 [details] [review]:

::: gi/overrides/GLib.py
@@ +324,3 @@
+    def __bool__(self):
+        if self.get_type_string() in ['y', 'n', 'q', 'i', 'u', 'x', 't', 'h', 'd']:
+            # FIXME: '\0' is True in Python, but Variant('y', '\0') is False

Do you mean '\0' as str object which is used to represent byte arrays in python 2 or zero the number? Could you please give an example where this issue occurs.
Comment 8 Nirbheek Chauhan 2012-01-28 10:43:16 UTC
(In reply to comment #7)
> Review of attachment 206312 [details] [review]:
> 
> ::: gi/overrides/GLib.py
> @@ +324,3 @@
> +    def __bool__(self):
> +        if self.get_type_string() in ['y', 'n', 'q', 'i', 'u', 'x', 't', 'h',
> 'd']:
> +            # FIXME: '\0' is True in Python, but Variant('y', '\0') is False
> 
> Do you mean '\0' as str object which is used to represent byte arrays in python
> 2 or zero the number? Could you please give an example where this issue occurs.

What I mean is that the byte \0 is FALSE in g_variant, but b'\0' is True in Python2 and Python3.

I'm not sure if this is of any actual consequence, I just wanted to note this as the only difference in bool definitions I could find.
Comment 9 Sebastian Pölsterl 2012-01-28 11:35:20 UTC
I think there is a slight difference: b'\0' is a byte array of length 1 whereas Variant.get_byte returns a single byte which is an integer.
Comment 10 Nirbheek Chauhan 2012-01-28 14:58:25 UTC
Created attachment 206329 [details] [review]
Define bool() for GLib.Variant objects, with tests, less deprecated API, and less comments!

(In reply to comment #9)
> I think there is a slight difference: b'\0' is a byte array of length 1 whereas
> Variant.get_byte returns a single byte which is an integer.

Ah, you're right. \0 is equivalent to 0x00 in Python, not b'\0'. I forgot how strings worked there. :)

I've removed the comment now.
Comment 11 Sebastian Pölsterl 2012-02-04 14:45:39 UTC
This problem has been fixed in the development version. The fix will be available in the next major software release. Thank you for your bug report.