[pygi] Add basic support for unions
- From: Tomeu Vizoso <tomeuv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygi] Add basic support for unions
- Date: Fri, 23 Apr 2010 14:33:33 +0000 (UTC)
commit 3ba666b7ab9c393963922c272e7d87bff50a93f9
Author: Tomeu Vizoso <tomeu sugarlabs org>
Date: Sat Jan 2 16:31:55 2010 +0100
Add basic support for unions
https://bugzilla.gnome.org/show_bug.cgi?id=603598
gi/module.py | 3 +-
gi/pygi-argument.c | 24 +++----------
gi/pygi-boxed.c | 18 +++++++++-
gi/pygi-info.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++-----
gi/pygi-info.h | 1 +
tests/test_gi.py | 56 +++++++++++++++++++++++++++++++
6 files changed, 165 insertions(+), 31 deletions(-)
---
diff --git a/gi/module.py b/gi/module.py
index 2d5a8cc..3afdc18 100644
--- a/gi/module.py
+++ b/gi/module.py
@@ -34,6 +34,7 @@ from ._gi import \
InterfaceInfo, \
ConstantInfo, \
StructInfo, \
+ UnionInfo, \
Struct, \
Boxed, \
enum_add, \
@@ -125,7 +126,7 @@ class DynamicModule(object):
elif isinstance(info, InterfaceInfo):
bases = (gobject.GInterface,)
metaclass = GObjectMeta
- elif isinstance(info, StructInfo):
+ elif isinstance(info, (StructInfo, UnionInfo)):
if g_type.is_a(gobject.TYPE_BOXED):
bases = (Boxed,)
elif g_type.is_a(gobject.TYPE_POINTER) or g_type == gobject.TYPE_NONE:
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 8244659..57547a0 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -441,11 +441,8 @@ check_number_release:
case GI_INFO_TYPE_BOXED:
case GI_INFO_TYPE_INTERFACE:
case GI_INFO_TYPE_OBJECT:
- retval = _pygi_g_registered_type_info_check_object((GIRegisteredTypeInfo *)info, TRUE, object);
- break;
case GI_INFO_TYPE_UNION:
- /* TODO */
- PyErr_SetString(PyExc_NotImplementedError, "union marshalling is not supported yet");
+ retval = _pygi_g_registered_type_info_check_object((GIRegisteredTypeInfo *)info, TRUE, object);
break;
default:
g_assert_not_reached();
@@ -910,6 +907,7 @@ array_item_error:
break;
case GI_INFO_TYPE_BOXED:
case GI_INFO_TYPE_STRUCT:
+ case GI_INFO_TYPE_UNION:
{
GType type;
@@ -1005,10 +1003,6 @@ array_item_error:
}
break;
- case GI_INFO_TYPE_UNION:
- PyErr_SetString(PyExc_NotImplementedError, "union marshalling is not supported yet");
- /* TODO */
- break;
default:
g_assert_not_reached();
}
@@ -1445,6 +1439,7 @@ _pygi_argument_to_object (GArgument *arg,
}
case GI_INFO_TYPE_BOXED:
case GI_INFO_TYPE_STRUCT:
+ case GI_INFO_TYPE_UNION:
{
GType type;
@@ -1461,11 +1456,8 @@ _pygi_argument_to_object (GArgument *arg,
PyObject *py_type;
py_type = _pygi_type_get_from_g_type(type);
- if (py_type == NULL) {
- PyErr_Format(PyExc_ValueError, "couldn't find a wrapper for type '%s'",
- g_type_name(type));
+ if (py_type == NULL)
break;
- }
object = _pygi_boxed_new((PyTypeObject *)py_type, arg->v_pointer, transfer == GI_TRANSFER_EVERYTHING);
@@ -1547,10 +1539,6 @@ _pygi_argument_to_object (GArgument *arg,
}
object = pygobject_new(arg->v_pointer);
break;
- case GI_INFO_TYPE_UNION:
- /* TODO */
- PyErr_SetString(PyExc_NotImplementedError, "union marshalling is not supported yet");
- break;
default:
g_assert_not_reached();
}
@@ -1769,6 +1757,7 @@ _pygi_argument_release (GArgument *arg,
break;
case GI_INFO_TYPE_BOXED:
case GI_INFO_TYPE_STRUCT:
+ case GI_INFO_TYPE_UNION:
{
GType type;
@@ -1819,9 +1808,6 @@ _pygi_argument_release (GArgument *arg,
g_object_unref(arg->v_pointer);
}
break;
- case GI_INFO_TYPE_UNION:
- /* TODO */
- break;
default:
g_assert_not_reached();
}
diff --git a/gi/pygi-boxed.c b/gi/pygi-boxed.c
index b157eb8..c320796 100644
--- a/gi/pygi-boxed.c
+++ b/gi/pygi-boxed.c
@@ -63,7 +63,7 @@ _boxed_new (PyTypeObject *type,
return NULL;
}
- info = _pygi_object_get_gi_info((PyObject *)type, &PyGIStructInfo_Type);
+ info = _pygi_object_get_gi_info((PyObject *)type, &PyGIBaseInfo_Type);
if (info == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Format(PyExc_TypeError, "missing introspection information");
@@ -71,7 +71,21 @@ _boxed_new (PyTypeObject *type,
return NULL;
}
- size = g_struct_info_get_size((GIStructInfo *)info);
+ switch (g_base_info_get_type(info)) {
+ case GI_INFO_TYPE_UNION:
+ size = g_union_info_get_size((GIUnionInfo *)info);
+ break;
+ case GI_INFO_TYPE_BOXED:
+ case GI_INFO_TYPE_STRUCT:
+ size = g_struct_info_get_size((GIStructInfo *)info);
+ break;
+ default:
+ PyErr_Format(PyExc_TypeError,
+ "info should be Boxed or Union, not '%d'",
+ g_base_info_get_type(info));
+ return NULL;
+ }
+
boxed = g_slice_alloc0(size);
if (boxed == NULL) {
PyErr_NoMemory();
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index 504bdac..59c99fa 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -204,8 +204,8 @@ _pygi_info_new (GIBaseInfo *info)
PyErr_SetString(PyExc_NotImplementedError, "GIErrorDomainInfo bindings not implemented");
return NULL;
case GI_INFO_TYPE_UNION:
- PyErr_SetString(PyExc_NotImplementedError, "GIUnionInfo bindings not implemented");
- return NULL;
+ type = &PyGIUnionInfo_Type;
+ break;
case GI_INFO_TYPE_VALUE:
type = &PyGIValueInfo_Type;
break;
@@ -792,9 +792,6 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
switch(container_info_type) {
case GI_INFO_TYPE_UNION:
- PyErr_SetString(PyExc_NotImplementedError, "calling methods on unions is not supported yet.");
- goto out;
- break;
case GI_INFO_TYPE_STRUCT:
{
GType type;
@@ -1931,8 +1928,6 @@ _wrap_g_field_info_get_value (PyGIBaseInfo *self,
container_info_type = g_base_info_get_type(container_info);
switch (container_info_type) {
case GI_INFO_TYPE_UNION:
- PyErr_SetString(PyExc_NotImplementedError, "getting a field from an union is not supported yet");
- return NULL;
case GI_INFO_TYPE_STRUCT:
pointer = pyg_boxed_get(instance, void);
break;
@@ -2028,8 +2023,6 @@ _wrap_g_field_info_set_value (PyGIBaseInfo *self,
container_info_type = g_base_info_get_type(container_info);
switch (container_info_type) {
case GI_INFO_TYPE_UNION:
- PyErr_SetString(PyExc_NotImplementedError, "setting a field in an union is not supported yet");
- return NULL;
case GI_INFO_TYPE_STRUCT:
pointer = pyg_boxed_get(instance, void);
break;
@@ -2159,6 +2152,88 @@ static PyMethodDef _PyGIVFuncInfo_methods[] = {
{ NULL, NULL, 0 }
};
+
+/* GIUnionInfo */
+_PyGI_DEFINE_INFO_TYPE("UnionInfo", GIUnionInfo, PyGIRegisteredTypeInfo_Type);
+
+static PyObject *
+_wrap_g_union_info_get_fields (PyGIBaseInfo *self)
+{
+ gssize n_infos;
+ PyObject *infos;
+ gssize i;
+
+ n_infos = g_union_info_get_n_fields((GIUnionInfo *)self->info);
+
+ infos = PyTuple_New(n_infos);
+ if (infos == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < n_infos; i++) {
+ GIBaseInfo *info;
+ PyObject *py_info;
+
+ info = (GIBaseInfo *)g_union_info_get_field((GIUnionInfo *)self->info, i);
+ g_assert(info != NULL);
+
+ py_info = _pygi_info_new(info);
+
+ g_base_info_unref(info);
+
+ if (py_info == NULL) {
+ Py_CLEAR(infos);
+ break;
+ }
+
+ PyTuple_SET_ITEM(infos, i, py_info);
+ }
+
+ return infos;
+}
+
+static PyObject *
+_wrap_g_union_info_get_methods (PyGIBaseInfo *self)
+{
+ gssize n_infos;
+ PyObject *infos;
+ gssize i;
+
+ n_infos = g_union_info_get_n_methods((GIUnionInfo *)self->info);
+
+ infos = PyTuple_New(n_infos);
+ if (infos == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < n_infos; i++) {
+ GIBaseInfo *info;
+ PyObject *py_info;
+
+ info = (GIBaseInfo *)g_union_info_get_method((GIUnionInfo *)self->info, i);
+ g_assert(info != NULL);
+
+ py_info = _pygi_info_new(info);
+
+ g_base_info_unref(info);
+
+ if (py_info == NULL) {
+ Py_CLEAR(infos);
+ break;
+ }
+
+ PyTuple_SET_ITEM(infos, i, py_info);
+ }
+
+ return infos;
+}
+
+static PyMethodDef _PyGIUnionInfo_methods[] = {
+ { "get_fields", (PyCFunction)_wrap_g_union_info_get_fields, METH_NOARGS },
+ { "get_methods", (PyCFunction)_wrap_g_union_info_get_methods, METH_NOARGS },
+ { NULL, NULL, 0 }
+};
+
/* Private */
gchar *
@@ -2209,6 +2284,7 @@ _pygi_info_register_types (PyObject *m)
_PyGI_REGISTER_TYPE(m, PyGIValueInfo_Type, "ValueInfo");
_PyGI_REGISTER_TYPE(m, PyGIFieldInfo_Type, "FieldInfo");
_PyGI_REGISTER_TYPE(m, PyGIVFuncInfo_Type, "VFuncInfo");
+ _PyGI_REGISTER_TYPE(m, PyGIUnionInfo_Type, "UnionInfo");
#undef _PyGI_REGISTER_TYPE
}
diff --git a/gi/pygi-info.h b/gi/pygi-info.h
index fe02d1a..0d2bade 100644
--- a/gi/pygi-info.h
+++ b/gi/pygi-info.h
@@ -46,6 +46,7 @@ extern PyTypeObject PyGIValueInfo_Type;
extern PyTypeObject PyGIFieldInfo_Type;
extern PyTypeObject PyGIUnresolvedInfo_Type;
extern PyTypeObject PyGIVFuncInfo_Type;
+extern PyTypeObject PyGIUnionInfo_Type;
#define PyGIBaseInfo_GET_GI_INFO(object) g_base_info_ref(((PyGIBaseInfo *)object)->info)
diff --git a/tests/test_gi.py b/tests/test_gi.py
index 0930d7c..7cab5db 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -1193,6 +1193,62 @@ class TestStructure(unittest.TestCase):
del in_struct
del out_struct
+ def test_union(self):
+ union = GIMarshallingTests.Union()
+
+ self.assertTrue(isinstance(union, GIMarshallingTests.Union))
+
+ new_union = union.copy()
+ self.assertTrue(isinstance(new_union, GIMarshallingTests.Union))
+
+ del union
+ del new_union
+
+ def test_union_return(self):
+ union = GIMarshallingTests.union_return()
+
+ self.assertTrue(isinstance(union, GIMarshallingTests.Union))
+ self.assertEquals(42, union.long_)
+
+ del union
+
+ def test_union_in(self):
+ union = GIMarshallingTests.Union()
+ union.long_ = 42
+
+ GIMarshallingTests.union_in(union)
+
+ del union
+
+ def test_union_out(self):
+ union = GIMarshallingTests.union_out()
+
+ self.assertTrue(isinstance(union, GIMarshallingTests.Union))
+ self.assertEquals(42, union.long_)
+
+ del union
+
+ def test_union_inout(self):
+ in_union = GIMarshallingTests.Union()
+ in_union.long_ = 42
+
+ out_union = GIMarshallingTests.union_inout(in_union)
+
+ self.assertTrue(isinstance(out_union, GIMarshallingTests.Union))
+ self.assertEquals(0, out_union.long_)
+
+ del in_union
+ del out_union
+
+ def test_union_method(self):
+ union = GIMarshallingTests.Union()
+ union.long_ = 42
+
+ union.method()
+
+ del union
+
+ self.assertRaises(TypeError, GIMarshallingTests.Union.method)
class TestGObject(unittest.TestCase):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]