[pygobject] Start implementing something equivalent to g_variant_new
- From: Tomeu Vizoso <tomeuv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Start implementing something equivalent to g_variant_new
- Date: Thu, 23 Sep 2010 15:18:55 +0000 (UTC)
commit 9714d765a34e246899f11b6792eea3aecce0b7ec
Author: Tomeu Vizoso <tomeu vizoso collabora co uk>
Date: Mon Sep 13 16:36:47 2010 +0200
Start implementing something equivalent to g_variant_new
https://bugzilla.gnome.org/show_bug.cgi?id=629367
gi/gimodule.c | 20 +++++++
gi/overrides/GLib.py | 131 +++++++++++++++++++++++++++++++++++++++++--
gi/pygi-foreign-gvariant.c | 2 +-
tests/test_everything.py | 16 -----
tests/test_overrides.py | 25 ++++++++
5 files changed, 170 insertions(+), 24 deletions(-)
---
diff --git a/gi/gimodule.c b/gi/gimodule.c
index 42b5f3c..89caf4e 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -272,6 +272,25 @@ _wrap_pyg_variant_new_tuple (PyObject *self, PyObject *args)
return py_variant;
}
+static PyObject *
+_wrap_pyg_variant_type_from_string (PyObject *self, PyObject *args)
+{
+ char *type_string;
+ PyObject *py_type;
+ PyObject *py_variant = NULL;
+
+ if (!PyArg_ParseTuple (args, "s:variant_type_from_string",
+ &type_string)) {
+ return NULL;
+ }
+
+ py_type = _pygi_type_import_by_name ("GLib", "VariantType");
+
+ py_variant = _pygi_struct_new ( (PyTypeObject *) py_type, type_string, FALSE);
+
+ return py_variant;
+}
+
static PyMethodDef _gi_functions[] = {
{ "enum_add", (PyCFunction) _wrap_pyg_enum_add, METH_VARARGS | METH_KEYWORDS },
{ "flags_add", (PyCFunction) _wrap_pyg_flags_add, METH_VARARGS | METH_KEYWORDS },
@@ -280,6 +299,7 @@ static PyMethodDef _gi_functions[] = {
{ "register_interface_info", (PyCFunction) _wrap_pyg_register_interface_info, METH_VARARGS },
{ "hook_up_vfunc_implementation", (PyCFunction) _wrap_pyg_hook_up_vfunc_implementation, METH_VARARGS },
{ "variant_new_tuple", (PyCFunction) _wrap_pyg_variant_new_tuple, METH_VARARGS },
+ { "variant_type_from_string", (PyCFunction) _wrap_pyg_variant_type_from_string, METH_VARARGS },
{ NULL, NULL, 0 }
};
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index 7f163f9..78d8c35 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -1,8 +1,7 @@
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
#
-# Copyright (C) 2009 Johan Dahlin <johan gnome org>
-# 2010 Simon van der Linden <svdlinden src gnome org>
+# Copyright (C) 2010 Tomeu Vizoso <tomeu vizoso collabora co uk>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -19,17 +18,135 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
-import ctypes
-
-from ..types import override
from ..importer import modules
-from .._gi import variant_new_tuple
+from .._gi import variant_new_tuple, variant_type_from_string
-GLib = modules['GLib']
+GLib = modules['GLib'].introspection_module
__all__ = []
+class _VariantCreator(object):
+
+ _LEAF_CONSTRUCTORS = {
+ 'b': GLib.Variant.new_boolean,
+ 'y': GLib.Variant.new_byte,
+ 'n': GLib.Variant.new_int16,
+ 'q': GLib.Variant.new_uint16,
+ 'i': GLib.Variant.new_int32,
+ 'u': GLib.Variant.new_uint32,
+ 'x': GLib.Variant.new_int64,
+ 't': GLib.Variant.new_uint64,
+ 'h': GLib.Variant.new_handle,
+ 'd': GLib.Variant.new_double,
+ 's': GLib.Variant.new_string,
+ 'o': GLib.Variant.new_object_path,
+ 'g': GLib.Variant.new_signature,
+ 'v': GLib.Variant.new_variant,
+ }
+
+ def __init__(self, format_string, args):
+ self._format_string = format_string
+ self._args = args
+
+ def create(self):
+ if self._format_string_is_leaf():
+ return self._new_variant_leaf()
+
+ format_char = self._pop_format_char()
+ arg = self._pop_arg()
+
+ if format_char == 'm':
+ raise NotImplementedError()
+ else:
+ builder = GLib.VariantBuilder()
+ if format_char == '(':
+ builder.init(variant_type_from_string('r'))
+ elif format_char == '{':
+ builder.init(variant_type_from_string('{?*}'))
+ else:
+ raise NotImplementedError()
+ format_char = self._pop_format_char()
+ while format_char not in [')', '}']:
+ builder.add_value(Variant(format_char, arg))
+ format_char = self._pop_format_char()
+ if self._args:
+ arg = self._pop_arg()
+ return builder.end()
+
+ def _format_string_is_leaf(self):
+ format_char = self._format_string[0]
+ return not format_char in ['m', '(', '{']
+
+ def _format_string_is_nnp(self):
+ format_char = self._format_string[0]
+ return format_char in ['a', 's', 'o', 'g', '^', '@', '*', '?', 'r',
+ 'v', '&']
+
+ def _new_variant_leaf(self):
+ if self._format_string_is_nnp():
+ return self._new_variant_nnp()
+
+ format_char = self._pop_format_char()
+ arg = self._pop_arg()
+
+ return _VariantCreator._LEAF_CONSTRUCTORS[format_char](arg)
+
+ def _new_variant_nnp(self):
+ format_char = self._pop_format_char()
+ arg = self._pop_arg()
+
+ if format_char == '&':
+ format_char = self._pop_format_char()
+
+ if format_char == 'a':
+ builder = GLib.VariantBuilder()
+ builder.init(variant_type_from_string('a*'))
+
+ element_format_string = self._pop_leaf_format_string()
+
+ if isinstance(arg, dict):
+ for element in arg.items():
+ value = Variant(element_format_string, *element)
+ builder.add_value(value)
+ else:
+ for element in arg:
+ value = Variant(element_format_string, element)
+ builder.add_value(value)
+ return builder.end()
+ elif format_char == '^':
+ raise NotImplementedError()
+ elif format_char == '@':
+ raise NotImplementedError()
+ elif format_char == '*':
+ raise NotImplementedError()
+ elif format_char == 'r':
+ raise NotImplementedError()
+ elif format_char == '?':
+ raise NotImplementedError()
+ else:
+ return _VariantCreator._LEAF_CONSTRUCTORS[format_char](arg)
+
+ def _pop_format_char(self):
+ format_char = self._format_string[0]
+ self._format_string = self._format_string[1:]
+ return format_char
+
+ def _pop_leaf_format_string(self):
+ # FIXME: This will break when the leaf is inside a tuple or dict entry
+ format_string = self._format_string
+ self._format_string = ''
+ return format_string
+
+ def _pop_arg(self):
+ arg = self._args[0]
+ self._args = self._args[1:]
+ return arg
+
class Variant(GLib.Variant):
+ def __new__(cls, format_string, *args):
+ creator = _VariantCreator(format_string, args)
+ return creator.create()
+
def __repr__(self):
return '<GLib.Variant(%s)>' % getattr(self, 'print')(True)
diff --git a/gi/pygi-foreign-gvariant.c b/gi/pygi-foreign-gvariant.c
index 81afaaa..ac16395 100644
--- a/gi/pygi-foreign-gvariant.c
+++ b/gi/pygi-foreign-gvariant.c
@@ -48,7 +48,7 @@ g_variant_from_arg (GITypeInfo *type_info,
GITypeInfo *interface_info = g_type_info_get_interface (type_info);
PyObject *type = _pygi_type_import_by_gi_info (interface_info);
- g_variant_ref (variant);
+ g_variant_ref_sink (variant);
return _pygi_struct_new ( (PyTypeObject *) type, variant, FALSE);
}
diff --git a/tests/test_everything.py b/tests/test_everything.py
index 171ef8d..5bb635c 100644
--- a/tests/test_everything.py
+++ b/tests/test_everything.py
@@ -48,22 +48,6 @@ class TestEverything(unittest.TestCase):
self.assertEquals(surface.get_width(), 10)
self.assertEquals(surface.get_height(), 10)
- def test_gvariant(self):
- variant = GLib.Variant.new_int32(42);
- self.assertTrue(isinstance(variant, GLib.Variant))
- self.assertEquals(variant.get_int32(), 42)
-
- variant = GLib.Variant.new_strv(['mec', 'mac']);
- self.assertTrue(isinstance(variant, GLib.Variant))
- self.assertEquals(variant.get_strv(), ['mec', 'mac'])
-
- variant = GLib.Variant.new_tuple(GLib.Variant.new_string('mec'), GLib.Variant.new_string('mac'))
- self.assertTrue(isinstance(variant, GLib.Variant))
- self.assertTrue(isinstance(variant.get_child_value(0), GLib.Variant))
- self.assertTrue(isinstance(variant.get_child_value(1), GLib.Variant))
- self.assertEquals(variant.get_child_value(0).get_string(), 'mec')
- self.assertEquals(variant.get_child_value(1).get_string(), 'mac')
-
def test_floating(self):
Everything.TestFloating()
diff --git a/tests/test_overrides.py b/tests/test_overrides.py
index 8791f94..b1e3617 100644
--- a/tests/test_overrides.py
+++ b/tests/test_overrides.py
@@ -9,11 +9,36 @@ import unittest
import sys
sys.path.insert(0, "../")
+from gi.repository import GLib
from gi.repository import GObject
from gi.repository import Gdk
from gi.repository import Gtk
import gi.overrides as overrides
+class TestGLib(unittest.TestCase):
+
+ def test_gvariant(self):
+ variant = GLib.Variant('i', 42)
+ self.assertTrue(isinstance(variant, GLib.Variant))
+ self.assertEquals(variant.get_int32(), 42)
+
+ variant = GLib.Variant('(ss)', 'mec', 'mac')
+ self.assertTrue(isinstance(variant, GLib.Variant))
+ self.assertTrue(isinstance(variant.get_child_value(0), GLib.Variant))
+ self.assertTrue(isinstance(variant.get_child_value(1), GLib.Variant))
+ self.assertEquals(variant.get_child_value(0).get_string(), 'mec')
+ self.assertEquals(variant.get_child_value(1).get_string(), 'mac')
+
+ variant = GLib.Variant('a{si}', {'key1': 1, 'key2': 2})
+ self.assertTrue(isinstance(variant, GLib.Variant))
+ self.assertTrue(isinstance(variant.get_child_value(0), GLib.Variant))
+ self.assertTrue(isinstance(variant.get_child_value(1), GLib.Variant))
+ # Looks like order is not preserved
+ self.assertEquals(variant.get_child_value(1).get_child_value(0).get_string(), 'key1')
+ self.assertEquals(variant.get_child_value(1).get_child_value(1).get_int32(), 1)
+ self.assertEquals(variant.get_child_value(0).get_child_value(0).get_string(), 'key2')
+ self.assertEquals(variant.get_child_value(0).get_child_value(1).get_int32(), 2)
+
class TestGdk(unittest.TestCase):
def test_color(self):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]