[pygobject/gsoc2009: 20/160] Add array support in function calls from Python
- From: Simon van der Linden <svdlinden src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [pygobject/gsoc2009: 20/160] Add array support in function calls from Python
- Date: Fri, 14 Aug 2009 21:23:46 +0000 (UTC)
commit 1311524ee6a0fcf4e52143f152fb3ee9c325ddc3
Author: Simon van der Linden <svdlinden src gnome org>
Date: Fri Jul 10 17:21:48 2009 +0200
Add array support in function calls from Python
Complete checks in pyg_argument_from_pyobject_check.
Add pyg_array_from_pyobject and refactore pyg_array_to_pyobject.
Add auxiliary argument support in _wrap_g_function_info_invoke.
Add most test_array_* and test_strv_* from Everything.
girepository/bank-argument.c | 206 ++++++++++++++++++++++++++++++-------
girepository/bank-info.c | 234 ++++++++++++++++++++++++++++++++++--------
girepository/bank.h | 7 +-
tests/test_girepository.py | 107 ++++++++++++++------
4 files changed, 441 insertions(+), 113 deletions(-)
---
diff --git a/girepository/bank-argument.c b/girepository/bank-argument.c
index 9f4d058..1939e11 100644
--- a/girepository/bank-argument.c
+++ b/girepository/bank-argument.c
@@ -20,6 +20,7 @@
#include "bank.h"
#include <pygobject.h>
+#include <string.h>
GQuark
pyg_argument_from_pyobject_error_quark(void)
@@ -234,7 +235,11 @@ pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError
break;
case GI_TYPE_TAG_ARRAY:
{
- gint size;
+ gssize size;
+ gssize required_size;
+ Py_ssize_t object_size;
+ GITypeInfo *item_type_info;
+ gsize i;
if (!PyTuple_Check(object)) {
py_type_name_expected = "tuple";
@@ -242,14 +247,32 @@ pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError
}
size = g_type_info_get_array_fixed_size(type_info);
- if (size != -1 && PyTuple_Size(object) != size) {
- /* FIXME: Set another more appropriate error. */
- g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE, "FIXME");
+ required_size = g_type_info_get_array_fixed_size(type_info);
+ object_size = PyTuple_Size(object);
+ if (required_size != -1 && object_size != required_size) {
+ g_set_error(error, PyG_ARGUMENT_FROM_PYOBJECT_ERROR, PyG_ARGUMENT_FROM_PYOBJECT_ERROR_SIZE,
+ "Must contain %zd items, not %zd", required_size, object_size);
retval = FALSE;
break;
}
- /* TODO: to complete */
+ item_type_info = g_type_info_get_param_type(type_info, 0);
+
+ for (i = 0; i < object_size; i++) {
+ PyObject *item;
+
+ item = PyTuple_GetItem(object, i);
+ g_assert(item != NULL);
+
+ g_assert(error == NULL || *error == NULL);
+ if (!pyg_argument_from_pyobject_check(item, item_type_info, error)) {
+ g_prefix_error(error, "Item %zu: ", i);
+ retval = FALSE;
+ break;
+ }
+ }
+
+ g_base_info_unref((GIBaseInfo *)item_type_info);
break;
}
@@ -413,8 +436,11 @@ pyg_argument_from_pyobject(PyObject *object, GITypeInfo *type_info)
arg.v_pointer = pygobject_get(object);
break;
case GI_TYPE_TAG_ARRAY:
- arg.v_pointer = NULL;
+ {
+ gsize length;
+ arg.v_pointer = pyg_array_from_pyobject(object, type_info, &length);
break;
+ }
case GI_TYPE_TAG_ERROR:
/* Allow NULL GError, otherwise fall through */
if (object == Py_None) {
@@ -483,51 +509,159 @@ glist_to_pyobject(GITypeTag list_tag, GITypeInfo *type_info, GList *list, GSList
return py_list;
}
-PyObject *
-pyarray_to_pyobject(gpointer array, int length, GITypeInfo *type_info)
+static
+gsize
+pyg_type_get_size(GITypeTag type_tag)
{
- PyObject *py_list;
- PyObject *child_obj;
- GITypeInfo *element_type = g_type_info_get_param_type (type_info, 0);
- GITypeTag type_tag = g_type_info_get_tag(element_type);
gsize size;
- char buf[256];
- int i;
- if (array == NULL)
- return Py_None;
+ switch(type_tag) {
+ case GI_TYPE_TAG_VOID:
+ size = sizeof(void);
+ break;
+ case GI_TYPE_TAG_BOOLEAN:
+ size = sizeof(gboolean);
+ break;
+ case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_UINT:
+ size = sizeof(gint);
+ break;
+ case GI_TYPE_TAG_INT8:
+ case GI_TYPE_TAG_UINT8:
+ size = sizeof(gint8);
+ break;
+ case GI_TYPE_TAG_INT16:
+ case GI_TYPE_TAG_UINT16:
+ size = sizeof(gint16);
+ break;
+ case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_UINT32:
+ size = sizeof(gint32);
+ break;
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64:
+ size = sizeof(gint64);
+ break;
+ case GI_TYPE_TAG_LONG:
+ case GI_TYPE_TAG_ULONG:
+ size = sizeof(glong);
+ break;
+ case GI_TYPE_TAG_SIZE:
+ case GI_TYPE_TAG_SSIZE:
+ size = sizeof(gsize);
+ break;
+ case GI_TYPE_TAG_FLOAT:
+ size = sizeof(gfloat);
+ break;
+ case GI_TYPE_TAG_DOUBLE:
+ size = sizeof(gdouble);
+ break;
+ case GI_TYPE_TAG_UTF8:
+ size = sizeof(gchar *);
+ break;
+ default:
+ /* TODO: Complete with other types */
+ g_assert_not_reached();
+ }
+
+ return size;
+}
- // FIXME: Doesn't seem right to have this here:
- switch (type_tag) {
- case GI_TYPE_TAG_INT:
- size = sizeof(int);
- break;
- case GI_TYPE_TAG_INTERFACE:
- size = sizeof(gpointer);
- break;
- default:
- snprintf(buf, sizeof(buf), "Unimplemented type: %s\n", g_type_tag_to_string(type_tag));
- PyErr_SetString(PyExc_TypeError, buf);
+gpointer
+pyg_array_from_pyobject(PyObject *object, GITypeInfo *type_info, gsize *length)
+{
+ gpointer items;
+ gpointer current_item;
+ gssize item_size;
+ gboolean is_zero_terminated;
+ GITypeInfo *item_type_info;
+ GITypeTag type_tag;
+ gsize i;
+
+ is_zero_terminated = g_type_info_is_zero_terminated(type_info);
+ item_type_info = g_type_info_get_param_type(type_info, 0);
+
+ type_tag = g_type_info_get_tag(item_type_info);
+ item_size = pyg_type_get_size(type_tag);
+
+ *length = PyTuple_Size(object);
+ items = g_try_malloc(*length * (item_size + (is_zero_terminated ? 1 : 0)));
+
+ if (items == NULL) {
+ g_base_info_unref((GIBaseInfo *)item_type_info);
return NULL;
}
- if ((py_list = PyList_New(0)) == NULL) {
+ current_item = items;
+ for (i = 0; i < *length; i++) {
+ GArgument arg;
+ PyObject *py_item;
+
+ py_item = PyTuple_GetItem(object, i);
+ g_assert(py_item != NULL);
+
+ arg = pyg_argument_from_pyobject(py_item, item_type_info);
+
+ g_memmove(current_item, &arg, item_size);
+
+ current_item += item_size;
+ }
+
+ if (is_zero_terminated) {
+ memset(current_item, 0, item_size);
+ }
+
+ g_base_info_unref((GIBaseInfo *)item_type_info);
+
+ return items;
+}
+
+PyObject *
+pyg_array_to_pyobject(gpointer items, gsize length, GITypeInfo *type_info)
+{
+ PyObject *py_items;
+ gsize item_size;
+ GITypeInfo *item_type_info;
+ GITypeTag type_tag;
+ gsize i;
+ gpointer current_item;
+
+ if (g_type_info_is_zero_terminated(type_info)) {
+ length = g_strv_length(items);
+ }
+
+ py_items = PyTuple_New(length);
+ if (py_items == NULL) {
return NULL;
}
- for( i = 0; i < length; i++ ) {
- gpointer current_element = array + i * size;
+ item_type_info = g_type_info_get_param_type (type_info, 0);
+ type_tag = g_type_info_get_tag(item_type_info);
+ item_size = pyg_type_get_size(type_tag);
+
+ current_item = items;
+ for(i = 0; i < length; i++) {
+ PyObject *item;
+ int retval;
- child_obj = pyg_argument_to_pyobject((GArgument *)¤t_element, element_type);
- if (child_obj == NULL) {
- Py_DECREF(py_list);
+ item = pyg_argument_to_pyobject((GArgument *)current_item, item_type_info);
+ if (item == NULL) {
+ g_base_info_unref((GIBaseInfo *)item_type_info);
+ Py_DECREF(py_items);
return NULL;
}
- PyList_Append(py_list, child_obj);
- Py_DECREF(child_obj);
+
+ retval = PyTuple_SetItem(py_items, i, item);
+ if (retval) {
+ g_base_info_unref((GIBaseInfo *)item_type_info);
+ Py_DECREF(py_items);
+ return NULL;
+ }
+
+ current_item += item_size;
}
- return py_list;
+ return py_items;
}
PyObject *
diff --git a/girepository/bank-info.c b/girepository/bank-info.c
index 652b1f8..ed1246c 100644
--- a/girepository/bank-info.c
+++ b/girepository/bank-info.c
@@ -335,6 +335,8 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
guint n_in_args;
guint n_out_args;
Py_ssize_t n_py_args;
+ gsize n_aux_in_args;
+ gsize n_aux_out_args;
guint n_return_values;
GICallableInfo *callable_info;
@@ -343,6 +345,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
GArgument *in_args;
GArgument *out_args;
+ GArgument **aux_args;
GArgument *out_values;
GArgument return_arg;
PyObject *return_value;
@@ -364,14 +367,23 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
n_py_args = PyTuple_Size(args);
n_in_args = is_method ? 1 : 0; /* The first argument is the instance. */
n_out_args = 0;
+ n_aux_in_args = 0;
+ n_aux_out_args = 0;
+ aux_args = g_newa(GArgument *, n_args);
for (i = 0; i < n_args; i++) {
GIDirection direction;
GIArgInfo *arg_info;
+ GITypeInfo *arg_type_info;
+ GITypeTag arg_type_tag;
arg_info = g_callable_info_get_arg(callable_info, i);
+
+ arg_type_info = g_arg_info_get_type(arg_info);
direction = g_arg_info_get_direction(arg_info);
+ arg_type_tag = g_type_info_get_tag(arg_type_info);
+
if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
n_in_args += 1;
}
@@ -379,18 +391,53 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
n_out_args += 1;
}
+ aux_args[i] = NULL;
+ if (arg_type_tag == GI_TYPE_TAG_ARRAY) {
+ gint length_arg_pos;
+
+ length_arg_pos = g_type_info_get_array_length(arg_type_info);
+ if (length_arg_pos != -1) {
+ /* Tag the argument as auxiliary. Later, it'll be changed into a pointer to (in|out)_args[(in|out)_args_pos].
+ * We cannot do it now since we don't know how much space to allocate (n_(in|out)_args) yet.
+ */
+ aux_args[length_arg_pos] = (GArgument *)!NULL;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
+ n_aux_in_args += 1;
+ }
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
+ n_aux_out_args += 1;
+ }
+ }
+ }
+
+ g_base_info_unref((GIBaseInfo *)arg_type_info);
g_base_info_unref((GIBaseInfo *)arg_info);
}
+ return_info = g_callable_info_get_return_type((GICallableInfo *)self->info);
+ return_tag = g_type_info_get_tag(return_info);
+
+ /* Tag the return value's auxiliary argument too, if applicable. */
+ if (return_tag == GI_TYPE_TAG_ARRAY) {
+ gint length_arg_pos;
+ length_arg_pos = g_type_info_get_array_length(return_info);
+ if (length_arg_pos != -1) {
+ aux_args[length_arg_pos] = (GArgument *)!NULL;
+ n_aux_out_args += 1;
+ }
+ }
+
{
Py_ssize_t py_args_pos;
/* Check the argument count. */
- if (n_py_args != n_in_args + (is_constructor ? 1 : 0)) {
- PyErr_Format(PyExc_TypeError, "%s.%s() takes exactly %i argument(s) (%zd given)",
+ if (n_py_args != n_in_args + (is_constructor ? 1 : 0) - n_aux_in_args) {
+ g_base_info_unref((GIBaseInfo *)return_info);
+ PyErr_Format(PyExc_TypeError, "%s.%s() takes exactly %zd argument(s) (%zd given)",
g_base_info_get_namespace((GIBaseInfo *)callable_info),
g_base_info_get_name((GIBaseInfo *)callable_info),
- n_in_args + (is_constructor ? 1 : 0), n_py_args);
+ n_in_args + (is_constructor ? 1 : 0) - n_aux_in_args, n_py_args);
return NULL;
}
@@ -404,6 +451,11 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
PyObject *py_arg;
GError *error;
+ if (aux_args[i] != NULL) {
+ /* No check needed for auxiliary arguments. */
+ continue;
+ }
+
arg_info = g_callable_info_get_arg(callable_info, i);
direction = g_arg_info_get_direction(arg_info);
if (!(direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)) {
@@ -424,6 +476,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
case PyG_ARGUMENT_FROM_PYOBJECT_ERROR_TYPE:
py_error_type = PyExc_TypeError;
break;
+ case PyG_ARGUMENT_FROM_PYOBJECT_ERROR_SIZE:
case PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE:
py_error_type = PyExc_ValueError;
break;
@@ -444,6 +497,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
g_base_info_unref((GIBaseInfo *)arg_info);
if (PyErr_Occurred()) {
+ g_base_info_unref((GIBaseInfo *)return_info);
return NULL;
}
@@ -453,7 +507,6 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
g_assert(py_args_pos == n_py_args);
}
- /* Get the arguments. */
in_args = g_newa(GArgument, n_in_args);
out_args = g_newa(GArgument, n_out_args);
/* each out arg is a pointer, they point to these values */
@@ -461,6 +514,46 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
http://bugzilla.gnome.org/show_bug.cgi?id=573314 */
out_values = g_newa(GArgument, n_out_args);
+ /* Link aux_args to in_args. */
+ {
+ gsize in_args_pos;
+ gsize out_args_pos;
+
+ in_args_pos = is_method ? 1 : 0;
+ out_args_pos = 0;
+
+ for (i = 0; i < n_args; i++) {
+ GIArgInfo *arg_info;
+ GIDirection direction;
+
+ arg_info = g_callable_info_get_arg((GICallableInfo *)self->info, i);
+ direction = g_arg_info_get_direction(arg_info);
+
+ if (direction == GI_DIRECTION_IN) {
+ if (aux_args[i] != NULL) {
+ g_assert(in_args_pos < n_in_args);
+ aux_args[i] = &in_args[in_args_pos];
+ }
+ in_args_pos += 1;
+ } else {
+ if (aux_args[i] != NULL) {
+ g_assert(out_args_pos < n_out_args);
+ aux_args[i] = &out_values[out_args_pos];
+ }
+ out_args_pos += 1;
+ if (direction == GI_DIRECTION_INOUT) {
+ in_args_pos += 1;
+ }
+ }
+
+ g_base_info_unref((GIBaseInfo *)arg_info);
+ }
+
+ g_assert(in_args_pos == n_in_args);
+ g_assert(out_args_pos == n_out_args);
+ }
+
+ /* Get the arguments. */
{
guint in_args_pos = 0;
guint out_args_pos = 0;
@@ -486,6 +579,7 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
py_buffer = PyObject_GetAttrString((PyObject *)py_arg, "__buffer__");
if (py_buffer == NULL) {
g_base_info_unref(container);
+ g_base_info_unref((GIBaseInfo *)return_info);
return NULL;
}
py_buffer_procs = py_buffer->ob_type->tp_as_buffer;
@@ -521,6 +615,23 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
PyObject *py_arg;
+ GITypeInfo *arg_type_info;
+ GITypeTag arg_type_tag;
+
+ g_assert(in_args_pos < n_in_args);
+ if (direction == GI_DIRECTION_INOUT) {
+ in_args[in_args_pos].v_pointer = out_value;
+ }
+
+ if (aux_args[i] != NULL) {
+ /* Auxiliary argument has already been set or will be set later. */
+ in_args_pos += 1;
+ g_base_info_unref((GIBaseInfo *)arg_info);
+ continue;
+ }
+
+ arg_type_info = g_arg_info_get_type(arg_info);
+ arg_type_tag = g_type_info_get_tag(arg_type_info);
g_assert(py_args_pos < n_py_args);
py_arg = PyTuple_GetItem(args, py_args_pos);
@@ -528,7 +639,6 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
GArgument in_value = pyg_argument_from_pyobject(py_arg, g_arg_info_get_type(arg_info));
- g_assert(in_args_pos < n_in_args);
if (direction == GI_DIRECTION_IN) {
/* Pass the value. */
in_args[in_args_pos] = in_value;
@@ -536,9 +646,27 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
/* Pass a pointer to the value. */
g_assert(out_value != NULL);
*out_value = in_value;
- in_args[in_args_pos].v_pointer = out_value;
}
+ if (arg_type_tag == GI_TYPE_TAG_ARRAY) {
+ gint length_arg_pos;
+ length_arg_pos = g_type_info_get_array_length(arg_type_info);
+ if (length_arg_pos != -1) {
+ GArgument *length_arg;
+ Py_ssize_t size;
+
+ size = PyTuple_Size(py_arg);
+ if (size > 0) {
+ g_assert(in_value.v_pointer != NULL);
+ }
+ length_arg = aux_args[length_arg_pos];
+ g_assert(length_arg != NULL);
+ length_arg->v_size = size;
+ }
+ }
+
+ g_base_info_unref((GIBaseInfo *)arg_type_info);
+
in_args_pos += 1;
py_args_pos += 1;
}
@@ -553,14 +681,16 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
/* Invoke the callable. */
{
- GError *error = NULL;
+ GError *error;
+
+ error = NULL;
if (!g_function_info_invoke((GIFunctionInfo *)callable_info,
in_args, n_in_args,
out_args, n_out_args,
&return_arg,
&error)) {
- g_assert(error != NULL);
+ g_base_info_unref((GIBaseInfo *)return_info);
PyErr_Format(PyExc_RuntimeError, "Error invoking %s.%s(): %s",
g_base_info_get_namespace((GIBaseInfo *)callable_info),
g_base_info_get_name((GIBaseInfo *)callable_info),
@@ -570,17 +700,35 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
}
}
- /* Get return value. */
- return_info = g_callable_info_get_return_type(callable_info);
- return_tag = g_type_info_get_tag(return_info);
-
- n_return_values = n_out_args;
+ n_return_values = n_out_args - n_aux_out_args;
if (return_tag != GI_TYPE_TAG_VOID) {
n_return_values += 1;
if (!is_constructor) {
/* Convert the return value. */
- return_value = pyg_argument_to_pyobject(&return_arg, return_info);
+ if (return_tag == GI_TYPE_TAG_ARRAY) {
+ gssize length;
+ length = g_type_info_get_array_fixed_size(return_info);
+ if (length < 0) {
+ gint length_arg_pos;
+ GArgument *length_arg;
+
+ length_arg_pos = g_type_info_get_array_length(return_info);
+
+ if (length_arg_pos >= 0) {
+ length_arg = aux_args[length_arg_pos];
+ g_assert(length_arg != NULL);
+ length = length_arg->v_int;
+ }
+ }
+ if (length < 0) {
+ g_assert(g_type_info_is_zero_terminated(return_info));
+ }
+ return_value = pyg_array_to_pyobject(return_arg.v_pointer, length, return_info);
+ } else {
+ return_value = pyg_argument_to_pyobject(&return_arg, return_info);
+ }
+
g_assert(return_value != NULL);
} else {
/* Wrap the return value inside the first argument. */
@@ -692,57 +840,57 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
} else {
PyObject *obj;
GITypeTag type_tag;
- int retval;
+ GArgument *arg;
if (direction == GI_DIRECTION_INOUT) {
g_assert(in_args_pos < n_in_args);
}
g_assert(out_args_pos < n_out_args);
+ if (aux_args[i] != NULL) {
+ if (direction == GI_DIRECTION_INOUT) {
+ in_args_pos += 1;
+ }
+ out_args_pos += 1;
+ g_base_info_unref((GIBaseInfo *)arg_type_info);
+ g_base_info_unref((GIBaseInfo *)arg_info);
+ continue;
+ }
+
+ arg = (GArgument *)out_args[out_args_pos].v_pointer;
+
type_tag = g_type_info_get_tag(arg_type_info);
if (type_tag == GI_TYPE_TAG_ARRAY) {
- /* FIXME: Verify all that... */
+ gssize length;
- gint length_arg_index;
- GArgument *length_arg;
- GArgument *arg;
+ length = g_type_info_get_array_fixed_size(arg_type_info);
+ if (length < 0) {
+ gint length_arg_pos;
+ GArgument *length_arg;
- length_arg_index = g_type_info_get_array_length(arg_type_info);
+ length_arg_pos = g_type_info_get_array_length(arg_type_info);
- if (is_method) {
- /* XXX: Why? */
- length_arg_index -= 1;
+ if (length_arg_pos >= 0) {
+ length_arg = aux_args[length_arg_pos];
+ g_assert(length_arg != NULL);
+ length = length_arg->v_int;
+ }
}
-
- if (length_arg_index == -1) {
- g_base_info_unref((GIBaseInfo *)arg_type_info);
- g_base_info_unref((GIBaseInfo *)arg_info);
- g_base_info_unref((GIBaseInfo *)return_info);
- PyErr_SetString(PyExc_NotImplementedError, "Need a field to specify the array length");
- return NULL;
+ if (length < 0) {
+ g_assert(g_type_info_is_zero_terminated(arg_type_info));
}
- length_arg = out_args[length_arg_index].v_pointer;
-
- if (length_arg == NULL) {
- g_base_info_unref((GIBaseInfo *)arg_type_info);
- g_base_info_unref((GIBaseInfo *)arg_info);
- g_base_info_unref((GIBaseInfo *)return_info);
- PyErr_SetString(PyExc_RuntimeError, "Failed to get the length of the array");
- return NULL;
- }
-
- arg = (GArgument *)out_args[out_args_pos].v_pointer;
- obj = pyarray_to_pyobject(arg->v_pointer, length_arg->v_int, arg_type_info);
+ obj = pyg_array_to_pyobject(arg->v_pointer, length, arg_type_info);
} else {
- obj = pyg_argument_to_pyobject(out_args[out_args_pos].v_pointer, arg_type_info);
+ obj = pyg_argument_to_pyobject(arg, arg_type_info);
}
g_assert(obj != NULL);
g_assert(return_values_pos < n_return_values);
if (n_return_values > 1) {
+ int retval;
g_assert(return_value != NULL);
retval = PyTuple_SetItem(return_value, return_values_pos, obj);
diff --git a/girepository/bank.h b/girepository/bank.h
index 3f76b77..5808f80 100644
--- a/girepository/bank.h
+++ b/girepository/bank.h
@@ -76,14 +76,17 @@ GArgument pyg_argument_from_pyobject(PyObject *object,
GITypeInfo *info);
PyObject* pyg_argument_to_pyobject(GArgument *arg,
GITypeInfo *info);
-PyObject* pyarray_to_pyobject(gpointer array, int length, GITypeInfo *info);
+
+PyObject* pyg_array_to_pyobject(gpointer items, gsize length, GITypeInfo *info);
+gpointer pyg_array_from_pyobject(PyObject *object, GITypeInfo *type_info, gsize *length);
#define PyG_ARGUMENT_FROM_PYOBJECT_ERROR pyg_argument_from_pyobject_error_quark()
GQuark pyg_argument_from_pyobject_error_quark(void);
typedef enum {
PyG_ARGUMENT_FROM_PYOBJECT_ERROR_TYPE,
- PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE
+ PyG_ARGUMENT_FROM_PYOBJECT_ERROR_VALUE,
+ PyG_ARGUMENT_FROM_PYOBJECT_ERROR_SIZE
} PyGArgumentFromPyObjectError;
gboolean pyg_argument_from_pyobject_check(PyObject *object, GITypeInfo *type_info, GError **error);
diff --git a/tests/test_girepository.py b/tests/test_girepository.py
index a07f16a..4e08c11 100644
--- a/tests/test_girepository.py
+++ b/tests/test_girepository.py
@@ -260,23 +260,81 @@ class TestGIEverything(unittest.TestCase):
self.assertEquals(("first", "second"), Everything.test_utf8_out_nonconst_return())
-# FIXME
-# ======================================================================
-# ERROR: testStrv (__main__.TestGIEverything)
-# ----------------------------------------------------------------------
-# Traceback (most recent call last):
-# File "test_girepository.py", line 179, in testStrv
-# self.assertTrue(Everything.test_strv_in(('1', '2', '3')))
-# File "/opt/gnome-introspection/lib64/python2.5/site-packages/gtk-2.0/girepository/btypes.py", line 124, in __call__
-# self.type_check(name, value, argType)
-# File "/opt/gnome-introspection/lib64/python2.5/site-packages/gtk-2.0/girepository/btypes.py", line 89, in type_check
-# raise TypeError("Must pass None for arrays currently")
-# TypeError: Must pass None for arrays currently
-# def testStrv(self):
-# self.assertTrue(Everything.test_strv_in(('1', '2', '3')))
-# self.assertTrue(Everything.test_strv_in(['1', '2', '3'])) # XXX valid?
-# self.assertRaises(TypeError, Everything.test_strv_in(('1', 2, 3)))
-# self.assertEquals((1, 2, 3), Everything.test_strv_out())
+# Arrays
+
+ def testArrayIntIn(self):
+ self.assertEquals(5, Everything.test_array_int_in((1, 2, 3, -1)))
+
+ self.assertRaises(TypeError, Everything.test_array_int_in, 0)
+ self.assertRaises(TypeError, Everything.test_array_int_in, (2, 'a'))
+
+ def testArrayInt8In(self):
+ self.assertEquals(5, Everything.test_array_gint8_in((1, 2, 3, -1)))
+ self.assertEquals(-1, Everything.test_array_gint8_in((INT8_MAX, INT8_MIN)))
+
+ self.assertRaises(TypeError, Everything.test_array_gint8_in, 0)
+ self.assertRaises(TypeError, Everything.test_array_gint8_in, (2, 'a'))
+ self.assertRaises(ValueError, Everything.test_array_gint8_in, (INT8_MAX+1,))
+ self.assertRaises(ValueError, Everything.test_array_gint8_in, (INT8_MIN-1,))
+
+ def testArrayInt16In(self):
+ self.assertEquals(5, Everything.test_array_gint16_in((1, 2, 3, -1)))
+ self.assertEquals(-1, Everything.test_array_gint16_in((INT16_MAX, INT16_MIN)))
+
+ self.assertRaises(TypeError, Everything.test_array_gint16_in, 0)
+ self.assertRaises(TypeError, Everything.test_array_gint16_in, (2, 'a'))
+ self.assertRaises(ValueError, Everything.test_array_gint16_in, (INT16_MAX+1,))
+ self.assertRaises(ValueError, Everything.test_array_gint16_in, (INT16_MIN-1,))
+
+ def testArrayInt32In(self):
+ self.assertEquals(5, Everything.test_array_gint32_in((1, 2, 3, -1)))
+ self.assertEquals(-1, Everything.test_array_gint32_in((INT32_MAX, INT32_MIN)))
+
+ self.assertRaises(TypeError, Everything.test_array_gint32_in, 0)
+ self.assertRaises(TypeError, Everything.test_array_gint32_in, (2, 'a'))
+ self.assertRaises(ValueError, Everything.test_array_gint32_in, (INT32_MAX+1,))
+ self.assertRaises(ValueError, Everything.test_array_gint32_in, (INT32_MIN-1,))
+
+ def testArrayInt32In(self):
+ self.assertEquals(5, Everything.test_array_gint32_in((1, 2, 3, -1)))
+ self.assertEquals(-1, Everything.test_array_gint32_in((INT32_MAX, INT32_MIN)))
+
+ self.assertRaises(TypeError, Everything.test_array_gint32_in, 0)
+ self.assertRaises(TypeError, Everything.test_array_gint32_in, (2, 'a'))
+ self.assertRaises(ValueError, Everything.test_array_gint32_in, (INT32_MAX+1,))
+ self.assertRaises(ValueError, Everything.test_array_gint32_in, (INT32_MIN-1,))
+
+ def testArrayInt64In(self):
+ self.assertEquals(5, Everything.test_array_gint64_in((1, 2, 3, -1)))
+ self.assertEquals(-1, Everything.test_array_gint64_in((INT64_MAX, INT64_MIN)))
+
+ self.assertRaises(TypeError, Everything.test_array_gint64_in, 0)
+ self.assertRaises(TypeError, Everything.test_array_gint64_in, (2, 'a'))
+ self.assertRaises(ValueError, Everything.test_array_gint64_in, (INT64_MAX+1,))
+ self.assertRaises(ValueError, Everything.test_array_gint64_in, (INT64_MIN-1,))
+
+ def testStrvIn(self):
+ self.assertTrue(Everything.test_strv_in(('1', '2', '3')))
+ self.assertFalse(Everything.test_strv_in(('1', '2')))
+ self.assertFalse(Everything.test_strv_in(('1', '2', '3', '4')))
+
+ self.assertRaises(TypeError, Everything.test_strv_in, '1')
+ self.assertRaises(TypeError, Everything.test_strv_in, ('1', 2, 3))
+
+ def testArrayGTypeIn(self):
+ # TODO
+ pass
+
+ def testStrvOut(self):
+ self.assertEquals(("thanks", "for", "all", "the", "fish"), Everything.test_strv_out())
+ self.assertEquals(("thanks", "for", "all", "the", "fish"), Everything.test_strv_out_c())
+
+ def testStrvOutarg(self):
+ self.assertEquals(("1", "2", "3"), Everything.test_strv_outarg())
+
+
+# Interface
+# GSList
def testGList(self):
retval = Everything.test_glist_nothing_return()
@@ -456,21 +514,6 @@ class TestGIEverything(unittest.TestCase):
s = TestSubclass()
self.assertEquals(s.do_matrix('matrix'), 42)
-# FIXME
-# ======================================================================
-# ERROR: testArrayOut (__main__.TestGIEverything)
-# ----------------------------------------------------------------------
-# Traceback (most recent call last):
-# File "test_girepository.py", line 282, in testArrayOut
-# b, n_ints, ints = Everything.test_array_int_full_out2()
-# File "/opt/gnome-introspection/lib64/python2.5/site-packages/gtk-2.0/girepository/module.py", line 56, in __getattr__
-# self.__class__.__name__, name))
-# AttributeError: 'DynamicModule' object has no attribute 'test_array_int_full_out2'
-# def testArrayOut(self):
-# b, n_ints, ints = Everything.test_array_int_full_out2()
-# self.assertEquals(b, True)
-# self.assertEquals(n_ints, 5)
-# self.assertEquals(ints, [1, 2, 3, 4, 5])
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestGIEverything)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]