diff options
| author | Tomeu Vizoso <tomeu@sugarlabs.org> | 2010-01-02 16:31:55 +0100 |
|---|---|---|
| committer | Tomeu Vizoso <tomeu@sugarlabs.org> | 2010-04-23 16:33:19 +0200 |
| commit | 3ba666b7ab9c393963922c272e7d87bff50a93f9 (patch) | |
| tree | 8c463f92c7cc65153dd5e7f8fb5604a7d3901378 | |
| parent | af9e4e086d160fe7fb24758ed81753e784b198a8 (diff) | |
| download | pygobject-3ba666b7ab9c393963922c272e7d87bff50a93f9.tar.gz | |
Add basic support for unions
https://bugzilla.gnome.org/show_bug.cgi?id=603598
| -rw-r--r-- | gi/module.py | 3 | ||||
| -rw-r--r-- | gi/pygi-argument.c | 24 | ||||
| -rw-r--r-- | gi/pygi-boxed.c | 18 | ||||
| -rw-r--r-- | gi/pygi-info.c | 94 | ||||
| -rw-r--r-- | gi/pygi-info.h | 1 | ||||
| -rw-r--r-- | tests/test_gi.py | 56 |
6 files changed, 165 insertions, 31 deletions
diff --git a/gi/module.py b/gi/module.py index 2d5a8ccf..3afdc187 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 8244659a..57547a09 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 b157eb88..c3207969 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 504bdac6..59c99fae 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 fe02d1a2..0d2bade3 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 0930d7cc..7cab5db8 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): |
