[pygobject/gsoc2009: 25/160] Add closure support in input arguments
- From: Simon van der Linden <svdlinden src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [pygobject/gsoc2009: 25/160] Add closure support in input arguments
- Date: Fri, 14 Aug 2009 21:24:11 +0000 (UTC)
commit 4a1210ae5e12d65d5e6f0df1d7ca484d69d72efe
Author: Simon van der Linden <simon vanderlinden student uclouvain be>
Date: Mon Jul 6 11:15:22 2009 +0200
Add closure support in input arguments
The input argument must be a Python callable. When passed, it is wrapped
into a PyGClosure.
Add pyg_base_info_from_object.
girepository/bank-argument.c | 115 ++++++++++++++++++++++++++++++-----------
girepository/bank-info.c | 27 ++++++++++
girepository/bank.h | 2 +
tests/test_girepository.py | 19 ++-----
4 files changed, 118 insertions(+), 45 deletions(-)
---
diff --git a/girepository/bank-argument.c b/girepository/bank-argument.c
index 1939e11..95df956 100644
--- a/girepository/bank-argument.c
+++ b/girepository/bank-argument.c
@@ -284,26 +284,52 @@ pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError
interface_info = g_type_info_get_interface(type_info);
interface_info_type = g_base_info_get_type(interface_info);
- if (interface_info_type == GI_INFO_TYPE_ENUM) {
- (void) PyInt_AsLong(object);
- if (PyErr_Occurred()) {
- PyErr_Clear();
- g_base_info_unref(interface_info);
- py_type_name_expected = "int";
- goto check_error_type;
+ switch (interface_info_type) {
+ case GI_INFO_TYPE_ENUM:
+ {
+ (void) PyInt_AsLong(object);
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ py_type_name_expected = "int";
+ goto check_error_type;
+ }
+ /* XXX: What if the value doesn't correspond to any enum field? */
+ break;
}
- /* XXX: What if the value doesn't correspond to any enum field? */
- } else if (interface_info_type == GI_INFO_TYPE_STRUCT || interface_info_type == GI_INFO_TYPE_BOXED) {
- GType gtype;
- GType object_gtype;
+ case GI_INFO_TYPE_STRUCT:
+ case GI_INFO_TYPE_BOXED:
+ {
+ GType gtype;
+
+ gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)interface_info);
+
+ if (g_type_is_a(gtype, G_TYPE_CLOSURE)) {
+ if (!PyCallable_Check(object)) {
+ g_base_info_unref(interface_info);
+ py_type_name_expected = "callable";
+ goto check_error_type;
+ }
+ } else {
+ GIBaseInfo *info;
+
+ info = pyg_base_info_from_object(object);
+ if (info == NULL || !g_base_info_equals(info, interface_info)) {
+ py_type_name_expected = g_base_info_get_name(interface_info);
+ if (info != NULL) {
+ g_base_info_unref(info);
+ }
+ g_base_info_unref(interface_info);
+ goto check_error_type;
+ }
+
+ g_base_info_unref(info);
+ }
- gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)interface_info);
- object_gtype = pyg_type_from_object(object);
- if (object_gtype != gtype) {
- g_base_info_unref(interface_info);
- py_type_name_expected = g_type_name(gtype);
- goto check_error_type;
+ break;
}
+ default:
+ /* TODO: To complete with other types. */
+ g_assert_not_reached();
}
g_base_info_unref(interface_info);
@@ -354,8 +380,6 @@ pyg_argument_from_pyobject(PyObject *object, GITypeInfo *type_info)
{
GArgument arg;
GITypeTag type_tag;
- GIBaseInfo* interface_info;
- GIInfoType interface_type;
type_tag = g_type_info_get_tag((GITypeInfo*)type_info);
switch (type_tag) {
@@ -421,20 +445,49 @@ pyg_argument_from_pyobject(PyObject *object, GITypeInfo *type_info)
arg.v_double = PyFloat_AsDouble(object);
break;
case GI_TYPE_TAG_INTERFACE:
+ {
+ GIBaseInfo* interface_info;
+ GIInfoType interface_info_type;
+
interface_info = g_type_info_get_interface(type_info);
- interface_type = g_base_info_get_type(interface_info);
- if (interface_type == GI_INFO_TYPE_ENUM) {
- arg.v_int = PyInt_AsLong(object);
- } else if (interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) {
- PyObject *py_buffer;
- py_buffer = PyObject_GetAttrString(object, "__buffer__");
- g_assert(py_buffer != NULL);
- (*py_buffer->ob_type->tp_as_buffer->bf_getreadbuffer)(py_buffer, 0, &arg.v_pointer);
- } else if (object == Py_None)
- arg.v_pointer = NULL;
- else
- arg.v_pointer = pygobject_get(object);
+ interface_info_type = g_base_info_get_type(interface_info);
+
+ switch (interface_info_type) {
+ case GI_INFO_TYPE_ENUM:
+ arg.v_int = PyInt_AsLong(object);
+ break;
+ case GI_INFO_TYPE_STRUCT:
+ {
+ GType gtype;
+ PyObject *py_buffer;
+
+ gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)interface_info);
+
+ if (g_type_is_a(gtype, G_TYPE_CLOSURE)) {
+ arg.v_pointer = pyg_closure_new(object, NULL, NULL);
+ break;
+ }
+
+ py_buffer = PyObject_GetAttrString(object, "__buffer__");
+ g_assert(py_buffer != NULL);
+ (*py_buffer->ob_type->tp_as_buffer->bf_getreadbuffer)(py_buffer, 0, &arg.v_pointer);
+
+ break;
+ }
+ case GI_INFO_TYPE_OBJECT:
+ if (object == Py_None) {
+ arg.v_pointer = NULL;
+ break;
+ }
+ arg.v_pointer = pygobject_get(object);
+ break;
+ default:
+ /* TODO: To complete with other types. */
+ g_assert_not_reached();
+ }
+ g_base_info_unref((GIBaseInfo *)interface_info);
break;
+ }
case GI_TYPE_TAG_ARRAY:
{
gsize length;
diff --git a/girepository/bank-info.c b/girepository/bank-info.c
index ed1246c..2a63274 100644
--- a/girepository/bank-info.c
+++ b/girepository/bank-info.c
@@ -266,6 +266,33 @@ pyg_info_new(void *info)
return (PyObject*)self;
}
+GIBaseInfo *
+pyg_base_info_from_object(PyObject *object)
+{
+ PyObject *py_info;
+ GIBaseInfo *info;
+
+ g_return_val_if_fail(object != NULL, NULL);
+
+ py_info = PyObject_GetAttrString(object, "__info__");
+ if (py_info == NULL) {
+ PyErr_Clear();
+ return NULL;
+ }
+ if (!PyObject_TypeCheck(py_info, (PyTypeObject *)&PyGIBaseInfo_Type)) {
+ Py_DECREF(py_info);
+ return NULL;
+ }
+
+ info = ((PyGIBaseInfo *)py_info)->info;
+ g_base_info_ref(info);
+
+ Py_DECREF(py_info);
+
+ return info;
+}
+
+
static PyMethodDef _PyGIBaseInfo_methods[] = {
{ "getName", (PyCFunction)_wrap_g_base_info_get_name, METH_NOARGS },
{ "getType", (PyCFunction)_wrap_g_base_info_get_type, METH_NOARGS },
diff --git a/girepository/bank.h b/girepository/bank.h
index 5808f80..ddda161 100644
--- a/girepository/bank.h
+++ b/girepository/bank.h
@@ -41,6 +41,8 @@ extern PyTypeObject PyGIRepository_Type;
PyObject * pyg_info_new(gpointer info);
+GIBaseInfo* pyg_base_info_from_object(PyObject *object);
+
typedef struct {
PyObject_HEAD
GIBaseInfo *info;
diff --git a/tests/test_girepository.py b/tests/test_girepository.py
index 58b867b..63d9d7c 100644
--- a/tests/test_girepository.py
+++ b/tests/test_girepository.py
@@ -365,20 +365,11 @@ class TestGIEverything(unittest.TestCase):
self.assertEquals(retval[1], '2')
self.assertEquals(retval[2], '3')
-# XXX Currently causes a segfault.
-# def testClosure(self):
-# def someCallback():
-# return 3
-# self.assertEquals(3, Everything.test_closure(someCallback))
-# someLambda = lambda: 3
-# self.assertEquals(3, Everything.test_closure(someLambda))
-
-# def testClosureOneArg(self):
-# def someCallback(arg):
-# return arg
-# self.assertEquals(3, Everything.test_closure_one_arg(someCallback, 3))
-# someLambda = lambda x: x
-# self.assertEquals(3, Everything.test_closure_one_arg(someLambda, 3))
+ def testClosure(self):
+ self.assertEquals(3, Everything.test_closure(lambda: 3))
+
+ def testClosureOneArg(self):
+ self.assertEquals(3, Everything.test_closure_one_arg(lambda x: x, 3))
# def testIntValueArg(self):
# i = Everything.test_int_value_arg(42)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]