diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | gio/gfile.override | 160 | ||||
-rw-r--r-- | gio/gfileenumerator.override | 8 | ||||
-rw-r--r-- | gio/ginputstream.override | 22 | ||||
-rw-r--r-- | gio/gio.defs | 38 | ||||
-rw-r--r-- | gio/gio.override | 14 | ||||
-rw-r--r-- | gio/goutputstream.override | 16 | ||||
-rw-r--r-- | tests/test_gio.py | 31 |
8 files changed, 246 insertions, 55 deletions
@@ -1,3 +1,15 @@ +2008-07-24 Johan Dahlin <johan@gnome.org> + + * gio/gfile.override: + * gio/gfileenumerator.override: + * gio/ginputstream.override: + * gio/gio.defs: + * gio/gio.override: + * gio/goutputstream.override: + * tests/test_gio.py: + Wrap gio.File.copy, add tests and documentation. + Rename PyGAsyncRequestNotify to PyGIONotify and reuse it. + 2008-07-23 Johan Dahlin <johan@gnome.org> * glib/pyglib.c (_pyglib_destroy_notify): diff --git a/gio/gfile.override b/gio/gfile.override index 9fcb883..d510823 100644 --- a/gio/gfile.override +++ b/gio/gfile.override @@ -1,4 +1,4 @@ -/* -*- Mode: C; c-basic-offset: 4 -*- +%%/* -*- Mode: C; c-basic-offset: 4 -*- * pygobject - Python bindings for GObject * Copyright (C) 2008 Johan Dahlin * @@ -20,6 +20,48 @@ * USA */ %% +headers + +typedef struct { + PyObject *callback; + PyObject *data; +} PyGFileProgressCallback; + +static void +file_progress_callback_marshal(goffset current_num_bytes, + goffset total_num_bytes, + PyGIONotify *notify) +{ + PyObject *ret; + PyGILState_STATE state; + + state = pyg_gil_state_ensure(); + + if (notify->data) + ret = PyEval_CallFunction(notify->callback, "(kkO)", + current_num_bytes, + total_num_bytes, + notify->data); + else + ret = PyObject_CallFunction(notify->callback, "(kk)", + current_num_bytes, + total_num_bytes); + + if (ret == NULL) + { + PyErr_Print(); + PyErr_Clear(); + } + + Py_XDECREF(ret); + + Py_DECREF(notify->callback); + Py_XDECREF(notify->data); + g_slice_free(PyGIONotify, notify); + + pyg_gil_state_release(state); +} +%% define _install_file_meta static PyObject * _wrap__install_file_meta(PyObject *self, PyObject *args) @@ -96,9 +138,9 @@ _wrap_g_file_read_async(PyGObject *self, int io_priority = G_PRIORITY_DEFAULT; PyGObject *pycancellable = NULL; GCancellable *cancellable; - PyGAsyncRequestNotify *notify; + PyGIONotify *notify; - notify = g_slice_new0(PyGAsyncRequestNotify); + notify = g_slice_new0(PyGIONotify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iOO:File.read_async", @@ -108,14 +150,14 @@ _wrap_g_file_read_async(PyGObject *self, &pycancellable, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } if (!PyCallable_Check(notify->callback)) { PyErr_SetString(PyExc_TypeError, "callback argument not callable"); - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } Py_INCREF(notify->callback); @@ -180,9 +222,9 @@ _wrap_g_file_load_contents_async(PyGObject *self, static char *kwlist[] = { "callback", "cancellable", "user_data", NULL }; GCancellable *cancellable; PyGObject *pycancellable = NULL; - PyGAsyncRequestNotify *notify; + PyGIONotify *notify; - notify = g_slice_new0(PyGAsyncRequestNotify); + notify = g_slice_new0(PyGIONotify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OO:File.load_contents_async", @@ -192,7 +234,7 @@ _wrap_g_file_load_contents_async(PyGObject *self, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } @@ -249,7 +291,7 @@ _wrap_g_file_enumerate_children_async(PyGObject *self, PyObject *args, PyObject { static char *kwlist[] = { "attributes", "flags", "callback", "io_priority", "cancellable", "user_data", NULL }; - PyGAsyncRequestNotify *notify; + PyGIONotify *notify; char *attributes; PyObject *py_flags = NULL; int io_priority = G_PRIORITY_DEFAULT; @@ -257,7 +299,7 @@ _wrap_g_file_enumerate_children_async(PyGObject *self, PyObject *args, PyObject GCancellable *cancellable = NULL; PyGObject *py_cancellable = NULL; - notify = g_slice_new0(PyGAsyncRequestNotify); + notify = g_slice_new0(PyGIONotify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|OiOO:GFile.enumerate_children_async", @@ -269,14 +311,14 @@ _wrap_g_file_enumerate_children_async(PyGObject *self, PyObject *args, PyObject &py_cancellable, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } if (!PyCallable_Check(notify->callback)) { PyErr_SetString(PyExc_TypeError, "callback argument not callable"); - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } Py_INCREF(notify->callback); @@ -309,14 +351,14 @@ _wrap_g_file_mount_mountable(PyGObject *self, { static char *kwlist[] = { "callback", "flags", "mount_operation", "cancellable", "user_data", NULL }; - PyGAsyncRequestNotify *notify; + PyGIONotify *notify; PyObject *py_flags = NULL; PyGObject *mount_operation; PyGObject *py_cancellable = NULL; GMountMountFlags flags = G_MOUNT_MOUNT_NONE; GCancellable *cancellable; - notify = g_slice_new0(PyGAsyncRequestNotify); + notify = g_slice_new0(PyGIONotify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O|OOO:File.mount_mountable", @@ -329,14 +371,14 @@ _wrap_g_file_mount_mountable(PyGObject *self, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } if (!PyCallable_Check(notify->callback)) { PyErr_SetString(PyExc_TypeError, "callback argument not callable"); - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } Py_INCREF(notify->callback); @@ -368,13 +410,13 @@ _wrap_g_file_unmount_mountable(PyGObject *self, { static char *kwlist[] = { "callback", "flags", "cancellable", "user_data", NULL }; - PyGAsyncRequestNotify *notify; + PyGIONotify *notify; PyObject *py_flags = NULL; PyGObject *py_cancellable = NULL; GMountMountFlags flags = G_MOUNT_MOUNT_NONE; GCancellable *cancellable; - notify = g_slice_new0(PyGAsyncRequestNotify); + notify = g_slice_new0(PyGIONotify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOO:File.unmount_mountable", @@ -385,14 +427,14 @@ _wrap_g_file_unmount_mountable(PyGObject *self, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } if (!PyCallable_Check(notify->callback)) { PyErr_SetString(PyExc_TypeError, "callback argument not callable"); - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } Py_INCREF(notify->callback); @@ -423,14 +465,14 @@ _wrap_g_file_mount_enclosing_volume(PyGObject *self, { static char *kwlist[] = { "callback", "flags", "mount_operation", "cancellable", "user_data", NULL }; - PyGAsyncRequestNotify *notify; + PyGIONotify *notify; PyObject *py_flags = NULL; PyGObject *mount_operation; PyGObject *py_cancellable = NULL; GMountMountFlags flags = G_MOUNT_MOUNT_NONE; GCancellable *cancellable; - notify = g_slice_new0(PyGAsyncRequestNotify); + notify = g_slice_new0(PyGIONotify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O|OOO:File.mount_enclosing_volume", @@ -443,14 +485,14 @@ _wrap_g_file_mount_enclosing_volume(PyGObject *self, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } if (!PyCallable_Check(notify->callback)) { PyErr_SetString(PyExc_TypeError, "callback argument not callable"); - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } Py_INCREF(notify->callback); @@ -473,7 +515,76 @@ _wrap_g_file_mount_enclosing_volume(PyGObject *self, Py_INCREF(Py_None); return Py_None; } +%% +override g_file_copy kwargs +static PyObject * +_wrap_g_file_copy(PyGObject *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "destination", "flags", + "cancellable", "progress_callback", + "user_data", NULL }; + PyGIONotify *notify; + PyObject *py_flags = NULL; + PyGObject *destination = NULL; + PyGObject *py_cancellable = NULL; + GFileCopyFlags flags = G_FILE_COPY_NONE; + GCancellable *cancellable; + int ret; + GError *error = NULL; + GFileProgressCallback callback = NULL; + + notify = g_slice_new0(PyGIONotify); + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!|OOOO:File.unmount_mountable", + kwlist, + &PyGFile_Type, + &destination, + ¬ify->callback, + &py_flags, + &py_cancellable, + ¬ify->data)) + + { + 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); + } + Py_XINCREF(notify->data); + + if (py_flags && pyg_flags_get_value(G_TYPE_FILE_COPY_FLAGS, + py_flags, (gpointer)&flags)) + return NULL; + + if (!pygio_check_cancellable(py_cancellable, &cancellable)) + return NULL; + + ret = g_file_copy(G_FILE(self->obj), + G_FILE(destination->obj), + flags, + cancellable, + callback, + notify, + &error); + + if (pyg_error_check(&error)) + return NULL; + + return PyBool_FromLong(ret); +} /* GFile.append_to_async */ /* GFile.create_async */ /* GFile.eject_mountable */ @@ -484,7 +595,6 @@ _wrap_g_file_mount_enclosing_volume(PyGObject *self, /* GFile.set_attributes_async */ /* GFile.set_display_name_async */ /* GFile.load_partial_contents_async: No ArgType for GFileReadMoreCallback */ -/* GFile.copy: No ArgType for GFileProgressCallback */ /* GFile.move: No ArgType for GFileProgressCallback */ /* GFile.query_settable_attributes: No ArgType for GFileAttributeInfoList* */ /* GFile.query_writable_namespaces: No ArgType for GFileAttributeInfoList* */ diff --git a/gio/gfileenumerator.override b/gio/gfileenumerator.override index 06c7f54..55c2ffe 100644 --- a/gio/gfileenumerator.override +++ b/gio/gfileenumerator.override @@ -61,13 +61,13 @@ _wrap_g_file_enumerator_next_files_async(PyGObject *self, PyObject *args, PyObje { static char *kwlist[] = { "num_files", "callback", "io_priority", "cancellable", "user_data", NULL }; - PyGAsyncRequestNotify *notify; + PyGIONotify *notify; int num_files; int io_priority = G_PRIORITY_DEFAULT; GCancellable *cancellable = NULL; PyGObject *py_cancellable = NULL; - notify = g_slice_new0(PyGAsyncRequestNotify); + notify = g_slice_new0(PyGIONotify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO|iOO:GFileEnumerator.enumerate_children_async", @@ -78,14 +78,14 @@ _wrap_g_file_enumerator_next_files_async(PyGObject *self, PyObject *args, PyObje &py_cancellable, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } if (!PyCallable_Check(notify->callback)) { PyErr_SetString(PyExc_TypeError, "callback argument not callable"); - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } Py_INCREF(notify->callback); diff --git a/gio/ginputstream.override b/gio/ginputstream.override index 8a42d60..878f7e7 100644 --- a/gio/ginputstream.override +++ b/gio/ginputstream.override @@ -27,12 +27,12 @@ typedef struct { PyObject *callback; PyObject *data; PyObject *buffer; -} PyGAsyncRequestNotifyRead; +} PyGIONotifyRead; static void async_result_callback_marshal_read(GObject *source_object, GAsyncResult *result, - PyGAsyncRequestNotifyRead *notify) + PyGIONotifyRead *notify) { PyObject *ret; PyGILState_STATE state; @@ -69,7 +69,7 @@ async_result_callback_marshal_read(GObject *source_object, Py_DECREF(notify->callback); Py_XDECREF(notify->data); - g_slice_free(PyGAsyncRequestNotifyRead, notify); + g_slice_free(PyGIONotifyRead, notify); pyg_gil_state_release(state); } @@ -157,9 +157,9 @@ _wrap_g_input_stream_read_async(PyGObject *self, int io_priority = G_PRIORITY_DEFAULT; PyGObject *pycancellable = NULL; GCancellable *cancellable; - PyGAsyncRequestNotifyRead *notify; + PyGIONotifyRead *notify; - notify = g_slice_new0(PyGAsyncRequestNotifyRead); + notify = g_slice_new0(PyGIONotifyRead); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "lO|iOO:InputStream.read_async", @@ -170,14 +170,14 @@ _wrap_g_input_stream_read_async(PyGObject *self, &pycancellable, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotifyRead, notify); + g_slice_free(PyGIONotifyRead, notify); return NULL; } if (!PyCallable_Check(notify->callback)) { PyErr_SetString(PyExc_TypeError, "callback argument not callable"); - g_slice_free(PyGAsyncRequestNotifyRead, notify); + g_slice_free(PyGIONotifyRead, notify); return NULL; } Py_INCREF(notify->callback); @@ -245,9 +245,9 @@ _wrap_g_input_stream_close_async(PyGObject *self, int io_priority = G_PRIORITY_DEFAULT; PyGObject *pycancellable = NULL; GCancellable *cancellable; - PyGAsyncRequestNotify *notify; + PyGIONotify *notify; - notify = g_slice_new0(PyGAsyncRequestNotify); + notify = g_slice_new0(PyGIONotify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iOO:InputStream.close_async", @@ -257,14 +257,14 @@ _wrap_g_input_stream_close_async(PyGObject *self, &pycancellable, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } if (!PyCallable_Check(notify->callback)) { PyErr_SetString(PyExc_TypeError, "callback argument not callable"); - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } Py_INCREF(notify->callback); diff --git a/gio/gio.defs b/gio/gio.defs index 7a225d0..2ce5726 100644 --- a/gio/gio.defs +++ b/gio/gio.defs @@ -1645,6 +1645,44 @@ ) (define-method copy + (docstring +"Copies the file source to the location specified by destination.\n" +"Can not handle recursive copies of directories.\n" +"\n" +"If the flag gio.FILE_COPY_OVERWRITE is specified an already existing\n" +"destination file is overwritten.\n" +"\n" +"If the flag gio.FILE_COPY_NOFOLLOW_SYMLINKS is specified then symlink\n" +"will be copied as symlinks, otherwise the target of the source symlink\n" +"will be copied.\n" +"\n" +"If cancellable is not None, then the operation can be cancelled b\n" +"triggering the cancellable object from another thread.\n" +"If the operation was cancelled, the error gio.ERROR_CANCELLED\n" +"will be returned.\n" +"\n" +"If progress_callback is not None, then the operation can be monitored\n" +"by setting this to a callable. if specified progress_callback_data will\n" +"be passed to this function. It is guaranteed that this callback\n" +"will be called after all data has been transferred with the total number\n" +"of bytes copied during the operation.\n" +"\n" +"If the source file does not exist then the gio.ERROR_NOT_FOUND\n" +"error is returned, independent on the status of the destination.\n" +"\n" +"If gio.FILE_COPY_OVERWRITE is not specified and the target exists\n" +"then the error gio.ERROR_EXISTS is returned.\n" +"\n" +"If trying to overwrite a file over a directory the gio.ERROR_IS_DIRECTORY\n" +"error is returned. If trying to overwrite a directory with a directory\n" +"the gio.ERROR_WOULD_MERGE error is returned.\n" +"\n" +"If the source is a directory and the target does not exist\n" +"or gio.FILE_COPY_OVERWRITE is specified and the target is a file\n" +"then the gio.ERROR_WOULD_RECURSE error is returned.\n" +"\n" +"If you are interested in copying the GFile object itself\n" +"(not the on-disk file), see gio.File.dup().") (of-object "GFile") (c-name "g_file_copy") (return-type "gboolean") diff --git a/gio/gio.override b/gio/gio.override index 3d26b7d..ffd2d4e 100644 --- a/gio/gio.override +++ b/gio/gio.override @@ -35,7 +35,7 @@ headers typedef struct { PyObject *callback; PyObject *data; -} PyGAsyncRequestNotify; +} PyGIONotify; static void py_decref_callback (gpointer data) @@ -46,7 +46,7 @@ py_decref_callback (gpointer data) static void async_result_callback_marshal(GObject *source_object, GAsyncResult *result, - PyGAsyncRequestNotify *notify) + PyGIONotify *notify) { PyObject *ret; PyGILState_STATE state; @@ -73,7 +73,7 @@ async_result_callback_marshal(GObject *source_object, Py_DECREF(notify->callback); Py_XDECREF(notify->data); - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); pyg_gil_state_release(state); } @@ -234,13 +234,13 @@ _wrap_g_mount_unmount(PyGObject *self, { static char *kwlist[] = { "callback", "flags", "cancellable", "user_data", NULL }; - PyGAsyncRequestNotify *notify; + PyGIONotify *notify; PyObject *py_flags = NULL; PyGObject *py_cancellable = NULL; GMountUnmountFlags flags = G_MOUNT_UNMOUNT_NONE; GCancellable *cancellable; - notify = g_slice_new0(PyGAsyncRequestNotify); + notify = g_slice_new0(PyGIONotify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOO:GMount.unmount", @@ -251,14 +251,14 @@ _wrap_g_mount_unmount(PyGObject *self, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } if (!PyCallable_Check(notify->callback)) { PyErr_SetString(PyExc_TypeError, "callback argument not callable"); - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } Py_INCREF(notify->callback); diff --git a/gio/goutputstream.override b/gio/goutputstream.override index 193bdc7..3bcf3ce 100644 --- a/gio/goutputstream.override +++ b/gio/goutputstream.override @@ -67,9 +67,9 @@ _wrap_g_output_stream_write_async(PyGObject *self, int io_priority = G_PRIORITY_DEFAULT; PyGObject *pycancellable = NULL; GCancellable *cancellable; - PyGAsyncRequestNotify *notify; + PyGIONotify *notify; - notify = g_slice_new0(PyGAsyncRequestNotify); + notify = g_slice_new0(PyGIONotify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#O|iOO:OutputStream.write_async", @@ -80,14 +80,14 @@ _wrap_g_output_stream_write_async(PyGObject *self, &pycancellable, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } if (!PyCallable_Check(notify->callback)) { PyErr_SetString(PyExc_TypeError, "callback argument not callable"); - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } Py_INCREF(notify->callback); @@ -119,9 +119,9 @@ _wrap_g_output_stream_close_async(PyGObject *self, int io_priority = G_PRIORITY_DEFAULT; PyGObject *pycancellable = NULL; GCancellable *cancellable; - PyGAsyncRequestNotify *notify; + PyGIONotify *notify; - notify = g_slice_new0(PyGAsyncRequestNotify); + notify = g_slice_new0(PyGIONotify); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iOO:OutputStream.close_async", @@ -131,7 +131,7 @@ _wrap_g_output_stream_close_async(PyGObject *self, &pycancellable, ¬ify->data)) { - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } @@ -141,7 +141,7 @@ _wrap_g_output_stream_close_async(PyGObject *self, if (!PyCallable_Check(notify->callback)) { PyErr_SetString(PyExc_TypeError, "callback argument not callable"); - g_slice_free(PyGAsyncRequestNotify, notify); + g_slice_free(PyGIONotify, notify); return NULL; } Py_INCREF(notify->callback); diff --git a/tests/test_gio.py b/tests/test_gio.py index bac9cfc..2d39220 100644 --- a/tests/test_gio.py +++ b/tests/test_gio.py @@ -124,6 +124,37 @@ class TestFile(unittest.TestCase): loop = gobject.MainLoop() loop.run() + def testCopy(self): + if os.path.exists('copy.txt'): + os.unlink("copy.txt") + + source = gio.File('file.txt') + destination = gio.File('copy.txt') + try: + retval = source.copy(destination) + self.failUnless(retval) + + self.failUnless(os.path.exists('copy.txt')) + self.assertEqual(open('file.txt').read(), + open('copy.txt').read()) + finally: + os.unlink("copy.txt") + + self.called = False + def callback(current, total): + self.called = True + source = gio.File('file.txt') + destination = gio.File('copy.txt') + try: + retval = source.copy(destination, callback) + self.failUnless(retval) + + self.failUnless(os.path.exists('copy.txt')) + self.assertEqual(open('file.txt').read(), + open('copy.txt').read()) + self.failUnless(self.called) + finally: + os.unlink("copy.txt") class TestGFileEnumerator(unittest.TestCase): def setUp(self): |