[pygobject] [gi] Provide comfortable GSettings API



commit b7f32e4cca0cef201489b55653f96ac64a8f9ab9
Author: Martin Pitt <martin pitt ubuntu com>
Date:   Sat Jan 29 12:20:50 2011 +0100

    [gi] Provide comfortable GSettings API
    
    Make Gio.Settings behave like a dictionary, with transparent conversion from/to
    GVariants. Also provide a more comfortable constructor.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=640838

 gi/overrides/Gio.py              |   54 ++++++++++++++++++++++++++++
 tests/org.gnome.test.gschema.xml |    9 +++++
 tests/test_overrides.py          |   73 ++++++++++++++++++++++++++++++-------
 3 files changed, 122 insertions(+), 14 deletions(-)
---
diff --git a/gi/overrides/Gio.py b/gi/overrides/Gio.py
index 5a6af2f..78affa2 100644
--- a/gi/overrides/Gio.py
+++ b/gi/overrides/Gio.py
@@ -21,6 +21,8 @@
 from ..overrides import override
 from ..importer import modules
 
+from gi.repository import GLib
+
 Gio = modules['Gio']._introspection_module
 
 __all__ = []
@@ -43,3 +45,55 @@ class FileEnumerator(Gio.FileEnumerator):
 
 FileEnumerator = override(FileEnumerator)
 __all__.append('FileEnumerator')
+
+class Settings(Gio.Settings):
+    '''Provide dictionary-like access to GLib.Settings.'''
+
+    def __init__(self, schema, path=None, backend=None):
+        Gio.Settings.__init__(self, schema=schema, backend=backend, path=path)
+
+    def __contains__(self, key):
+        return key in self.list_keys()
+
+    def __len__(self):
+        return len(self.list_keys())
+
+    def __bool__(self):
+        # for "if mysettings" we don't want a dictionary-like test here, just
+        # if the object isn't None
+        return True
+
+    # alias for Python 2.x object protocol
+    __nonzero__ = __bool__
+
+    def __getitem__(self, key):
+        # get_value() aborts the program on an unknown key
+        if not key in self:
+            raise KeyError('unknown key: %r' % (key,))
+
+        return self.get_value(key).unpack()
+
+    def __setitem__(self, key, value):
+        # set_value() aborts the program on an unknown key
+        if not key in self:
+            raise KeyError('unknown key: %r' % (key,))
+
+        # determine type string of this key
+        range = self.get_range(key)
+        type_ = range.get_child_value(0).get_string()
+        v = range.get_child_value(1)
+        if type_ == 'type':
+            # v is boxed empty array, type of its elements is the allowed value type
+            type_str = v.get_child_value(0).get_type_string()
+            assert type_str.startswith('a')
+            type_str = type_str[1:]
+        else:
+            raise NotImplementedError('Cannot handle allowed type range class' + str(type_))
+
+        self.set_value(key, GLib.Variant(type_str, value))
+
+    def keys(self):
+        return self.list_keys()
+
+Settings = override(Settings)
+__all__.append('Settings')
diff --git a/tests/org.gnome.test.gschema.xml b/tests/org.gnome.test.gschema.xml
index 0002e85..221b87a 100644
--- a/tests/org.gnome.test.gschema.xml
+++ b/tests/org.gnome.test.gschema.xml
@@ -13,4 +13,13 @@
 	    <default>[1,2]</default>
 	</key>
     </schema>
+
+    <schema id="org.gnome.nopathtest">
+	<key name="np-int" type="i">
+	    <default>42</default>
+	</key>
+    </schema>
+
+    <schema id="org.gnome.empty" path="/tests/">
+    </schema>
 </schemalist>
diff --git a/tests/test_overrides.py b/tests/test_overrides.py
index 0642dcc..766beaf 100644
--- a/tests/test_overrides.py
+++ b/tests/test_overrides.py
@@ -1234,6 +1234,11 @@ class TestGio(unittest.TestCase):
     def setUp(self):
         os.environ['GSETTINGS_BACKEND'] = 'memory'
         os.environ['GSETTINGS_SCHEMA_DIR'] = os.path.dirname(__file__)
