pygobject r950 - in trunk: . gio tests
- From: paulp svn gnome org
- To: svn-commits-list gnome org
- Subject: pygobject r950 - in trunk: . gio tests
- Date: Wed, 27 Aug 2008 21:22:08 +0000 (UTC)
Author: paulp
Date: Wed Aug 27 21:22:08 2008
New Revision: 950
URL: http://svn.gnome.org/viewvc/pygobject?rev=950&view=rev
Log:
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.
Modified:
trunk/ChangeLog
trunk/gio/ginputstream.override
trunk/gio/gio.defs
trunk/gio/gio.override
trunk/gio/goutputstream.override
trunk/tests/test_gio.py
Modified: trunk/gio/ginputstream.override
==============================================================================
--- trunk/gio/ginputstream.override (original)
+++ trunk/gio/ginputstream.override Wed Aug 27 21:22:08 2008
@@ -91,7 +91,7 @@
&pycancellable))
return NULL;
- buffersize = BUFSIZE;
+ buffersize = (count < 0 ? BUFSIZE : count);
if (!pygio_check_cancellable(pycancellable, &cancellable))
return NULL;
@@ -111,31 +111,99 @@
&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) {
+ /* 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;
+
+ 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)
+ if (bytesread < buffersize || chunksize == 0) {
+ /* End of file. */
break;
+ }
- if (count < 0)
- {
- buffersize += BUFSIZE;
- if (_PyString_Resize(&v, buffersize) < 0)
- return NULL;
- }
- else
+ 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 @@
Py_INCREF(Py_None);
return Py_None;
}
-/* GInputStream.read_all: No ArgType for void* */
/* GInputStream.skip_async: No ArgType for GAsyncReadyCallback */
Modified: trunk/gio/gio.defs
==============================================================================
--- trunk/gio/gio.defs (original)
+++ trunk/gio/gio.defs Wed Aug 27 21:22:08 2008
@@ -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
Modified: trunk/gio/gio.override
==============================================================================
--- trunk/gio/gio.override (original)
+++ trunk/gio/gio.override Wed Aug 27 21:22:08 2008
@@ -105,7 +105,6 @@
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
Modified: trunk/gio/goutputstream.override
==============================================================================
--- trunk/gio/goutputstream.override (original)
+++ trunk/gio/goutputstream.override Wed Aug 27 21:22:08 2008
@@ -54,6 +54,40 @@
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,
Modified: trunk/tests/test_gio.py
==============================================================================
--- trunk/tests/test_gio.py (original)
+++ trunk/tests/test_gio.py Wed Aug 27 21:22:08 2008
@@ -485,6 +485,46 @@
def testRead(self):
self.assertEquals(self.stream.read(), "testing")
+ self.stream = gio.MemoryInputStream()
+ self.assertEquals(self.stream.read(), '')
+
+ self.stream = gio.MemoryInputStream()
+ some_data = open("test_gio.py", "rb").read()
+ self.stream.add_data(some_data)
+ self.assertEquals(self.stream.read(), some_data)
+
+ stream = gio.MemoryInputStream()
+ stream.add_data(some_data)
+ self.assertEquals(self._read_in_loop(stream,
+ lambda: stream.read(50),
+ 50),
+ some_data)
+
+ def test_read_part(self):
+ self.assertEquals(self._read_in_loop(self.stream,
+ lambda: self.stream.read_part()),
+ 'testing')
+
+ stream = gio.MemoryInputStream()
+ some_data = open('test_gio.py', 'rb').read()
+ stream.add_data(some_data)
+ self.assertEquals(self._read_in_loop(stream,
+ lambda: stream.read_part(50),
+ 50),
+ some_data)
+
+ def _read_in_loop(self, stream, reader, size_limit=0):
+ read_data = ''
+ while True:
+ read_part = reader()
+ if read_part:
+ read_data += read_part
+ if size_limit > 0:
+ self.assert_(len(read_part) <= size_limit,
+ '%d <= %d' % (len(read_part), size_limit))
+ else:
+ return read_data
+
def testReadAsync(self):
def callback(stream, result):
self.assertEquals(result.get_op_res_gssize(), 7)
@@ -595,6 +635,23 @@
self.failUnless(os.path.exists("outputstream.txt"))
self.assertEquals(open("outputstream.txt").read(), "testing")
+ def test_write_part(self):
+ stream = gio.MemoryOutputStream()
+ some_data = open('test_gio.py', 'rb').read()
+ buffer = some_data
+
+ # In fact this makes only one looping (memory stream is fast,
+ # write_part behaves just like write), but let's still be
+ # complete.
+ while buffer:
+ written = stream.write_part(buffer)
+ if written == len(buffer):
+ break
+ else:
+ buffer = buffer[written:]
+
+ self.assertEquals(stream.get_contents(), some_data)
+
def testWriteAsync(self):
def callback(stream, result):
self.assertEquals(result.get_op_res_gssize(), 7)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]