[pygobject] Fix hash() and __eq__() for GLib.Variant objects



commit 8d6a127df5dd1e5f26faeba8f977074b4496b24f
Author: Nirbheek Chauhan <nirbheek gentoo org>
Date:   Sat Feb 4 15:41:08 2012 +0100

    Fix hash() and __eq__() for GLib.Variant objects
    
    Define __hash__, __eq__, __ne__ for GLib.Variant so that objects can
    be used in sets, dicts, and can be compared using == and != easily.
    
    Also adds some tests for this.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=647725

 gi/overrides/GLib.py    |   23 +++++++++++++++++++
 tests/test_overrides.py |   56 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+), 0 deletions(-)
---
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index f3abe28..a8f8e34 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -277,6 +277,7 @@ class Variant(GLib.Variant):
     def __len__(self):
         if self.get_type_string() in ['s', 'o', 'g']:
             return len(self.get_string())
+        # Array, dict, tuple
         if self.get_type_string().startswith('a') or self.get_type_string().startswith('('):
             return self.n_children()
         raise TypeError('GVariant type %s does not have a length' % self.get_type_string())
@@ -314,6 +315,28 @@ class Variant(GLib.Variant):
 
         raise TypeError('GVariant type %s is not a container' % self.get_type_string())
 
+    #
+    # Pythonic bool operations
+    #
+    def __nonzero__(self):
+        return self.__bool__()
+
+    def __bool__(self):
+        if self.get_type_string() in ['y', 'n', 'q', 'i', 'u', 'x', 't', 'h', 'd']:
+            return self.unpack() != 0
+        if self.get_type_string() in ['b']:
+            return self.get_boolean()
+        if self.get_type_string() in ['s', 'o', 'g']:
+            return len(self.get_string()) != 0
+        # Array, dict, tuple
+        if self.get_type_string().startswith('a') or self.get_type_string().startswith('('):
+            return self.n_children() != 0
+        if self.get_type_string() in ['v']:
+            # unpack works recursively, hence bool also works recursively
+            return bool(self.unpack())
+        # Everything else is True
+        return True
+
     def keys(self):
         if not self.get_type_string().startswith('a{'):
             return TypeError, 'GVariant type %s is not a dictionary' % self.get_type_string()
diff --git a/tests/test_overrides.py b/tests/test_overrides.py
index e875d30..5a4d8fd 100644
--- a/tests/test_overrides.py
+++ b/tests/test_overrides.py
@@ -348,6 +348,62 @@ class TestGLib(unittest.TestCase):
         self.assertEqual(GLib.Variant.split_signature('(a{iv}(ii)((ss)a{s(ss)}))'), 
                 ['a{iv}', '(ii)', '((ss)a{s(ss)})'])
 
+    def test_variant_bool(self):
+        # Check if the GVariant bool matches the unpacked Pythonic bool
+
+        def assert_equals_bool(vtype, value):
+            self.assertEqual(bool(GLib.Variant(vtype, value)), bool(value))
+
+        # simple values
+        assert_equals_bool('b', True)
+        assert_equals_bool('b', False)
+
+        numbers = ['y', 'n', 'q', 'i', 'u', 'x', 't', 'h', 'd']
+        for number in numbers:
+            assert_equals_bool(number, 0)
+            assert_equals_bool(number, 1)
+
+        assert_equals_bool('s', '')
+        assert_equals_bool('g', '')
+        assert_equals_bool('s', 'something')
+        assert_equals_bool('o', '/dev/null')
+        assert_equals_bool('g', 'dustybinqhogx')
+
+        # arrays
+        assert_equals_bool('ab', [True])
+        assert_equals_bool('ab', [False])
+        for number in numbers:
+            assert_equals_bool('a'+number, [])
+            assert_equals_bool('a'+number, [0])
+        assert_equals_bool('as', [])
+        assert_equals_bool('as', [''])
+        assert_equals_bool('ao', [])
+        assert_equals_bool('ao', ['/'])
+        assert_equals_bool('ag', [])
+        assert_equals_bool('ag', [''])
+        assert_equals_bool('aai', [[]])
+
+        # tuples
+        assert_equals_bool('()', ())
+        for number in numbers:
+            assert_equals_bool('('+number+')', (0,))
+        assert_equals_bool('(s)', ('',))
+        assert_equals_bool('(o)', ('/',))
+        assert_equals_bool('(g)', ('',))
+        assert_equals_bool('(())', ((),))
+
+        # dictionaries
+        assert_equals_bool('a{si}', {})
+        assert_equals_bool('a{si}', {'': 0})
+
+        # complex types, always True
+        assert_equals_bool('(as)', ([],))
+        assert_equals_bool('a{s(i)}', {'': (0,)})
+
+        # variant types, recursive unpacking
+        assert_equals_bool('v', GLib.Variant('i', 0))
+        assert_equals_bool('v', GLib.Variant('i', 1))
+
 class TestPango(unittest.TestCase):
 
     def test_default_font_description(self):



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]