+        self.settings = Gio.Settings('org.gnome.test')
+        # we change the values in the tests, so set them to predictable start
+        # value
+        self.settings.reset('test-string')
+        self.settings.reset('test-array')
 
     def test_file_enumerator(self):
         self.assertEquals(Gio.FileEnumerator, overrides.Gio.FileEnumerator)
@@ -1253,29 +1258,69 @@ class TestGio(unittest.TestCase):
 
         self.assertEquals(iter_info, next_info)
 
-    def test_gsettings(self):
-        settings = Gio.Settings.new('org.gnome.test')
-        
-        self.assert_('test-array' in settings.list_keys())
+    def test_gsettings_native(self):
+        self.assertTrue('test-array' in self.settings.list_keys())
 
         # get various types
-        v = settings.get_value('test-boolean')
+        v = self.settings.get_value('test-boolean')
         self.assertEqual(v.get_boolean(), True)
-        self.assertEqual(settings.get_boolean('test-boolean'), True)
+        self.assertEqual(self.settings.get_boolean('test-boolean'), True)
 
-        v = settings.get_value('test-string')
+        v = self.settings.get_value('test-string')
         self.assertEqual(v.get_string(), 'Hello')
-        self.assertEqual(settings.get_string('test-string'), 'Hello')
+        self.assertEqual(self.settings.get_string('test-string'), 'Hello')
 
-        v = settings.get_value('test-array')
+        v = self.settings.get_value('test-array')
         self.assertEqual(v.unpack(), [1, 2])
 
-        v = settings.get_value('test-tuple')
+        v = self.settings.get_value('test-tuple')
         self.assertEqual(v.unpack(), (1, 2))
 
         # set a value
-        settings.set_string('test-string', 'World')
-        self.assertEqual(settings.get_string('test-string'), 'World')
+        self.settings.set_string('test-string', 'World')
+        self.assertEqual(self.settings.get_string('test-string'), 'World')
+
+        self.settings.set_value('test-string', GLib.Variant('s', 'Goodbye'))
+        self.assertEqual(self.settings.get_string('test-string'), 'Goodbye')
+
+    def test_gsettings_constructor(self):
+        # default constructor uses path from schema
+        self.assertEqual(self.settings.get_property('path'), '/tests/')
+
+        # optional constructor arguments
+        with_path = Gio.Settings('org.gnome.nopathtest', path='/mypath/')
+        self.assertEqual(with_path.get_property('path'), '/mypath/')
+        self.assertEqual(with_path['np-int'], 42)
+
+    def test_gsettings_override(self):
+        # dictionary interface
+        self.assertEqual(len(self.settings), 4)
+        self.assertTrue('test-array' in self.settings)
+        self.assertTrue('test-array' in self.settings.keys())
+        self.failIf('nonexisting' in self.settings)
+        self.failIf(4 in self.settings)
+        self.assertEqual(bool(self.settings), True)
 
-        settings.set_value('test-string', GLib.Variant('s', 'Goodbye'))
-        self.assertEqual(settings.get_string('test-string'), 'Goodbye')
+        # get various types
+        self.assertEqual(self.settings['test-boolean'], True)
+        self.assertEqual(self.settings['test-string'], 'Hello')
+        self.assertEqual(self.settings['test-array'], [1, 2])
+        self.assertEqual(self.settings['test-tuple'], (1, 2))
+
+        self.assertRaises(KeyError, self.settings.__getitem__, 'unknown')
+        self.assertRaises(KeyError, self.settings.__getitem__, 2)
+
+        # set a value
+        self.settings['test-string'] = 'Goodbye'
+        self.assertEqual(self.settings['test-string'], 'Goodbye')
+        self.settings['test-array'] = [3, 4, 5]
+        self.assertEqual(self.settings['test-array'], [3, 4, 5])
+
+        self.assertRaises(TypeError, self.settings.__setitem__, 'test-string', 1)
+        self.assertRaises(KeyError, self.settings.__setitem__, 'unknown', 'moo')
+
+    def test_gsettings_empty(self):
+        empty = Gio.Settings('org.gnome.empty', path='/tests/')
+        self.assertEqual(len(empty), 0)
+        self.assertEqual(bool(empty), True)
+        self.assertEqual(empty.keys(), [])



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