[pygobject] Use g_vfunc_info_invoke for chaining up in vfuncs
- From: Tomeu Vizoso <tomeuv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Use g_vfunc_info_invoke for chaining up in vfuncs
- Date: Mon, 17 Jan 2011 14:40:22 +0000 (UTC)
commit da50d5620a42046d4fc905bb28a0890d73533cb1
Author: Tomeu Vizoso <tomeu vizoso collabora co uk>
Date: Mon Dec 13 18:03:51 2010 +0100
Use g_vfunc_info_invoke for chaining up in vfuncs
https://bugzilla.gnome.org/show_bug.cgi?id=637165
gi/pygi-info.c | 4 +-
gi/pygi-invoke.c | 72 +++++++++++++++++++++++++++++++++++++++++------------
gi/pygi-invoke.h | 3 +-
gi/types.py | 28 ++++++++++++++++++++-
tests/test_gi.py | 5 ++-
5 files changed, 89 insertions(+), 23 deletions(-)
---
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index 9d15e5e..c753097 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -235,6 +235,7 @@ out:
PYGLIB_DEFINE_TYPE ("gi.CallableInfo", PyGICallableInfo_Type, PyGIBaseInfo);
static PyMethodDef _PyGICallableInfo_methods[] = {
+ { "invoke", (PyCFunction) _wrap_g_callable_info_invoke, METH_VARARGS | METH_KEYWORDS },
{ NULL, NULL, 0 }
};
@@ -476,7 +477,6 @@ _pygi_g_type_info_size (GITypeInfo *type_info)
static PyMethodDef _PyGIFunctionInfo_methods[] = {
{ "is_constructor", (PyCFunction) _wrap_g_function_info_is_constructor, METH_NOARGS },
{ "is_method", (PyCFunction) _wrap_g_function_info_is_method, METH_NOARGS },
- { "invoke", (PyCFunction) _wrap_g_function_info_invoke, METH_VARARGS },
{ NULL, NULL, 0 }
};
@@ -1544,7 +1544,7 @@ _pygi_info_register_types (PyObject *m)
_PyGI_REGISTER_TYPE (m, PyGIFieldInfo_Type, FieldInfo,
PyGIBaseInfo_Type);
_PyGI_REGISTER_TYPE (m, PyGIVFuncInfo_Type, VFuncInfo,
- PyGIBaseInfo_Type);
+ PyGICallableInfo_Type);
_PyGI_REGISTER_TYPE (m, PyGIUnionInfo_Type, UnionInfo,
PyGIRegisteredTypeInfo_Type);
_PyGI_REGISTER_TYPE (m, PyGIBoxedInfo_Type, BoxedInfo,
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 3a4fafa..e0b365a 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -58,19 +58,40 @@ struct invocation_state
GIArgument *backup_args;
GIArgument return_arg;
- PyObject *return_value;
+ PyObject *return_value;
+
+ GType implementor_gtype;
};
-static void
+static gboolean
_initialize_invocation_state (struct invocation_state *state,
GIFunctionInfo *info,
- PyObject *py_args)
+ PyObject *py_args,
+ PyObject *kwargs)
{
- GIFunctionInfoFlags flags;
+ if (g_base_info_get_type (info) == GI_INFO_TYPE_FUNCTION) {
+ GIFunctionInfoFlags flags = g_function_info_get_flags (info);
+
+ state->is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
+ state->is_constructor = (flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0;
+ state->implementor_gtype = 0;
+ } else {
+ PyObject *obj;
+
+ state->is_method = TRUE;
+ state->is_constructor = FALSE;
+
+ obj = PyDict_GetItemString (kwargs, "gtype");
+ if (obj == NULL) {
+ PyErr_SetString (PyExc_TypeError,
+ "need the GType of the implementor class");
+ return FALSE;
+ }
- flags = g_function_info_get_flags (info);
- state->is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
- state->is_constructor = (flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0;
+ state->implementor_gtype = pyg_type_from_object (obj);
+ if (state->implementor_gtype == 0)
+ return FALSE;
+ }
/* Count arguments. */
state->n_args = g_callable_info_get_n_args ( (GICallableInfo *) info);
@@ -98,6 +119,8 @@ _initialize_invocation_state (struct invocation_state *state,
state->out_args = NULL;
state->out_values = NULL;
state->backup_args = NULL;
+
+ return TRUE;
}
static gboolean
@@ -552,7 +575,7 @@ _prepare_invocation_state (struct invocation_state *state,
static gboolean
_invoke_function (struct invocation_state *state,
- GIFunctionInfo *function_info, PyObject *py_args)
+ GICallableInfo *callable_info, PyObject *py_args)
{
GError *error;
gint retval;
@@ -560,13 +583,24 @@ _invoke_function (struct invocation_state *state,
error = NULL;
pyg_begin_allow_threads;
- retval = g_function_info_invoke ( (GIFunctionInfo *) function_info,
- state->in_args,
- state->n_in_args,
- state->out_args,
- state->n_out_args,
- &state->return_arg,
- &error);
+ if (g_base_info_get_type (callable_info) == GI_INFO_TYPE_FUNCTION) {
+ retval = g_function_info_invoke ( (GIFunctionInfo *) callable_info,
+ state->in_args,
+ state->n_in_args,
+ state->out_args,
+ state->n_out_args,
+ &state->return_arg,
+ &error);
+ } else {
+ retval = g_vfunc_info_invoke ( (GIVFuncInfo *) callable_info,
+ state->implementor_gtype,
+ state->in_args,
+ state->n_in_args,
+ state->out_args,
+ state->n_out_args,
+ &state->return_arg,
+ &error);
+ }
pyg_end_allow_threads;
if (!retval) {
@@ -916,11 +950,15 @@ _free_invocation_state (struct invocation_state *state)
PyObject *
-_wrap_g_function_info_invoke (PyGIBaseInfo *self, PyObject *py_args)
+_wrap_g_callable_info_invoke (PyGIBaseInfo *self, PyObject *py_args,
+ PyObject *kwargs)
{
struct invocation_state state = { 0, };
- _initialize_invocation_state (&state, self->info, py_args);
+ if (!_initialize_invocation_state (&state, self->info, py_args, kwargs)) {
+ _free_invocation_state (&state);
+ return NULL;
+ }
if (!_prepare_invocation_state (&state, self->info, py_args)) {
_free_invocation_state (&state);
diff --git a/gi/pygi-invoke.h b/gi/pygi-invoke.h
index 0d07b21..dc1ce18 100644
--- a/gi/pygi-invoke.h
+++ b/gi/pygi-invoke.h
@@ -30,7 +30,8 @@
G_BEGIN_DECLS
-PyObject *_wrap_g_function_info_invoke (PyGIBaseInfo *self, PyObject *py_args);
+PyObject *_wrap_g_callable_info_invoke (PyGIBaseInfo *self, PyObject *py_args,
+ PyObject *kwargs);
G_END_DECLS
diff --git a/gi/types.py b/gi/types.py
index cc43d02..4f7094e 100644
--- a/gi/types.py
+++ b/gi/types.py
@@ -45,6 +45,16 @@ def Function(info):
return function
+def NativeVFunc(info, cls):
+
+ def native_vfunc(*args):
+ return info.invoke(*args, gtype=cls.__gtype__)
+ native_vfunc.__info__ = info
+ native_vfunc.__name__ = info.get_name()
+ native_vfunc.__module__ = info.get_namespace()
+
+ return native_vfunc
+
def Constructor(info):
def constructor(cls, *args):
@@ -125,6 +135,21 @@ class MetaClassHelper(object):
base._setup_vfuncs(impl)
+ def _setup_native_vfuncs(cls, impl):
+ for base in cls.__bases__ + (cls,):
+ if not hasattr(base, '__info__') or \
+ not hasattr(base.__info__, 'get_vfuncs') or \
+ isinstance(base.__info__, InterfaceInfo):
+ continue
+ for vfunc_info in base.__info__.get_vfuncs():
+ name = 'do_%s' % vfunc_info.get_name()
+ value = NativeVFunc(vfunc_info, impl)
+ setattr(impl, name, value)
+
+ if base != cls:
+ base._setup_native_vfuncs(impl)
+
+
def find_vfunc_conflict_in_bases(vfunc, bases):
for klass in bases:
if not hasattr(klass, '__info__') or \
@@ -153,7 +178,6 @@ class GObjectMeta(gobject.GObjectMeta, MetaClassHelper):
def __init__(cls, name, bases, dict_):
super(GObjectMeta, cls).__init__(name, bases, dict_)
-
is_gi_defined = False
if cls.__module__ == 'gi.repository.' + cls.__info__.get_namespace():
is_gi_defined = True
@@ -167,6 +191,7 @@ class GObjectMeta(gobject.GObjectMeta, MetaClassHelper):
elif is_gi_defined:
cls._setup_methods()
cls._setup_constants()
+ cls._setup_native_vfuncs(cls)
if isinstance(cls.__info__, ObjectInfo):
cls._setup_fields()
@@ -175,6 +200,7 @@ class GObjectMeta(gobject.GObjectMeta, MetaClassHelper):
elif isinstance(cls.__info__, InterfaceInfo):
register_interface_info(cls.__info__.get_g_type())
+
class StructMeta(type, MetaClassHelper):
def __init__(cls, name, bases, dict_):
diff --git a/tests/test_gi.py b/tests/test_gi.py
index d1566c6..e19b7fd 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -1372,7 +1372,8 @@ class TestPythonGObject(unittest.TestCase):
return 42
def do_method_with_default_implementation(self, int8):
- self.props.int = int8 * 2
+ GIMarshallingTests.Object.do_method_with_default_implementation(self, int8)
+ self.props.int += int8
class SubObject(GIMarshallingTests.SubObject):
__gtype_name__ = "SubObject"
@@ -1400,7 +1401,7 @@ class TestPythonGObject(unittest.TestCase):
self.assertEqual(object_.method_int8_out(), 42)
object_.method_with_default_implementation(42)
- self.assertEqual(object_.val, 84)
+ self.assertEqual(object_.props.int, 84)
class ObjectWithoutVFunc(GIMarshallingTests.Object):
__gtype_name__ = 'ObjectWithoutVFunc'
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]