[pygi] Allow passing None for callbacks which are annotated allow-none
- From: John Palmieri <johnp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygi] Allow passing None for callbacks which are annotated allow-none
- Date: Mon, 14 Jun 2010 17:17:41 +0000 (UTC)
commit 729072e73d65e7fd5b5197ebe5a8c53a449d0ec0
Author: John (J5) Palmieri <johnp redhat com>
Date: Mon Jun 7 17:12:09 2010 -0400
Allow passing None for callbacks which are annotated allow-none
* Many callbacks are optional parameters yet we were asserting on
Py_None
* We now check to see if allow_none is set when setting up callbacks,
if it is set and py_function == Py_None, we set the closure to NULL
and return
* pygi-invoke.c now checks to see if the closure == NULL when setting
arguments
* if it is NULL there is no reason to set the the destroy notify handler
so we skip that too
https://bugzilla.gnome.org/show_bug.cgi?id=620906
gi/pygi-callbacks.c | 7 +++++++
gi/pygi-invoke.c | 14 +++++++++++---
tests/test_everything.py | 4 ++++
3 files changed, 22 insertions(+), 3 deletions(-)
---
diff --git a/gi/pygi-callbacks.c b/gi/pygi-callbacks.c
index ac9ca6a..a12eaed 100644
--- a/gi/pygi-callbacks.c
+++ b/gi/pygi-callbacks.c
@@ -161,9 +161,11 @@ _pygi_create_callback (GIBaseInfo *function_info,
PyObject *py_function;
guint8 i, py_argv_pos;
PyObject *py_user_data;
+ gboolean allow_none;
callback_arg = g_callable_info_get_arg ( (GICallableInfo*) function_info, callback_index);
scope = g_arg_info_get_scope (callback_arg);
+ allow_none = g_arg_info_may_be_null (callback_arg);
callback_type = g_arg_info_get_type (callback_arg);
g_assert (g_type_info_get_tag (callback_type) == GI_TYPE_TAG_INTERFACE);
@@ -185,6 +187,11 @@ _pygi_create_callback (GIBaseInfo *function_info,
for (i = 0; i < n_args && i < py_argc; i++) {
if (i == callback_index) {
py_function = PyTuple_GetItem (py_argv, py_argv_pos);
+ /* if we allow none then set the closure to NULL and return */
+ if (allow_none && py_function == Py_None) {
+ *closure_out = NULL;
+ return TRUE;
+ }
found_py_function = TRUE;
} else if (i == user_data_index) {
py_user_data = PyTuple_GetItem (py_argv, py_argv_pos);
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 63e57e7..16b4037 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -113,6 +113,7 @@ _prepare_invocation_state (struct invocation_state *state,
return FALSE;
if (state->callback_index != G_MAXUINT8) {
+
if (!_pygi_create_callback (function_info,
state->is_method,
state->is_constructor,
@@ -428,7 +429,11 @@ _prepare_invocation_state (struct invocation_state *state,
GIDirection direction;
if (i == state->callback_index) {
- state->args[i]->v_pointer = state->closure->closure;
+ if (state->closure)
+ state->args[i]->v_pointer = state->closure->closure;
+ else
+ /* Some callbacks params accept NULL */
+ state->args[i]->v_pointer = NULL;
py_args_pos++;
continue;
} else if (i == state->user_data_index) {
@@ -436,8 +441,11 @@ _prepare_invocation_state (struct invocation_state *state,
py_args_pos++;
continue;
} else if (i == state->destroy_notify_index) {
- PyGICClosure *destroy_notify = _pygi_destroy_notify_create();
- state->args[i]->v_pointer = destroy_notify->closure;
+ if (state->closure) {
+ /* No need to clean up if the callback is NULL */
+ PyGICClosure *destroy_notify = _pygi_destroy_notify_create();
+ state->args[i]->v_pointer = destroy_notify->closure;
+ }
continue;
}
diff --git a/tests/test_everything.py b/tests/test_everything.py
index 06a8d8c..36de1e3 100644
--- a/tests/test_everything.py
+++ b/tests/test_everything.py
@@ -264,3 +264,7 @@ class TestCallbacks(unittest.TestCase):
TestCallbacks.called = False
obj_ = Everything.TestObj.new_callback(callbackWithUserData, None)
self.assertTrue(TestCallbacks.called)
+
+ def testCallbackNone(self):
+ # make sure this doesn't assert or crash
+ Everything.test_simple_callback(None)
\ No newline at end of file
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]