summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Feltman <sfeltman@src.gnome.org>2014-01-04 16:31:56 -0800
committerSimon Feltman <sfeltman@src.gnome.org>2014-01-04 17:10:29 -0800
commitaaaead18e2167c2becb309f1d9ae199222c0256b (patch)
tree37713bbc05ad12134f4e7b949357c3ee16fdc096
parent64f15961b637a7e1388bd8d2cd08f04fa20e4de4 (diff)
downloadpygobject-aaaead18e2167c2becb309f1d9ae199222c0256b.tar.gz
Support union creation with PyGIStruct
Add additional case for allowing the creation bare unions wrapped with PyGIStruct. This is needed because PyGIStruct wraps both GIStruct and GIUnion types.
-rw-r--r--gi/pygi-struct.c39
-rw-r--r--tests/test_repository.py13
2 files changed, 47 insertions, 5 deletions
diff --git a/gi/pygi-struct.c b/gi/pygi-struct.c
index 38f6a8ae..296c47c0 100644
--- a/gi/pygi-struct.c
+++ b/gi/pygi-struct.c
@@ -27,12 +27,39 @@
#include <girepository.h>
#include <pyglib-python-compat.h>
+
+static GIBaseInfo *
+_struct_get_info (PyObject *self)
+{
+ PyObject *py_info;
+ GIBaseInfo *info = NULL;
+
+ py_info = PyObject_GetAttrString (self, "__info__");
+ if (py_info == NULL) {
+ return NULL;
+ }
+ if (!PyObject_TypeCheck (py_info, &PyGIStructInfo_Type) &&
+ !PyObject_TypeCheck (py_info, &PyGIUnionInfo_Type)) {
+ PyErr_Format (PyExc_TypeError, "attribute '__info__' must be %s or %s, not %s",
+ PyGIStructInfo_Type.tp_name,
+ PyGIUnionInfo_Type.tp_name,
+ Py_TYPE(py_info)->tp_name);
+ goto out;
+ }
+
+ info = ( (PyGIBaseInfo *) py_info)->info;
+ g_base_info_ref (info);
+
+out:
+ Py_DECREF (py_info);
+
+ return info;
+}
+
static void
_struct_dealloc (PyGIStruct *self)
{
- GIBaseInfo *info = _pygi_object_get_gi_info (
- (PyObject *) self,
- &PyGIStructInfo_Type);
+ GIBaseInfo *info = _struct_get_info ( (PyObject *) self );
if (info != NULL && g_struct_info_is_foreign ( (GIStructInfo *) info)) {
pygi_struct_foreign_release (info, ( (PyGPointer *) self)->pointer);
@@ -40,7 +67,9 @@ _struct_dealloc (PyGIStruct *self)
g_free ( ( (PyGPointer *) self)->pointer);
}
- g_base_info_unref (info);
+ if (info != NULL) {
+ g_base_info_unref (info);
+ }
Py_TYPE( (PyGPointer *) self )->tp_free ( (PyObject *) self);
}
@@ -61,7 +90,7 @@ _struct_new (PyTypeObject *type,
return NULL;
}
- info = _pygi_object_get_gi_info ( (PyObject *) type, &PyGIStructInfo_Type);
+ info = _struct_get_info ( (PyObject *) type );
if (info == NULL) {
if (PyErr_ExceptionMatches (PyExc_AttributeError)) {
PyErr_Format (PyExc_TypeError, "missing introspection information");
diff --git a/tests/test_repository.py b/tests/test_repository.py
index 20602ba1..c02581cc 100644
--- a/tests/test_repository.py
+++ b/tests/test_repository.py
@@ -28,6 +28,7 @@ from gi.module import repository as repo
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import GIMarshallingTests
+from gi.repository import GIRepository as IntrospectedRepository
try:
import cairo
@@ -338,6 +339,18 @@ class Test(unittest.TestCase):
self.assertTrue(hasattr(GIRepository, 'TypeTag'))
self.assertTrue(hasattr(GIRepository, 'InfoType'))
+ def test_introspected_argument_info(self):
+ self.assertTrue(isinstance(IntrospectedRepository.Argument.__info__,
+ GIRepository.UnionInfo))
+
+ arg = IntrospectedRepository.Argument()
+ self.assertTrue(isinstance(arg.__info__, GIRepository.UnionInfo))
+
+ old_info = IntrospectedRepository.Argument.__info__
+ IntrospectedRepository.Argument.__info__ = 'not an info'
+ self.assertRaises(TypeError, IntrospectedRepository.Argument)
+ IntrospectedRepository.Argument.__info__ = old_info
+
if __name__ == '__main__':
unittest.main()