GNOME Bugzilla – Bug 647723
GLib.Variant doesn't define bool() for any of its types
Last modified: 2012-02-04 14:45:39 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):
+ Trace 226723
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__
Created attachment 185913 [details] [review] Define bool() for GLib.Variant objects
You might consider wrapping g_variant_equal and g_variant_compare as well.
(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 on attachment 185913 [details] [review] Define bool() for GLib.Variant objects Can we get test cases as well? Thanks!
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...
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.
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.
(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.
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.
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.
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.