[pybank] Fix constructors



commit 5924cb177f79c5de0ff32ee17beecac24155ed44
Author: Tomeu Vizoso <tomeu sugarlabs org>
Date:   Mon May 11 11:53:02 2009 +0200

    Fix constructors
---
 bank/bank-argument.c   |   27 ++++++++---------
 bank/bank-info.c       |   73 ++++++++++++++++++++++++++++++++++++-----------
 bank/btypes.py         |   17 ++---------
 everything_unittest.py |    1 +
 4 files changed, 73 insertions(+), 45 deletions(-)

diff --git a/bank/bank-argument.c b/bank/bank-argument.c
index babb023..e611448 100644
--- a/bank/bank-argument.c
+++ b/bank/bank-argument.c
@@ -83,7 +83,6 @@ pyg_argument_from_pyobject(PyObject *object, GITypeInfo *type_info)
 	    arg.v_pointer = pygobject_get(object);
 	break;
     case GI_TYPE_TAG_ARRAY:
-	g_assert (object == Py_None);
 	arg.v_pointer = NULL;
 	break;
     case GI_TYPE_TAG_ERROR:
@@ -116,20 +115,20 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
         interface_type = g_base_info_get_type(interface_info);
 
         if (interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) {
-	    // Create new struct based on arg->v_pointer
-	    const gchar *module_name = g_base_info_get_namespace(interface_info);
-	    const gchar *type_name = g_base_info_get_name(interface_info);
-	    PyObject *module = PyImport_ImportModule(module_name);
-	    PyObject *tp = PyObject_GetAttrString(module, type_name);
-	    gsize size = g_struct_info_get_size ((GIStructInfo*)type_info);
-	    PyObject *buffer = PyBuffer_FromReadWriteMemory(arg->v_pointer, size);
-	    PyObject *args = Py_BuildValue("(O)", buffer);
+            // Create new struct based on arg->v_pointer
+            const gchar *module_name = g_base_info_get_namespace(interface_info);
+            const gchar *type_name = g_base_info_get_name(interface_info);
+            PyObject *module = PyImport_ImportModule(module_name);
+            PyObject *tp = PyObject_GetAttrString(module, type_name);
+            gsize size = g_struct_info_get_size ((GIStructInfo*)type_info);
+            PyObject *buffer = PyBuffer_FromReadWriteMemory(arg->v_pointer, size);
+            PyObject *args = Py_BuildValue("(O)", buffer);
 
-	    obj = PyObject_Call(tp, args, NULL);
-	    if (obj == NULL)
-		return NULL;
-	    Py_INCREF(obj);
-	    return obj;
+            obj = PyObject_Call(tp, args, NULL);
+            if (obj == NULL)
+                return NULL;
+            Py_INCREF(obj);
+            return obj;
         } else if (interface_type == GI_INFO_TYPE_ENUM) {
             g_warning("pyg_argument_to_pyobject: enums not implemented");
 	    obj = Py_None;
diff --git a/bank/bank-info.c b/bank/bank-info.c
index d85ab09..9f220f3 100644
--- a/bank/bank-info.c
+++ b/bank/bank-info.c
@@ -343,6 +343,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
     gboolean failed;
     GIFunctionInfoFlags flags;
     gboolean is_method;
+    gboolean is_constructor;
     gboolean invoke_ok;
     GITypeInfo *return_info;
     GITypeTag return_tag;
@@ -354,6 +355,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
 
     flags = g_function_info_get_flags((GIFunctionInfo*)self->info);
     is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
+    is_constructor = (flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0;
 
     expected_in_argc = 0;
     expected_out_argc = 0;
@@ -395,7 +397,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
     out_args_pos = 0; /* into out_args */
     argv_pos = 0; /* index into argv */
 
-    if (is_method) {
+    if (is_method && !is_constructor) {
         GIBaseInfo *container = g_base_info_get_container((GIBaseInfo *) self->info);
         GIInfoType type = g_base_info_get_type(container);
 
@@ -404,14 +406,14 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
             PyErr_SetString(PyExc_ValueError, "Calling a method without passing an instance");
             return NULL;
         }
-        if (py_arg == Py_None)
+        if (py_arg == Py_None) {
             in_args[0].v_pointer = NULL;
-        else if (type == GI_INFO_TYPE_STRUCT || type == GI_INFO_TYPE_BOXED) {
-	    PyObject *buffer = PyObject_GetAttrString((PyObject *)py_arg,
-	                                                  "__buffer__");
-	    in_args[0].v_pointer = PyString_AsString(buffer);
+        } else if (type == GI_INFO_TYPE_STRUCT || type == GI_INFO_TYPE_BOXED) {
+            PyObject *buffer = PyObject_GetAttrString((PyObject *)py_arg,
+                                                      "__buffer__");
+            in_args[0].v_pointer = PyString_AsString(buffer);
         } else { /* by fallback is always object */
-	    in_args[0].v_pointer = pygobject_get(py_arg);
+            in_args[0].v_pointer = pygobject_get(py_arg);
         }
         ++in_args_pos;
     }
@@ -434,11 +436,12 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
         }
 
         if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
-            if (is_method)
+            if (is_method || is_constructor)
                 py_arg = PyTuple_GetItem(args, i + 1);
             else
                 py_arg = PyTuple_GetItem(args, i);
-	    GArgument in_value = pyg_argument_from_pyobject(py_arg, g_arg_info_get_type(arg_info));
+
+            GArgument in_value = pyg_argument_from_pyobject(py_arg, g_arg_info_get_type(arg_info));
 
             ++argv_pos;
 
@@ -494,6 +497,42 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
 
     return_tag = g_type_info_get_tag(return_info);
 
+    if (is_constructor) {
+        py_arg = PyTuple_GetItem(args, 0);
+
+        if (return_tag == GI_TYPE_TAG_INTERFACE) {
+            GIBaseInfo *interface_info = g_type_info_get_interface(return_info);
+            GIInfoType interface_type = g_base_info_get_type(interface_info);
+
+            if (interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) {
+                // FIXME: We should reuse this. Perhaps by separating the
+                // wrapper creation from the binding to the wrapper.
+                gsize size = g_struct_info_get_size ((GIStructInfo*)return_info);
+                PyObject *buffer = PyBuffer_FromReadWriteMemory(return_arg.v_pointer, size);
+
+                //PyObject *dict = PyObject_GetDict(py_arg);
+                PyObject_SetAttrString(py_arg, "__buffer__", buffer);
+
+                Py_INCREF(py_arg);
+                return py_arg;
+            } else {
+                PyGObject *self = (PyGObject *) py_arg;
+                if (self->obj != NULL) {
+                    PyErr_SetString(PyExc_ValueError, "Calling constructor on an instance that isn't a GObject");
+                    return NULL;
+                }
+                self->obj = return_arg.v_pointer;
+                g_object_ref(return_arg.v_pointer);
+                pygobject_register_wrapper(py_arg);
+                Py_INCREF(py_arg);
+                return py_arg;
+            }
+        } else {
+            PyErr_SetString(PyExc_NotImplementedError, "");
+            return NULL;
+        }
+    }
+
     retval = NULL;
 
     next_rval = 0; /* index into return_values */
@@ -505,7 +544,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
     return_values = g_newa(PyObject*, n_return_values);
     if (n_return_values > 0) {
         if (return_tag != GI_TYPE_TAG_VOID) {
-	    return_values[next_rval] = pyg_argument_to_pyobject(&return_arg, return_info);
+            return_values[next_rval] = pyg_argument_to_pyobject(&return_arg, return_info);
 
             ++next_rval;
         }
@@ -538,7 +577,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
             g_assert(next_rval < n_return_values);
             g_assert(out_args_pos < expected_out_argc);
 
-	    return_values[next_rval] = pyg_argument_to_pyobject(&out_args[out_args_pos], arg_type_info);
+            return_values[next_rval] = pyg_argument_to_pyobject(&out_args[out_args_pos], arg_type_info);
 
             if (direction == GI_DIRECTION_INOUT)
                 ++in_args_pos;
@@ -557,16 +596,16 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
     g_assert(in_args_pos == expected_in_argc);
 
     if (n_return_values > 0) {
- 	if (n_return_values == 0) {
-	    retval = Py_None;
-	    Py_INCREF(retval);
+        if (n_return_values == 0) {
+            retval = Py_None;
+            Py_INCREF(retval);
         } else if (n_return_values == 1) {
             retval = return_values[0];
         } else {
             retval = PyTuple_New(n_return_values);
-	    for (i = 0; i < n_return_values; i++) {	    
-		PyTuple_SetItem(retval, i, return_values[i]);
-	    }
+            for (i = 0; i < n_return_values; i++) {
+                PyTuple_SetItem(retval, i, return_values[i]);
+            }
         }
     }
 
diff --git a/bank/btypes.py b/bank/btypes.py
index 66f69c0..9f47b0d 100644
--- a/bank/btypes.py
+++ b/bank/btypes.py
@@ -82,6 +82,7 @@ class Callable(object):
             raise NotImplementedError('type checking for tag %d' % tag)
 
     def __call__(self, *args, **kwargs):
+        print '__call__ %r' % (args,)
         infoArgs = list(self.info.getArgs())
         requiredArgs = 0
         for arg in infoArgs:
@@ -89,17 +90,9 @@ class Callable(object):
             if direct in [repo.DIRECTION_IN, repo.DIRECTION_INOUT]:
                 requiredArgs += 1
 
-        obj = None
         is_method = self.info.isMethod() and not self.info.isConstructor()
-        if self.call_type == self.INSTANCE_METHOD:
+        if self.call_type in [self.INSTANCE_METHOD, self.CLASS_METHOD]:
             requiredArgs += 1
-            if self.info.isConstructor():
-                obj = args[0]
-                args = args[1:]
-            elif is_method:
-                obj = args[0]
-        elif self.call_type == self.CLASS_METHOD:
-            args = args[1:]
 
         totalInArgs = len(args) + len(kwargs)
 
@@ -126,7 +119,7 @@ class Callable(object):
                 raise AssertionError(
                     "Invoked constructor %s.%s.%s returned NULL " % (
                     self.__module__, self.className, self.info.getName()))
-
+            print "mec %r" % retval
             return retval
 
         if type(retval).__name__ == 'PyCObject':
@@ -248,10 +241,6 @@ def buildClass(info, bases):
 
     setupConstructors(className, newType, constructors)
 
-    def __init__(self, *args, **kw):
-        pass
-    newType.__init__ = new.instancemethod(__init__, None, newType)
-
     _classDict[fullName] = newType
     
     return newType
diff --git a/everything_unittest.py b/everything_unittest.py
index bfdd9dd..d2bb68a 100644
--- a/everything_unittest.py
+++ b/everything_unittest.py
@@ -269,6 +269,7 @@ class TestGIEverything(unittest.TestCase):
             def __init__(self):
                 Everything.TestObj.__init__(self, 'foo')
         s = TestSubclass()
+        self.assertEquals(s.do_matrix('matrix'), 42)
 
 if __name__ == '__main__':
     unittest.main()



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