[pygobject] Support union creation with PyGIStruct



commit aaaead18e2167c2becb309f1d9ae199222c0256b
Author: Simon Feltman <sfeltman src gnome org>
Date:   Sat Jan 4 16:31:56 2014 -0800

    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.

 gi/pygi-struct.c         |   39 ++++++++++++++++++++++++++++++++++-----
 tests/test_repository.py |   13 +++++++++++++
 2 files changed, 47 insertions(+), 5 deletions(-)
---
diff --git a/gi/pygi-struct.c b/gi/pygi-struct.c
index 38f6a8a..296c47c 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 20602ba..c02581c 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()


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