pygobject r996 - in trunk: . gio tests



Author: paulp
Date: Wed Jan 14 18:39:45 2009
New Revision: 996
URL: http://svn.gnome.org/viewvc/pygobject?rev=996&view=rev

Log:
2009-01-14  Paul Pogonyshev  <pogonyshev gmx net>

	Bug 566706 â cleanup GIO overrides

	* gio/gio.override (pygio_notify_new)
	(pygio_notify_using_optional_callback)
	(pygio_notify_callback_is_valid_full)
	(pygio_notify_callback_is_valid)
	(pygio_notify_reference_callback): New functions.
	(pygio_notify_free): Rename from pygio_free_notify() and extend.
	(async_result_callback_marshal): Warn if new `referenced' field is
	not set (programming error).
	(_wrap_g_drive_eject, _wrap_g_drive_poll_for_media)
	(_wrap_g_mount_unmount, _wrap_g_mount_eject)
	(_wrap_g_mount_remount): Lots of cleanup: use new functions
	instead of repeating code, unify and fix error handling.

	* gio/gfile.override (_wrap_g_file_read_async)
	(_wrap_g_file_load_contents_async)
	(_wrap_g_file_enumerate_children_async)
	(_wrap_g_file_mount_mountable, _wrap_g_file_unmount_mountable)
	(_wrap_g_file_mount_enclosing_volume, _wrap_g_file_copy)
	(_wrap_g_file_copy_async, _wrap_g_file_move)
	(_wrap_g_file_append_to_async, _wrap_g_file_create_async)
	(_wrap_g_file_replace_async, _wrap_g_file_query_info_async)
	(_wrap_g_file_replace_contents_async): Similar cleanup.

	* gio/gfileenumerator.override
	(_wrap_g_file_enumerator_next_files_async): Similar cleanup.

	* gio/gicon.override (_wrap_g_loadable_icon_load_async): Similar
	cleanup.

	* gio/ginputstream.override (_wrap_g_input_stream_close_async):
	Similar cleanup.

	* gio/goutputstream.override (_wrap_g_output_stream_write_async)
	(_wrap_g_output_stream_close_async): Similar cleanup.

	* gio/gvolume.override (_wrap_g_volume_mount)
	(_wrap_g_volume_eject): Similar cleanup.

	* tests/test_gio.py (TestFile.test_copy_async): Fix the test.


Modified:
   trunk/ChangeLog
   trunk/gio/gfile.override
   trunk/gio/gfileenumerator.override
   trunk/gio/gicon.override
   trunk/gio/ginputstream.override
   trunk/gio/gio.override
   trunk/gio/goutputstream.override
   trunk/gio/gvolume.override
   trunk/tests/test_gio.py

Modified: trunk/gio/gfile.override
==============================================================================
--- trunk/gio/gfile.override	(original)
+++ trunk/gio/gfile.override	Wed Jan 14 18:39:45 2009
@@ -130,7 +130,7 @@
   GCancellable *cancellable;
   PyGIONotify *notify;
 
-  notify = g_slice_new0(PyGIONotify);
+  notify = pygio_notify_new();
 
   if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                    "O|iOO:File.read_async",
@@ -139,22 +139,15 @@
                                    &io_priority,
                                    &pycancellable,
                                    &notify->data))
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
+      goto error;
 
-  if (!PyCallable_Check(notify->callback))
-    {
-      PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
-  Py_INCREF(notify->callback);
-  Py_XINCREF(notify->data);
+  if (!pygio_notify_callback_is_valid(notify))
+      goto error;
 
   if (!pygio_check_cancellable(pycancellable, &cancellable))
-      return NULL;
+      goto error;
+
+  pygio_notify_reference_callback(notify);
 
   g_file_read_async(G_FILE(self->obj),
                     io_priority,
@@ -164,6 +157,10 @@
 
   Py_INCREF(Py_None);
   return Py_None;
+
+ error:
+  pygio_notify_free(notify);
+  return NULL;
 }
 %%
 override g_file_load_contents kwargs
@@ -214,7 +211,7 @@
     PyGObject *pycancellable = NULL;
     PyGIONotify *notify;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|OO:File.load_contents_async",
@@ -222,17 +219,16 @@
                                       &notify->callback,
                                       &pycancellable,
                                       &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (!pygio_check_cancellable(pycancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
     g_file_load_contents_async(G_FILE(self->obj),
 			       cancellable,
 			       (GAsyncReadyCallback)async_result_callback_marshal,
@@ -240,6 +236,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_load_contents_finish kwargs
@@ -291,7 +291,7 @@
     GCancellable *cancellable = NULL;
     PyGObject *py_cancellable = NULL;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 				     "sO|OiOO:GFile.enumerate_children_async",
@@ -302,26 +302,19 @@
 				     &io_priority,
 				     &py_cancellable,
 				     &notify->data))
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
+        goto error;
 
-    if (!PyCallable_Check(notify->callback))
-    {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_FILE_QUERY_INFO_FLAGS,
 					py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(py_cancellable, &cancellable))
-	return NULL;
+	goto error;
+
+    pygio_notify_reference_callback(notify);
 
     g_file_enumerate_children_async(G_FILE(self->obj),
 				    attributes,
@@ -333,6 +326,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_mount_mountable kwargs
@@ -350,7 +347,7 @@
     GMountMountFlags flags = G_MOUNT_MOUNT_NONE;
     GCancellable *cancellable;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O!O|OOO:File.mount_mountable",
@@ -361,27 +358,19 @@
 				     &py_flags,
 				     &py_cancellable,
 				     &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
-
-    if (!PyCallable_Check(notify->callback))
-    {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_MOUNT_MOUNT_FLAGS,
 					py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(py_cancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
     g_file_mount_mountable(G_FILE(self->obj),
 			   flags,
@@ -392,6 +381,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_unmount_mountable kwargs
@@ -408,7 +401,7 @@
     GMountUnmountFlags flags = G_MOUNT_UNMOUNT_NONE;
     GCancellable *cancellable;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|OOO:File.unmount_mountable",
@@ -417,27 +410,19 @@
 				     &py_flags,
 				     &py_cancellable,
 				     &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
-
-    if (!PyCallable_Check(notify->callback))
-    {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_MOUNT_UNMOUNT_FLAGS,
 					py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(py_cancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
     g_file_unmount_mountable(G_FILE(self->obj),
 			     flags,
@@ -447,6 +432,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_mount_enclosing_volume kwargs
@@ -464,7 +453,7 @@
     GMountMountFlags flags = G_MOUNT_MOUNT_NONE;
     GCancellable *cancellable;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O!O|OOO:File.mount_enclosing_volume",
@@ -475,27 +464,19 @@
 				     &py_flags,
 				     &py_cancellable,
 				     &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
-
-    if (!PyCallable_Check(notify->callback))
-    {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_MOUNT_MOUNT_FLAGS,
 					py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(py_cancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
     g_file_mount_enclosing_volume(G_FILE(self->obj),
 				  flags,
@@ -506,6 +487,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_copy kwargs
@@ -527,7 +512,7 @@
     GError *error = NULL;
     GFileProgressCallback callback = NULL;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O!|OOOO:File.copy",
@@ -538,31 +523,23 @@
 				     &py_flags,
 				     &py_cancellable,
 				     &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
-
-    if (notify->callback != NULL)
-    {
-	if (!PyCallable_Check(notify->callback))
-	{
-	    PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	    g_slice_free(PyGIONotify, notify);
-	    return NULL;
-	}
-	callback = (GFileProgressCallback)file_progress_callback_marshal;
-	Py_INCREF(notify->callback);
+    if (pygio_notify_using_optional_callback(notify)) {
+        callback = (GFileProgressCallback)file_progress_callback_marshal;
+        if (!pygio_notify_callback_is_valid(notify))
+            goto error;
     }
-    Py_XINCREF(notify->data);
 
     if (py_flags && pyg_flags_get_value(G_TYPE_FILE_COPY_FLAGS,
 					py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(py_cancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    /* No need to reference callback here, because it will be used
+     * only while this function is in progress. */
 
     ret = g_file_copy(G_FILE(self->obj),
 		      G_FILE(destination->obj),
@@ -572,11 +549,15 @@
 		      notify,
 		      &error);
 
-    pygio_free_notify(notify);
     if (pyg_error_check(&error))
-        return NULL;
+        goto error;
 
+    pygio_notify_free(notify);
     return PyBool_FromLong(ret);
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_copy_async kwargs
@@ -585,10 +566,11 @@
 			PyObject *args,
 			PyObject *kwargs)
 {
+  /* FIXME: Double-check argument order. */
   static char *kwlist[] = { "destination", "callback", "flags", "io_priority",
 			    "user_data", "cancellable", "progress_callback", 
                             "progress_callback_data", NULL };
-  PyGIONotify *notify, *progress_callback;
+  PyGIONotify *notify, *progress_notify;
   PyObject *py_flags = NULL;
   PyGObject *destination = NULL;
   PyGObject *py_cancellable = NULL;
@@ -598,8 +580,8 @@
   GCancellable *cancellable;
   GFileProgressCallback callback = NULL;
 
-  notify = g_slice_new0(PyGIONotify);
-  progress_callback = g_slice_new0(PyGIONotify);
+  notify = pygio_notify_new();
+  progress_notify = pygio_notify_new();
 
   if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                    "O!O|OiOOOO:File.copy_async",
@@ -611,58 +593,46 @@
                                    &io_priority,
                                    &notify->data,
                                    &pycancellable,
-                                   &progress_callback->callback,
-                                   &progress_callback->data
-                                   ))
-    {
-      g_slice_free(PyGIONotify, notify);
-      g_slice_free(PyGIONotify, progress_callback);
-      return NULL;
-    }
+                                   &progress_notify->callback,
+                                   &progress_notify->data))
+      goto error;
+
+  if (!pygio_notify_callback_is_valid(notify))
+      goto error;
 
   if (!pygio_check_cancellable(py_cancellable, &cancellable))
-      return NULL;
-  if (progress_callback->callback != NULL)
-    {
-	if (!PyCallable_Check(progress_callback->callback))
-	{
-	    PyErr_SetString(PyExc_TypeError, "progress_callback argument not callable");
-	    g_slice_free(PyGIONotify, notify);
-            g_slice_free(PyGIONotify, progress_callback);
-	    return NULL;
-	}
-	callback = (GFileProgressCallback)file_progress_callback_marshal;
-	Py_INCREF(progress_callback->callback);
-        Py_XINCREF(progress_callback->data);
-    }
-  if (!PyCallable_Check(notify->callback))
-    {
-      PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-      Py_DECREF(progress_callback->callback);
-      Py_XDECREF(progress_callback->data);
-      g_slice_free(PyGIONotify, notify);
-      g_slice_free(PyGIONotify, progress_callback);
-      return NULL;
-    }
-  Py_INCREF(notify->callback);
-  Py_XINCREF(notify->data);
+      goto error;
 
+  if (pygio_notify_using_optional_callback(progress_notify)) {
+      callback = (GFileProgressCallback)file_progress_callback_marshal;
+      if (!pygio_notify_callback_is_valid_full(progress_notify, "progress_callback"))
+          goto error;
+  }
 
   if (!pygio_check_cancellable(pycancellable, &cancellable))
-      return NULL;
+      goto error;
 
+  pygio_notify_reference_callback(notify);
+  pygio_notify_reference_callback(progress_notify);
+
+  /* FIXME: 'progress_notify' is not properly freed up as far as I see. */
   g_file_copy_async(G_FILE(self->obj),
                     G_FILE(destination->obj),
                     flags,
                     io_priority,
                     cancellable,
                     callback,
-                    progress_callback,
+                    progress_notify,
                     (GAsyncReadyCallback)async_result_callback_marshal,
                     notify);
 
   Py_INCREF(Py_None);
   return Py_None;
+
+ error:
+  pygio_notify_free(notify);
+  pygio_notify_free(progress_notify);
+  return NULL;
 }
 %%
 override g_file_move kwargs
@@ -684,7 +654,7 @@
     GError *error = NULL;
     GFileProgressCallback callback = NULL;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O!|OOOO:File.move",
@@ -695,31 +665,23 @@
 				     &py_flags,
 				     &py_cancellable,
 				     &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
-
-    if (notify->callback != NULL)
-    {
-	if (!PyCallable_Check(notify->callback))
-	{
-	    PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	    g_slice_free(PyGIONotify, notify);
-	    return NULL;
-	}
-	callback = (GFileProgressCallback)file_progress_callback_marshal;
-	Py_INCREF(notify->callback);
+    if (pygio_notify_using_optional_callback(notify)) {
+        callback = (GFileProgressCallback)file_progress_callback_marshal;
+        if (!pygio_notify_callback_is_valid(notify))
+            goto error;
     }
-    Py_XINCREF(notify->data);
 
     if (py_flags && pyg_flags_get_value(G_TYPE_FILE_COPY_FLAGS,
 					py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(py_cancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    /* No need to reference callback here, because it will be used
+     * only while this function is in progress. */
 
     ret = g_file_move(G_FILE(self->obj),
 		      G_FILE(destination->obj),
@@ -729,11 +691,15 @@
 		      notify,
 		      &error);
 
-    pygio_free_notify(notify);
     if (pyg_error_check(&error))
-        return NULL;
+        goto error;
 
+    pygio_notify_free(notify);
     return PyBool_FromLong(ret);
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_set_attribute kwargs
@@ -882,7 +848,7 @@
     int io_priority = G_PRIORITY_DEFAULT;
     PyGIONotify *notify;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|OiOO:File.append_to_async",
@@ -891,27 +857,30 @@
                                       &flags, &io_priority,
                                       &pycancellable,
                                       &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_FILE_CREATE_FLAGS,
                                         py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(pycancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
     g_file_append_to_async(G_FILE(self->obj), flags, io_priority, cancellable,
                            (GAsyncReadyCallback)async_result_callback_marshal,
                            notify);
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_create_async kwargs
@@ -927,7 +896,7 @@
     int io_priority = G_PRIORITY_DEFAULT;
     PyGIONotify *notify;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|OiOO:File.create_async",
@@ -936,27 +905,30 @@
                                       &flags, &io_priority,
                                       &pycancellable,
                                       &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_FILE_CREATE_FLAGS,
                                         py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(pycancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
     g_file_create_async(G_FILE(self->obj), flags, io_priority, cancellable,
                         (GAsyncReadyCallback)async_result_callback_marshal,
                         notify);
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_replace_async kwargs
@@ -975,7 +947,7 @@
     PyObject *py_backup = Py_True;
     PyGIONotify *notify;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|zOOiOO:File.replace_async",
@@ -985,23 +957,22 @@
                                       &flags, &io_priority,
                                       &pycancellable,
                                       &notify->data))
-
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
+        goto error;
 
     make_backup = PyObject_IsTrue(py_backup) ? TRUE : FALSE;
 
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
+
     if (py_flags && pyg_flags_get_value(G_TYPE_FILE_CREATE_FLAGS,
                                         py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(pycancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
     g_file_replace_async(G_FILE(self->obj), etag, make_backup, flags,
                          io_priority, cancellable,
                          (GAsyncReadyCallback)async_result_callback_marshal,
@@ -1009,6 +980,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_query_info_async kwargs
@@ -1025,7 +1000,7 @@
     char *attributes;
     PyGIONotify *notify;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "Os|OiOO:File.query_info_async",
@@ -1035,21 +1010,20 @@
                                       &flags, &io_priority,
                                       &pycancellable,
                                       &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_FILE_CREATE_FLAGS,
                                         py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(pycancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
     g_file_query_info_async(G_FILE(self->obj), attributes, flags,
                          io_priority, cancellable,
                          (GAsyncReadyCallback)async_result_callback_marshal,
@@ -1057,6 +1031,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_replace_contents kwargs
@@ -1169,7 +1147,7 @@
     char *contents;
     char *etag = NULL;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "s#O|zbOOO:File.replace_contents_async",
@@ -1182,21 +1160,21 @@
                                       &py_flags,
                                       &pycancellable,
                                       &notify->data))
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
+        goto error;
+
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_FILE_CREATE_FLAGS,
                                         py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(pycancellable, &cancellable))
-        return NULL;
+        goto error;
 
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    pygio_notify_reference_callback(notify);
     pygio_notify_copy_buffer(notify, contents, length);
+
     g_file_replace_contents_async(G_FILE(self->obj),
                                   notify->buffer,
                                   notify->buffer_size,
@@ -1209,6 +1187,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override-slot GFile.tp_richcompare

Modified: trunk/gio/gfileenumerator.override
==============================================================================
--- trunk/gio/gfileenumerator.override	(original)
+++ trunk/gio/gfileenumerator.override	Wed Jan 14 18:39:45 2009
@@ -67,7 +67,7 @@
     GCancellable *cancellable = NULL;
     PyGObject *py_cancellable = NULL;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 				     "iO|iOO:GFileEnumerator.enumerate_children_async",
@@ -77,22 +77,15 @@
 				     &io_priority,
 				     &py_cancellable,
 				     &notify->data))
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
+        goto error;
+
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
-    if (!PyCallable_Check(notify->callback))
-    {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
-  
     if (!pygio_check_cancellable(py_cancellable, &cancellable))
-	return NULL;
+	goto error;
+
+    pygio_notify_reference_callback(notify);  
     
     g_file_enumerator_next_files_async(G_FILE_ENUMERATOR(self->obj),
 				       num_files,
@@ -103,6 +96,10 @@
     
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_file_enumerator_next_files_finish kwargs

Modified: trunk/gio/gicon.override
==============================================================================
--- trunk/gio/gicon.override	(original)
+++ trunk/gio/gicon.override	Wed Jan 14 18:39:45 2009
@@ -109,7 +109,7 @@
     GCancellable *cancellable;
     PyGIONotify *notify;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|iOO:gio.LoadableIcon.load_async",
@@ -117,16 +117,13 @@
 				     &notify->callback, &size, &pycancellable, &notify->data))
 	goto error;
 
-    if (!PyCallable_Check(notify->callback)) {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	goto error;
-    }
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (!pygio_check_cancellable(pycancellable, &cancellable))
 	goto error;
 
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    pygio_notify_reference_callback(notify);
 
     g_loadable_icon_load_async(G_LOADABLE_ICON(self->obj),
 			       size,
@@ -137,7 +134,7 @@
     return Py_None;
 
  error:
-    g_slice_free(PyGIONotify, notify);
+    pygio_notify_free(notify);
     return NULL;
 }
 %%

Modified: trunk/gio/ginputstream.override
==============================================================================
--- trunk/gio/ginputstream.override	(original)
+++ trunk/gio/ginputstream.override	Wed Jan 14 18:39:45 2009
@@ -318,7 +318,7 @@
     GCancellable *cancellable;
     PyGIONotify *notify;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|iOO:InputStream.close_async",
@@ -327,22 +327,15 @@
                                      &io_priority,
                                      &pycancellable,
                                      &notify->data))
-        {
-            g_slice_free(PyGIONotify, notify);
-            return NULL;
-        }
+        goto error;
 
-    if (!PyCallable_Check(notify->callback))
-        {
-            PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-            g_slice_free(PyGIONotify, notify);
-            return NULL;
-        }
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (!pygio_check_cancellable(pycancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
     g_input_stream_close_async(G_INPUT_STREAM(self->obj),
                                io_priority,
@@ -352,6 +345,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_data_input_stream_read_line kwargs

Modified: trunk/gio/gio.override
==============================================================================
--- trunk/gio/gio.override	(original)
+++ trunk/gio/gio.override	Wed Jan 14 18:39:45 2009
@@ -34,6 +34,7 @@
 #define BUFSIZE 8192
 
 typedef struct {
+    gboolean  referenced;
     PyObject *callback;
     PyObject *data;
     gpointer  buffer;
@@ -55,15 +56,72 @@
     }
 }
 
+static PyGIONotify *
+pygio_notify_new(void)
+{
+    return g_slice_new0(PyGIONotify);
+}
+
+static gboolean
+pygio_notify_using_optional_callback(PyGIONotify *notify)
+{
+    if (notify->callback)
+        return TRUE;
+    else {
+        notify->data = NULL;
+        return FALSE;
+    }
+}
+
+static gboolean
+pygio_notify_callback_is_valid_full(PyGIONotify *notify, const gchar *name)
+{
+    if (!notify->callback) {
+        PyErr_SetString(PyExc_RuntimeError, "internal error: callback is not set");
+        return FALSE;
+    }
+
+    if (!PyCallable_Check(notify->callback)) {
+        gchar *error_message = g_strdup_printf("%s argument not callable", name);
+
+	PyErr_SetString(PyExc_TypeError, error_message);
+        g_free(error_message);
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+static gboolean
+pygio_notify_callback_is_valid(PyGIONotify *notify)
+{
+    return pygio_notify_callback_is_valid_full(notify, "callback");
+}
+
 static void
-pygio_free_notify(PyGIONotify *notify)
+pygio_notify_reference_callback(PyGIONotify *notify)
 {
-    Py_XDECREF(notify->callback);
-    Py_XDECREF(notify->data);
-    if (notify->buffer)
-	g_slice_free1(notify->buffer_size, notify->buffer);
+    if (!notify->referenced) {
+        notify->referenced = TRUE;
+        Py_XINCREF(notify->callback);
+        Py_XINCREF(notify->data);
+    }
+}
 
-    g_slice_free(PyGIONotify, notify);
+static void
+pygio_notify_free(PyGIONotify *notify)
+{
+    if (notify) {
+        if (notify->referenced) {
+            Py_XDECREF(notify->callback);
+            Py_XDECREF(notify->data);
+        }
+
+        if (notify->buffer)
+            g_slice_free1(notify->buffer_size, notify->buffer);
+
+        g_slice_free(PyGIONotify, notify);
+    }
 }
 
 static void
@@ -76,6 +134,9 @@
 
     state = pyg_gil_state_ensure();
 
+    if (!notify->referenced)
+        g_warning("pygio_notify_reference_callback() hasn't been called before using the structure");
+
     if (notify->data)
 	ret = PyEval_CallFunction(notify->callback, "(OOO)",
 				  pygobject_new(source_object),
@@ -86,14 +147,13 @@
 				    pygobject_new(source_object),
 				    pygobject_new((GObject *)result));
 
-    if (ret == NULL)
-      {
+    if (ret == NULL) {
 	PyErr_Print();
 	PyErr_Clear();
-      }
+    }
 
     Py_XDECREF(ret);
-    pygio_free_notify(notify);
+    pygio_notify_free(notify);
 
     pyg_gil_state_release(state);
 }
@@ -165,7 +225,7 @@
     PyGObject *py_cancellable = NULL;
     GCancellable *cancellable;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|OOO:gio.Drive.eject",
@@ -173,30 +233,20 @@
 				     &notify->callback,
 				     &py_flags,
 				     &py_cancellable,
-				     &notify->data)) {
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
+				     &notify->data))
+        goto error;
 
-    if (!PyCallable_Check(notify->callback)) {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_MOUNT_UNMOUNT_FLAGS,
-					py_flags, (gpointer) &flags)) {
-	g_slice_free(PyGIONotify, notify);
-        return NULL;
-    }
+					py_flags, (gpointer) &flags))
+        goto error;
 
-    if (!pygio_check_cancellable(py_cancellable, &cancellable)) {
-	g_slice_free(PyGIONotify, notify);
-        return NULL;
-    }
+    if (!pygio_check_cancellable(py_cancellable, &cancellable))
+        goto error;
 
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    pygio_notify_reference_callback(notify);
 
     g_drive_eject(G_DRIVE(self->obj),
 		  flags,
@@ -206,6 +256,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_drive_poll_for_media kwargs
@@ -217,31 +271,23 @@
     PyGObject *py_cancellable = NULL;
     GCancellable *cancellable;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|OO:gio.Drive.eject",
 				     kwlist,
 				     &notify->callback,
 				     &py_cancellable,
-				     &notify->data)) {
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
+				     &notify->data))
+        goto error;
 
-    if (!PyCallable_Check(notify->callback)) {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
-    if (!pygio_check_cancellable(py_cancellable, &cancellable)) {
-	g_slice_free(PyGIONotify, notify);
-        return NULL;
-    }
+    if (!pygio_check_cancellable(py_cancellable, &cancellable))
+        goto error;
 
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    pygio_notify_reference_callback(notify);
 
     g_drive_poll_for_media(G_DRIVE(self->obj),
 			   cancellable,
@@ -250,6 +296,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override-slot GDrive.tp_repr
@@ -362,7 +412,7 @@
     GMountUnmountFlags flags = G_MOUNT_UNMOUNT_NONE;
     GCancellable *cancellable;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|OOO:GMount.unmount",
@@ -371,27 +421,19 @@
 				     &py_flags,
 				     &py_cancellable,
 				     &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
-
-    if (!PyCallable_Check(notify->callback))
-    {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_MOUNT_UNMOUNT_FLAGS,
 					py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(py_cancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
     g_mount_unmount(G_MOUNT(self->obj),
 		    flags,
@@ -401,6 +443,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_mount_eject kwargs
@@ -414,7 +460,7 @@
     PyGObject *py_cancellable = NULL;
     GCancellable *cancellable;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|OOO:gio.Mount.eject",
@@ -422,30 +468,20 @@
 				     &notify->callback,
 				     &py_flags,
 				     &py_cancellable,
-				     &notify->data)) {
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
+				     &notify->data))
+        goto error;
 
-    if (!PyCallable_Check(notify->callback)) {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_MOUNT_UNMOUNT_FLAGS,
-					py_flags, (gpointer) &flags)) {
-	g_slice_free(PyGIONotify, notify);
-        return NULL;
-    }
+					py_flags, (gpointer) &flags))
+        goto error;
 
-    if (!pygio_check_cancellable(py_cancellable, &cancellable)) {
-	g_slice_free(PyGIONotify, notify);
-        return NULL;
-    }
+    if (!pygio_check_cancellable(py_cancellable, &cancellable))
+        goto error;
 
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    pygio_notify_reference_callback(notify);
 
     g_mount_eject(G_MOUNT(self->obj),
 		  flags,
@@ -455,6 +491,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_mount_remount kwargs
@@ -471,7 +511,7 @@
     PyGObject *py_cancellable = NULL;
     GCancellable *cancellable;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|OOOO:gio.Mount.remount",
@@ -480,41 +520,30 @@
 				     &py_flags,
 				     &py_mount_operation,
 				     &py_cancellable,
-				     &notify->data)) {
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
+				     &notify->data))
+        goto error;
 
-    if (!PyCallable_Check(notify->callback)) {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_mount_operation != Py_None) {
 	if (!pygobject_check(py_mount_operation, &PyGMountOperation_Type)) {
 	    PyErr_SetString(PyExc_TypeError,
 			    "mount_operation must be a gio.MountOperation or None");
-	    g_slice_free(PyGIONotify, notify);
-	    return NULL;
+            goto error;
 	}
 
 	mount_operation = G_MOUNT_OPERATION(pygobject_get(py_mount_operation));
     }
 
     if (py_flags && pyg_flags_get_value(G_TYPE_MOUNT_UNMOUNT_FLAGS,
-					py_flags, (gpointer) &flags)) {
-	g_slice_free(PyGIONotify, notify);
-        return NULL;
-    }
+					py_flags, (gpointer) &flags))
+        goto error;
 
-    if (!pygio_check_cancellable(py_cancellable, &cancellable)) {
-	g_slice_free(PyGIONotify, notify);
-        return NULL;
-    }
+    if (!pygio_check_cancellable(py_cancellable, &cancellable))
+        goto error;
 
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    pygio_notify_reference_callback(notify);
 
     g_mount_remount(G_MOUNT(self->obj),
 		    flags,
@@ -525,6 +554,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override-slot GMount.tp_repr

Modified: trunk/gio/goutputstream.override
==============================================================================
--- trunk/gio/goutputstream.override	(original)
+++ trunk/gio/goutputstream.override	Wed Jan 14 18:39:45 2009
@@ -103,7 +103,7 @@
   GCancellable *cancellable;
   PyGIONotify *notify;
 
-  notify = g_slice_new0(PyGIONotify);
+  notify = pygio_notify_new();
 
   if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 				   "s#O|iOO:OutputStream.write_async",
@@ -113,24 +113,17 @@
 				   &io_priority,
 				   &pycancellable,
 				   &notify->data))
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
+      goto error;
 
-  if (!PyCallable_Check(notify->callback))
-    {
-      PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
-  Py_INCREF(notify->callback);
-  Py_XINCREF(notify->data);
+  if (!pygio_notify_callback_is_valid(notify))
+      goto error;
   
   if (!pygio_check_cancellable(pycancellable, &cancellable))
-      return NULL;
+      goto error;
 
+  pygio_notify_reference_callback(notify);
   pygio_notify_copy_buffer(notify, buffer, count);
+
   g_output_stream_write_async(G_OUTPUT_STREAM(self->obj),
 			      notify->buffer,
 			      notify->buffer_size,
@@ -141,6 +134,10 @@
   
   Py_INCREF(Py_None);
   return Py_None;
+
+ error:
+  pygio_notify_free(notify);
+  return NULL;
 }
 %%
 override g_output_stream_close_async kwargs
@@ -156,7 +153,7 @@
   GCancellable *cancellable;
   PyGIONotify *notify;
 
-  notify = g_slice_new0(PyGIONotify);
+  notify = pygio_notify_new();
 
   if (!PyArg_ParseTupleAndKeywords(args, kwargs,
 				   "O|iOO:OutputStream.close_async",
@@ -165,22 +162,15 @@
 				   &io_priority,
 				   &pycancellable,
 				   &notify->data))
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
+      goto error;
+
+  if (!pygio_notify_callback_is_valid(notify))
+      goto error;
 
   if (!pygio_check_cancellable(pycancellable, &cancellable))
-      return NULL;
+      goto error;
 
-  if (!PyCallable_Check(notify->callback))
-    {
-      PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
-  Py_INCREF(notify->callback);
-  Py_XINCREF(notify->data);
+  pygio_notify_reference_callback(notify);
   
   g_output_stream_close_async(G_OUTPUT_STREAM(self->obj),
 			      io_priority,
@@ -190,6 +180,10 @@
   
   Py_INCREF(Py_None);
   return Py_None;
+
+ error:
+  pygio_notify_free(notify);
+  return NULL;
 }
 %%
 override g_memory_output_stream_new noargs

Modified: trunk/gio/gvolume.override
==============================================================================
--- trunk/gio/gvolume.override	(original)
+++ trunk/gio/gvolume.override	Wed Jan 14 18:39:45 2009
@@ -35,7 +35,7 @@
     GMountMountFlags flags = G_MOUNT_MOUNT_NONE;
     GCancellable *cancellable;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O!O|OOO:Volume.mount",
@@ -46,27 +46,19 @@
 				     &py_flags,
 				     &py_cancellable,
 				     &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
-
-    if (!PyCallable_Check(notify->callback))
-    {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_MOUNT_MOUNT_FLAGS,
 					py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(py_cancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
     g_volume_mount(G_VOLUME(self->obj),
 		   flags,
@@ -77,6 +69,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override g_volume_eject kwargs
@@ -93,7 +89,7 @@
     GMountUnmountFlags flags = G_MOUNT_UNMOUNT_NONE;
     GCancellable *cancellable;
 
-    notify = g_slice_new0(PyGIONotify);
+    notify = pygio_notify_new();
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                      "O|OOO:Volume.eject",
@@ -102,27 +98,19 @@
 				     &py_flags,
 				     &py_cancellable,
 				     &notify->data))
+        goto error;
 
-    {
-      g_slice_free(PyGIONotify, notify);
-      return NULL;
-    }
-
-    if (!PyCallable_Check(notify->callback))
-    {
-	PyErr_SetString(PyExc_TypeError, "callback argument not callable");
-	g_slice_free(PyGIONotify, notify);
-	return NULL;
-    }
-    Py_INCREF(notify->callback);
-    Py_XINCREF(notify->data);
+    if (!pygio_notify_callback_is_valid(notify))
+        goto error;
 
     if (py_flags && pyg_flags_get_value(G_TYPE_MOUNT_UNMOUNT_FLAGS,
 					py_flags, (gpointer)&flags))
-        return NULL;
+        goto error;
 
     if (!pygio_check_cancellable(py_cancellable, &cancellable))
-        return NULL;
+        goto error;
+
+    pygio_notify_reference_callback(notify);
 
     g_volume_eject(G_VOLUME(self->obj),
 		   flags,
@@ -132,6 +120,10 @@
 
     Py_INCREF(Py_None);
     return Py_None;
+
+ error:
+    pygio_notify_free(notify);
+    return NULL;
 }
 %%
 override-slot GVolume.tp_repr

Modified: trunk/tests/test_gio.py
==============================================================================
--- trunk/tests/test_gio.py	(original)
+++ trunk/tests/test_gio.py	Wed Jan 14 18:39:45 2009
@@ -303,8 +303,11 @@
         destination = gio.File('copy.txt')
 
         def copied(source_, result):
-            self.assert_(source_ is source)
-            self.failUnless(source_.copy_finish(result))
+            try:
+                self.assert_(source_ is source)
+                self.failUnless(source_.copy_finish(result))
+            finally:
+                loop.quit()
 
         def progress(current, total):
             self.assert_(isinstance(current, long))
@@ -312,7 +315,9 @@
             self.assert_(0 <= current <= total)
 
         try:
+            loop = glib.MainLoop()
             source.copy_async(destination, copied, progress_callback = progress)
+            loop.run()
 
             self.failUnless(os.path.exists('copy.txt'))
             self.assertEqual(open('file.txt').read(),



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