diff options
| author | Paul Pogonyshev <pogonyshev@gmx.net> | 2008-08-27 21:22:08 +0000 |
|---|---|---|
| committer | Paul Pogonyshev <paulp@src.gnome.org> | 2008-08-27 21:22:08 +0000 |
| commit | 30eb71d505abcbaf42d098dac62d0c747338d910 (patch) | |
| tree | d0866a230255838c94dee43f1db5b3be199e3541 /gio | |
| parent | 70ede7ebbceb28e420c31d5ceb68e8abdd6216a5 (diff) | |
| download | pygobject-30eb71d505abcbaf42d098dac62d0c747338d910.tar.gz pygobject-30eb71d505abcbaf42d098dac62d0c747338d910.tar.xz pygobject-30eb71d505abcbaf42d098dac62d0c747338d910.zip | |
Rename from read(), document. (gio.InputStream.read): Rename from
2008-08-28 Paul Pogonyshev <pogonyshev@gmx.net>
* gio/gio.defs (gio.InputStream.read_part): Rename from read(),
document.
(gio.InputStream.read): Rename from read_all(), document.
(gio.OutputStream.write_part): Rename from write(), document.
(gio.OutputStream.write): Rename from write_all(), document.
* gio/ginputstream.override (_wrap_g_input_stream_read): Fix
several bugs.
(_wrap_g_input_stream_read_all): New function.
* gio/goutputstream.override (_wrap_g_output_stream_write_all):
New function.
* tests/test_gio.py (TestInputStream.testRead): Add more tests.
(TestInputStream.test_read_part): New test.
(TestInputStream._read_in_loop): New helper method.
(TestOutputStream.test_write_part): New test.
svn path=/trunk/; revision=950
Diffstat (limited to 'gio')
| -rw-r--r-- | gio/ginputstream.override | 109 | ||||
| -rw-r--r-- | gio/gio.defs | 65 | ||||
| -rw-r--r-- | gio/gio.override | 1 | ||||
| -rw-r--r-- | gio/goutputstream.override | 34 |
4 files changed, 183 insertions, 26 deletions
diff --git a/gio/ginputstream.override b/gio/ginputstream.override index 44378cd..b320034 100644 --- a/gio/ginputstream.override +++ b/gio/ginputstream.override @@ -91,7 +91,7 @@ _wrap_g_input_stream_read(PyGObject *self, PyObject *args, PyObject *kwargs) &pycancellable)) return NULL; - buffersize = BUFSIZE; + buffersize = (count < 0 ? BUFSIZE : count); if (!pygio_check_cancellable(pycancellable, &cancellable)) return NULL; @@ -111,31 +111,99 @@ _wrap_g_input_stream_read(PyGObject *self, PyObject *args, PyObject *kwargs) &error); pyg_end_allow_threads; - if (pyg_error_check(&error)) - { - Py_DECREF(v); - return NULL; - } - else if (chunksize == 0) - { - PyErr_SetFromErrno(PyExc_IOError); - Py_DECREF(v); - return NULL; - } + if (pyg_error_check(&error)) { + Py_DECREF(v); + return NULL; + } + if (chunksize == 0) { + /* End of file. */ + break; + } bytesread += chunksize; - if (bytesread < buffersize) + if (bytesread < buffersize) { + /* g_input_stream_read() decided to not read full buffer. We + * then return early too, even if 'count' is less than 0. + */ + break; + } + + if (count < 0) { + buffersize += BUFSIZE; + if (_PyString_Resize(&v, buffersize) < 0) + return NULL; + } + else { + /* Got what was requested. */ break; + } + } + + if (bytesread != buffersize) + _PyString_Resize(&v, bytesread); + + return v; +} +%% +override g_input_stream_read_all kwargs +static PyObject * +_wrap_g_input_stream_read_all(PyGObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "count", "cancellable", NULL }; + PyGObject *pycancellable = NULL; + PyObject *v; + GCancellable *cancellable; + long count = -1; + GError *error = NULL; + size_t bytesread, buffersize, chunksize; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|lO:InputStream.read", + kwlist, &count, + &pycancellable)) + return NULL; + + buffersize = (count < 0 ? BUFSIZE : count); + + if (!pygio_check_cancellable(pycancellable, &cancellable)) + return NULL; + + v = PyString_FromStringAndSize((char *)NULL, buffersize); + if (v == NULL) + return NULL; - if (count < 0) - { - buffersize += BUFSIZE; - if (_PyString_Resize(&v, buffersize) < 0) - return NULL; - } - else + bytesread = 0; + for (;;) + { + pyg_begin_allow_threads; + errno = 0; + g_input_stream_read_all(G_INPUT_STREAM(self->obj), + PyString_AS_STRING((PyStringObject *)v) + bytesread, + buffersize - bytesread, + &chunksize, + cancellable, &error); + pyg_end_allow_threads; + + if (pyg_error_check(&error)) { + Py_DECREF(v); + return NULL; + } + + bytesread += chunksize; + if (bytesread < buffersize || chunksize == 0) { + /* End of file. */ + break; + } + + if (count < 0) { + buffersize += BUFSIZE; + if (_PyString_Resize(&v, buffersize) < 0) + return NULL; + } + else { /* Got what was requested. */ break; + } } if (bytesread != buffersize) @@ -384,5 +452,4 @@ _wrap_g_memory_input_stream_add_data(PyGObject *self, Py_INCREF(Py_None); return Py_None; } -/* GInputStream.read_all: No ArgType for void* */ /* GInputStream.skip_async: No ArgType for GAsyncReadyCallback */ diff --git a/gio/gio.defs b/gio/gio.defs index 9ca1397..ce4ee5a 100644 --- a/gio/gio.defs +++ b/gio/gio.defs @@ -3177,8 +3177,26 @@ (return-type "GType") ) -(define-method read +;; Note: the following two methods are renamed for consistency with +;; Python file objects' read(). I.e. g_input_stream_read_all() is +;; more like Python file.read(), so it is renamed read(). Since now +;; there is a name clash, g_input_stream_read() is renamed +;; read_part(). +(define-method read_part (of-object "GInputStream") + (docstring + "STREAM.read_part([count, [cancellable]]) -> string\n" + "\n" + "Read 'count' bytes from the stream. If 'count' is not specified or is\n" + "omitted, read until the end of the stream. This method is allowed to\n" + "stop at any time after reading at least 1 byte from the stream. E.g.\n" + "when reading over a (relatively slow) HTTP connection, it will often\n" + "stop after receiving one packet. Therefore, to reliably read requested\n" + "number of bytes, you need to use a loop. See also gio.InputStream.read\n" + "for easier to use (though less efficient) method.\n" + "\n" + "Note: this method roughly corresponds to C GIO g_input_stream_read." + ) (c-name "g_input_stream_read") (return-type "gssize") (parameters @@ -3189,8 +3207,21 @@ ) ) -(define-method read_all +;; See comments before the previous method definition. +(define-method read (of-object "GInputStream") + (docstring + "STREAM.read([count, [cancellable]]) -> string\n" + "\n" + "Read 'count' bytes from the stream. If 'count' is not specified or is\n" + "omitted, read until the end of the stream. This method will stop only\n" + "after reading requested number of bytes, reaching end of stream or\n" + "triggering an I/O error. See also gio.InputStream.read_part for more\n" + "efficient, but more cumbersome to use method.\n" + "\n" + "Note: this method roughly corresponds to C GIO g_input_stream_read_all.\n" + "It was renamed for consistency with Python standard file.read." + ) (c-name "g_input_stream_read_all") (return-type "gboolean") (parameters @@ -3976,8 +4007,24 @@ (return-type "GType") ) -(define-method write +;; Note: the following two methods are renamed for consistency with +;; Python file objects' write(). I.e. g_output_stream_write_all() is +;; more like Python file.write(), so it is renamed write(). Since now +;; there is a name clash, g_output_stream_write() is renamed +;; write_part(). +(define-method write_part (of-object "GOutputStream") + (docstring + "STREAM.write_part(buffer, [cancellable]) -> int\n" + "\n" + "Write the bytes in 'buffer' to the stream. Return the number of bytes\n" + "successfully written. This method is allowed to stop at any time after\n" + "writing at least 1 byte. Therefore, to reliably write the whole buffer,\n" + "you need to use a loop. See also gio.OutputStream.write for easier to\n" + "use (though less efficient) method.\n" + "\n" + "Note: this method roughly corresponds to C GIO g_output_stream_write." + ) (c-name "g_output_stream_write") (return-type "gssize") (parameters @@ -3988,8 +4035,18 @@ ) ) -(define-method write_all +;; See comments before the previous method definition. +(define-method write (of-object "GOutputStream") + "STREAM.write(buffer, [cancellable]) -> int\n" + "\n" + "Write the bytes in 'buffer' to the stream. Return the number of bytes\n" + "successfully written. This method will stop only after writing the whole\n" + "buffer or triggering an I/O error. See also gio.OutputStream.write_part\n" + "for more efficient, but more cumbersome to use method.\n" + "\n" + "Note: this method roughly corresponds to C GIO g_output_stream_write_all.\n" + "It was renamed for consistency with Python standard file.write." (c-name "g_output_stream_write_all") (return-type "gboolean") (parameters diff --git a/gio/gio.override b/gio/gio.override index 86009cb..431d220 100644 --- a/gio/gio.override +++ b/gio/gio.override @@ -105,7 +105,6 @@ ignore-glob g_file_new_from_path g_file_new_from_uri g_file_hash - g_input_stream_read_all g_io_error_quark g_simple_async_result_new_error g_simple_async_report_error_in_idle diff --git a/gio/goutputstream.override b/gio/goutputstream.override index 03a5da7..e525739 100644 --- a/gio/goutputstream.override +++ b/gio/goutputstream.override @@ -54,6 +54,40 @@ _wrap_g_output_stream_write(PyGObject *self, return PyInt_FromLong(written); } %% +override g_output_stream_write_all kwargs +static PyObject * +_wrap_g_output_stream_write_all(PyGObject *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "buffer", "cancellable", NULL }; + PyGObject *pycancellable = NULL; + gchar *buffer; + long count = 0; + GCancellable *cancellable; + GError *error = NULL; + gssize written; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "s#|O!:OutputStream.write", + kwlist, &buffer, &count, + &PyGCancellable_Type, &pycancellable)) + return NULL; + + if (!pygio_check_cancellable(pycancellable, &cancellable)) + return NULL; + + pyg_begin_allow_threads; + g_output_stream_write_all(G_OUTPUT_STREAM(self->obj), + buffer, count, &written, cancellable, &error); + pyg_end_allow_threads; + + if (pyg_error_check(&error)) + return NULL; + + return PyInt_FromLong(written); +} +%% override g_output_stream_write_async kwargs static PyObject * _wrap_g_output_stream_write_async(PyGObject *self, |
