Imported Upstream version 3.4.0
[platform/upstream/python-gobject.git] / gi / _glib / pygiochannel.c
1 /* -*- Mode: C; c-basic-offset: 4 -*- */
2
3 #ifdef HAVE_CONFIG_H
4 #  include <config.h>
5 #endif
6
7 #include <Python.h>
8 #include <pythread.h>
9 #include <structmember.h> /* for PyMemberDef */
10
11 #include "pyglib.h"
12 #include "pyglib-private.h"
13 #include "pygsource.h"
14
15 #include "pygiochannel.h"
16
17 typedef struct {
18     PyObject_HEAD
19     GIOChannel *channel;
20     int softspace;         /* to make print >> chan, "foo" ... work */
21 } PyGIOChannel;
22
23 PYGLIB_DEFINE_TYPE("gi._glib.IOChannel", PyGIOChannel_Type, PyGIOChannel)
24
25 static PyObject*
26 py_io_channel_next(PyGIOChannel *self)
27 {
28     PyObject* ret_obj = NULL;
29     gsize length = 0, terminator_pos;
30     gchar *str_return = NULL;
31     GError *error = NULL;
32     GIOStatus status;
33
34     status = g_io_channel_read_line(self->channel, &str_return, &length,
35                                     &terminator_pos, &error);
36     if (pyglib_error_check(&error))
37         return NULL;
38
39     if (status == G_IO_STATUS_EOF) {
40         PyErr_SetString(PyExc_StopIteration, "EOF");
41         return NULL;
42     }
43
44     ret_obj = PYGLIB_PyUnicode_FromStringAndSize(str_return, length);
45     g_free(str_return);
46     return ret_obj;
47 }
48
49 static PyObject*
50 py_io_channel_richcompare(PyObject *self, PyObject *other, int op)
51 {
52     if (Py_TYPE(self) == Py_TYPE(other) && 
53           Py_TYPE(self) == &PyGIOChannel_Type) {
54         return _pyglib_generic_ptr_richcompare(((PyGIOChannel*)self)->channel,
55                                                ((PyGIOChannel*)other)->channel,
56                                                op);
57     } else {
58        Py_INCREF(Py_NotImplemented);
59        return Py_NotImplemented;
60     }
61 }
62
63 static PyObject*
64 py_io_channel_get_iter(PyObject *self)
65 {
66     Py_INCREF(self);
67     return self;
68 }
69
70 static long
71 py_io_channel_hash(PyGIOChannel *self)
72 {
73     return (long) self->channel;
74 }
75
76 static void
77 py_io_channel_dealloc(PyGIOChannel *self)
78 {
79     if (self->channel)
80         g_io_channel_unref(self->channel);
81     PyObject_DEL(self);
82 }
83
84 static PyObject*
85 py_io_channel_shutdown(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
86 {
87     static char *kwlist[] = { "flush", NULL };
88     GIOStatus ret;
89     PyObject* flush = Py_True;
90     GError* error = NULL;
91
92     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:gi._glib.IOChannel.shutdown", kwlist, &flush))
93         return NULL;
94         
95     ret = g_io_channel_shutdown(self->channel, PyObject_IsTrue(flush), &error);
96     if (pyglib_error_check(&error))
97         return NULL;
98         
99     return PYGLIB_PyLong_FromLong(ret);
100 }
101
102 /* character encoding conversion involved functions.
103  */
104  
105 static PyObject*
106 py_io_channel_set_buffer_size(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
107 {
108     static char *kwlist[] = { "size", NULL };
109     int size;
110
111     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gi._glib.IOChannel.set_buffer_size", kwlist, &size))
112         return NULL;
113         
114     g_io_channel_set_buffer_size(self->channel, size);
115     
116     Py_INCREF(Py_None);
117     return Py_None;
118 }
119
120 static PyObject*
121 py_io_channel_get_buffer_size(PyGIOChannel* self)
122 {
123     return PYGLIB_PyLong_FromLong(g_io_channel_get_buffer_size(self->channel));
124 }
125
126 static PyObject*
127 py_io_channel_set_buffered(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
128 {
129     static char *kwlist[] = { "buffered", NULL };
130     int buffered;
131
132     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gi._glib.IOChannel.set_buffered", kwlist, &buffered))
133         return NULL;
134         
135     g_io_channel_set_buffered(self->channel, buffered);
136     
137     Py_INCREF(Py_None);
138     return Py_None;
139 }
140
141 static PyObject*
142 py_io_channel_get_buffered(PyGIOChannel* self)
143 {
144     return PYGLIB_PyLong_FromLong(g_io_channel_get_buffered(self->channel));
145 }
146
147 static PyObject*
148 py_io_channel_set_encoding(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
149 {
150     static char *kwlist[] = { "encoding", NULL };
151     const char* encoding;
152     GError* error = NULL;
153     
154     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z:gi._glib.IOChannel.set_encoding", kwlist, &encoding))
155         return NULL;
156     
157     g_io_channel_set_encoding(self->channel, encoding, &error);
158     if (pyglib_error_check(&error))
159         return NULL;
160     
161     Py_INCREF(Py_None);
162     return Py_None;
163 }
164
165 static PyObject*
166 py_io_channel_get_encoding(PyGIOChannel* self)
167 {
168     const char* encoding = g_io_channel_get_encoding(self->channel);
169     
170     if (encoding == NULL) {
171         Py_INCREF(Py_None);
172         return Py_None;
173     }
174
175     return PYGLIB_PyUnicode_FromString(encoding);
176 }
177
178 #define CHUNK_SIZE (8 * 1024)
179
180 static PyObject*
181 py_io_channel_read_chars(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
182 {
183     static char *kwlist[] = { "max_count", NULL };
184     int max_count = -1;
185     PyObject* ret_obj = NULL;
186     gsize total_read = 0;
187     GError* error = NULL;
188     GIOStatus status = G_IO_STATUS_NORMAL;
189
190     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gi._glib.IOChannel.read", kwlist, &max_count))
191         return NULL;
192         
193     if (max_count == 0)
194         return PYGLIB_PyUnicode_FromString("");
195     
196     while (status == G_IO_STATUS_NORMAL
197            && (max_count == -1 || total_read < max_count)) {
198         gsize single_read;
199         char* buf;
200         gsize buf_size;
201         
202         if (max_count == -1) 
203             buf_size = CHUNK_SIZE;
204         else {
205             buf_size = max_count - total_read;
206             if (buf_size > CHUNK_SIZE)
207                 buf_size = CHUNK_SIZE;
208         }
209         
210         if ( ret_obj == NULL ) {
211             ret_obj = PYGLIB_PyBytes_FromStringAndSize((char *)NULL, buf_size);
212             if (ret_obj == NULL)
213                 goto failure;
214         }
215         else if (buf_size + total_read > PYGLIB_PyBytes_Size(ret_obj)) {
216             if (PYGLIB_PyBytes_Resize(&ret_obj, buf_size + total_read) == -1)
217                 goto failure;
218         }
219        
220         buf = PYGLIB_PyBytes_AsString(ret_obj) + total_read;
221
222         pyglib_unblock_threads();
223         status = g_io_channel_read_chars(self->channel, buf, buf_size, 
224                                          &single_read, &error);
225         pyglib_block_threads();
226         if (pyglib_error_check(&error))
227             goto failure;
228         
229         total_read += single_read;
230     }
231         
232     if ( total_read != PYGLIB_PyBytes_Size(ret_obj) ) {
233         if (PYGLIB_PyBytes_Resize(&ret_obj, total_read) == -1)
234             goto failure;
235     }
236
237 #if PY_VERSION_HEX >= 0x03000000
238     /* If this is not UTF8 encoded channel return the raw bytes */
239     if (g_io_channel_get_encoding(self->channel) != NULL)
240         return ret_obj;
241
242     /* convert to Unicode string */
243     {
244         PyObject *unicode_obj;
245
246         unicode_obj = PyUnicode_FromString(PyBytes_AS_STRING(ret_obj));
247         if (unicode_obj == NULL)
248             goto failure;
249         Py_DECREF(ret_obj);
250         ret_obj = unicode_obj;
251     }
252 #endif
253
254     return ret_obj;
255
256   failure:
257     Py_XDECREF(ret_obj);
258     return NULL;
259 }
260
261 static PyObject*
262 py_io_channel_write_chars(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
263 {
264     static char *kwlist[] = { "buf", NULL };
265     const char* buf;
266     Py_ssize_t buf_len;
267     gsize count;
268     GError* error = NULL;
269     GIOStatus status;
270
271     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#:gi._glib.IOChannel.write",
272                                      kwlist, &buf, &buf_len))
273         return NULL;
274         
275     pyglib_unblock_threads();
276     status = g_io_channel_write_chars(self->channel, buf, buf_len, &count, &error);
277     pyglib_block_threads();
278     if (pyglib_error_check(&error))
279         return NULL;
280         
281     return PYGLIB_PyLong_FromLong(count);
282 }
283
284 static PyObject*
285 py_io_channel_write_lines(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
286 {
287     static char *kwlist[] = { "lines", NULL };
288     char *buf;
289     Py_ssize_t buf_len;
290     gsize count;
291     GError* error = NULL;
292     GIOStatus status;
293     PyObject *iter, *value, *pylines;
294
295     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:gi._glib.IOChannel.writelines",
296                                      kwlist, &pylines))
297         return NULL;
298
299     iter = PyObject_GetIter(pylines);
300     
301     while (1) {
302         value = PyIter_Next(iter);
303         if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
304             PyErr_Clear();
305             goto normal_exit;
306         }
307         if (!PYGLIB_PyUnicode_Check(value)) {
308             PyErr_SetString(PyExc_TypeError, "gi._glib.IOChannel.writelines must"
309                             " be sequence/iterator of strings");
310             Py_DECREF(iter);
311             return NULL;
312         }
313         PYGLIB_PyUnicode_AsStringAndSize(value, &buf, &buf_len);
314         pyglib_unblock_threads();
315         status = g_io_channel_write_chars(self->channel, buf, buf_len, &count, &error);
316         pyglib_unblock_threads();
317         Py_DECREF(value);
318         if (pyglib_error_check(&error)) {
319             Py_DECREF(iter);
320             return NULL;
321         }
322     }
323 normal_exit:
324     Py_DECREF(iter);
325     Py_INCREF(Py_None);
326     return Py_None;
327 }
328
329 static PyObject*
330 py_io_channel_flush(PyGIOChannel* self)
331 {
332     GError* error = NULL;
333     GIOStatus status;
334         
335     pyglib_unblock_threads();
336     status = g_io_channel_flush(self->channel, &error);
337     pyglib_block_threads();
338     if (pyglib_error_check(&error))
339         return NULL;
340         
341     return PYGLIB_PyLong_FromLong(status);
342 }
343
344 static PyObject*
345 py_io_channel_set_flags(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
346 {
347     static char *kwlist[] = { "flags", NULL };
348     GIOFlags flags;
349     GIOStatus status;
350     GError* error = NULL;
351
352     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:gi._glib.IOChannel.set_flags",
353                                      kwlist, &flags))
354         return NULL;
355         
356     status = g_io_channel_set_flags(self->channel, flags, &error);
357     if (pyglib_error_check(&error))
358         return NULL;
359         
360     return PYGLIB_PyLong_FromLong(status);
361 }
362
363 static PyObject*
364 py_io_channel_get_flags(PyGIOChannel* self)
365 {
366     return PYGLIB_PyLong_FromLong(g_io_channel_get_flags(self->channel));
367 }
368
369 static PyObject*
370 py_io_channel_get_buffer_condition(PyGIOChannel* self)
371 {
372     return PYGLIB_PyLong_FromLong(g_io_channel_get_buffer_condition(self->channel));
373 }
374
375 static PyObject*
376 py_io_channel_set_close_on_unref(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
377 {
378     static char *kwlist[] = { "do_close", NULL };
379     PyObject *do_close;
380
381     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:gi._glib.IOChannel.set_close_on_unref",
382                                      kwlist, &do_close))
383         return NULL;
384         
385     g_io_channel_set_close_on_unref(self->channel, PyObject_IsTrue(do_close));
386     Py_INCREF(Py_None);
387     return Py_None;
388 }
389
390 static PyObject*
391 py_io_channel_get_close_on_unref(PyGIOChannel* self)
392 {
393     if (g_io_channel_get_close_on_unref(self->channel)) {
394         Py_INCREF(Py_True);
395         return Py_True;
396     } else {
397         Py_INCREF(Py_False);
398         return Py_False;
399     }
400 }
401
402 typedef struct {
403     PyObject *callback;
404     PyObject *iochannel;
405     PyObject *user_data;
406 } PyGIOWatchData;
407
408 static void
409 pyg_iowatch_data_free(PyGIOWatchData *data)
410 {
411     Py_DECREF(data->callback);
412     Py_XDECREF(data->user_data);
413     Py_DECREF(data->iochannel);
414     g_slice_free(PyGIOWatchData, data);
415 }
416
417 static gboolean
418 pyg_iowatch_marshal(GIOChannel *source,
419                     GIOCondition condition,
420                     gpointer user_data)
421 {
422     PyObject *ret;
423     gboolean res;
424     PyGIOWatchData *data = (PyGIOWatchData *) user_data;
425     PyGILState_STATE state;
426
427     g_return_val_if_fail(user_data != NULL, FALSE);
428     g_return_val_if_fail(((PyGIOChannel *) data->iochannel)->channel == source,
429                          FALSE);
430
431     state = pyglib_gil_state_ensure();
432
433     if (data->user_data)
434         ret = PyObject_CallFunction(data->callback, "OiO", data->iochannel,
435                                     condition, data->user_data);
436     else
437         ret = PyObject_CallFunction(data->callback, "Oi", data->iochannel,
438                                     condition);
439
440     if (!ret) {
441         PyErr_Print();
442         res = FALSE;
443     } else {
444         res = PyObject_IsTrue(ret);
445         Py_DECREF(ret);
446     }
447     pyglib_gil_state_release(state);
448
449     return res;
450 }
451
452
453
454 static PyObject *
455 py_io_channel_add_watch(PyObject *self, PyObject *args, PyObject *kwargs)
456 {
457     static char *kwlist[] = { "condition", "callback", "user_data", "priority", NULL };
458     PyObject *callback, *user_data = NULL;
459     int priority = G_PRIORITY_DEFAULT, condition;
460     GIOChannel *iochannel = NULL;
461     guint handler_id;
462     PyGIOWatchData *data;
463
464     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
465                                      "iO|Oi:gi._glib.IOChannel.add_watch",
466                                      kwlist, &condition, &callback,
467                                      &user_data, &priority))
468         return NULL;
469
470     iochannel = ((PyGIOChannel *) self)->channel;
471
472     if (!PyCallable_Check(callback)) {
473         PyErr_SetString(PyExc_TypeError, "second must be callable");
474         return NULL;
475     }
476
477     data = g_slice_new(PyGIOWatchData);
478     data->callback = callback; Py_INCREF(callback);
479     data->user_data = user_data; Py_XINCREF(user_data);
480     data->iochannel = self; Py_INCREF(self);
481
482     handler_id = g_io_add_watch_full(iochannel,
483                                      priority, condition,
484                                      pyg_iowatch_marshal, data,
485                                      (GDestroyNotify) pyg_iowatch_data_free);
486     return PyLong_FromUnsignedLong(handler_id);
487 }
488
489
490 #ifdef G_OS_WIN32
491
492 static PyObject *
493 py_io_channel_win32_poll(PyObject *self, PyObject *args, PyObject *kwargs)
494 {
495     static char *kwlist[] = { "fds", "timeout", NULL };
496     GPollFD *pollfd;
497     PyObject *pyfds, *pyfd;
498     guint len, i;
499     gint timeout = -1;
500     gint result;
501
502     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
503                                      "O!|i:gi._glib.IOChannel.win32_poll",
504                                      kwlist, &PyList_Type, &pyfds, &timeout))
505         return NULL;
506
507     len = PyList_Size(pyfds);
508     pollfd = g_newa(GPollFD, len);
509     for (i = 0; i < len; ++i) {
510         pyfd = PyList_GET_ITEM(pyfds, i);
511         if (!PyObject_TypeCheck(pyfd, &PyGPollFD_Type)) {
512             PyErr_SetString(PyExc_TypeError, "'fds' must be a list of gi._glib.PollFD objects");
513             return NULL;
514         }
515         pollfd[i] = ((PyGPollFD *) pyfd)->pollfd;
516     }
517
518     result = g_io_channel_win32_poll(pollfd, len, timeout);
519     for (i = 0; i < len; ++i) {
520         pyfd = PyList_GET_ITEM(pyfds, i);
521         ((PyGPollFD *) pyfd)->pollfd = pollfd[i];
522     }
523     return PYGLIB_PyLong_FromLong(result);
524 }
525
526 static PyObject *
527 py_io_channel_win32_make_pollfd(PyObject *self, PyObject *args, PyObject *kwargs)
528 {
529     static char *kwlist[] = { "condition", NULL };
530     int condition;
531     GPollFD pollfd;
532     PyGPollFD *pypollfd;
533
534     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
535                                      "i:gi._glib.IOChannel.win32_make_pollfd",
536                                      kwlist, &condition))
537         return NULL;
538
539     g_io_channel_win32_make_pollfd(((PyGIOChannel *) self)->channel,
540                                    condition, &pollfd);
541     pypollfd = PyObject_NEW(PyGPollFD, &PyGPollFD_Type);
542     pypollfd->pollfd = pollfd;
543     return (PyObject *) pypollfd;
544 }
545 #endif /* def G_OS_WIN32 */
546
547
548 static PyObject*
549 py_io_channel_read_line(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
550 {
551     static char *kwlist[] = { "size", NULL };
552     PyObject* ret_obj = NULL;
553     gsize length = 0, terminator_pos;
554     gchar *str_return = NULL;
555     GError *error = NULL;
556     gint size_hint = -1;
557     GIOStatus status;
558
559     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gi._glib.IOChannel.readline", kwlist,
560                                      &size_hint))
561         return NULL;
562
563     status = g_io_channel_read_line(self->channel, &str_return, &length,
564                                     &terminator_pos, &error);
565     if (pyglib_error_check(&error))
566         return NULL;
567     ret_obj = PYGLIB_PyUnicode_FromStringAndSize(str_return, length);
568     g_free(str_return);
569     return ret_obj;
570 }
571
572 static PyObject*
573 py_io_channel_read_lines(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
574 {
575     static char *kwlist[] = { "size", NULL };
576     PyObject *line = NULL;
577     gsize length = 0, terminator_pos;
578     gchar *str_return = NULL;
579     GError *error = NULL;
580     gint size_hint = -1;
581     GIOStatus status = G_IO_STATUS_NORMAL;
582     PyObject *list;
583
584     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:gi._glib.IOChannel.readlines", kwlist,
585                                      &size_hint))
586         return NULL;
587
588     list = PyList_New(0);
589     while (status == G_IO_STATUS_NORMAL) {
590         status = g_io_channel_read_line(self->channel, &str_return, &length,
591                                         &terminator_pos, &error);
592         if (pyglib_error_check(&error)) {
593             Py_DECREF(line);
594             return NULL;
595         }
596         line = PYGLIB_PyUnicode_FromStringAndSize(str_return, length);
597         g_free(str_return);
598         if (PyList_Append(list, line)) {
599             Py_DECREF(line);
600             Py_DECREF(list);
601             return NULL;
602         }
603     }
604     return list;
605 }
606
607
608 static PyObject*
609 py_io_channel_seek(PyGIOChannel* self, PyObject *args, PyObject *kwargs)
610 {
611     static char *kwlist[] = { "offset", "whence", NULL };
612     gint64 offset;
613     int whence = 0;
614     GIOStatus status;
615     GSeekType seek_type;
616     GError* error = NULL;
617
618     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "L|i:gi._glib.IOChannel.seek",
619                                      kwlist, &offset, &whence))
620         return NULL;
621
622     switch (whence)
623     {
624     case 0: seek_type = G_SEEK_SET; break;
625     case 1: seek_type = G_SEEK_CUR; break;
626     case 2: seek_type = G_SEEK_END; break;
627     default:
628         PyErr_SetString(PyExc_ValueError, "invalid 'whence' value");
629         return NULL;
630     }
631         
632     status = g_io_channel_seek_position(self->channel, offset,
633                                         seek_type, &error);
634     if (pyglib_error_check(&error))
635         return NULL;
636         
637     return PYGLIB_PyLong_FromLong(status);
638 }
639
640 #if 0 // Not wrapped
641 void                  g_io_channel_set_line_term        (GIOChannel   *channel,
642                                                          const gchar  *line_term,
643                                                          gint          length);
644
645 G_CONST_RETURN gchar* g_io_channel_get_line_term        (GIOChannel   *channel,
646                                                          gint         *length);
647
648
649
650 GIOStatus   g_io_channel_read_line_string (GIOChannel   *channel,
651                                            GString      *buffer,
652                                            gsize        *terminator_pos,
653                                            GError      **error);
654 GIOStatus   g_io_channel_read_to_end      (GIOChannel   *channel,
655                                            gchar       **str_return,
656                                            gsize        *length,
657                                            GError      **error);
658 GIOStatus   g_io_channel_read_unichar     (GIOChannel   *channel,
659                                            gunichar     *thechar,
660                                            GError      **error);
661 GIOStatus   g_io_channel_write_unichar    (GIOChannel   *channel,
662                                            gunichar      thechar,
663                                            GError      **error);
664 #endif // Not wrapped
665
666 static PyMemberDef py_io_channel_members[] = {
667     { "softspace", T_INT, offsetof(PyGIOChannel, softspace), 0, NULL },
668     { NULL, 0, 0, 0, NULL }
669 };
670
671 static PyMethodDef py_io_channel_methods[] = {
672     { "close", (PyCFunction)py_io_channel_shutdown, METH_VARARGS|METH_KEYWORDS },
673     { "flush", (PyCFunction)py_io_channel_flush, METH_NOARGS },
674     { "set_encoding", (PyCFunction)py_io_channel_set_encoding, METH_VARARGS|METH_KEYWORDS },
675     { "get_encoding", (PyCFunction)py_io_channel_get_encoding, METH_NOARGS },
676     { "set_buffered", (PyCFunction)py_io_channel_set_buffered, METH_VARARGS|METH_KEYWORDS },
677     { "get_buffered", (PyCFunction)py_io_channel_get_buffered, METH_NOARGS },
678     { "set_buffer_size", (PyCFunction)py_io_channel_set_buffer_size, METH_VARARGS|METH_KEYWORDS },
679     { "get_buffer_size", (PyCFunction)py_io_channel_get_buffer_size, METH_NOARGS },
680     { "read", (PyCFunction)py_io_channel_read_chars, METH_VARARGS|METH_KEYWORDS },
681     { "readline", (PyCFunction)py_io_channel_read_line, METH_VARARGS|METH_KEYWORDS },
682     { "readlines", (PyCFunction)py_io_channel_read_lines, METH_VARARGS|METH_KEYWORDS },
683     { "write", (PyCFunction)py_io_channel_write_chars, METH_VARARGS|METH_KEYWORDS },
684     { "writelines", (PyCFunction)py_io_channel_write_lines, METH_VARARGS|METH_KEYWORDS },
685     { "set_flags", (PyCFunction)py_io_channel_set_flags, METH_VARARGS|METH_KEYWORDS },
686     { "get_flags", (PyCFunction)py_io_channel_get_flags, METH_NOARGS },
687     { "get_buffer_condition", (PyCFunction)py_io_channel_get_buffer_condition, METH_NOARGS },
688     { "set_close_on_unref", (PyCFunction)py_io_channel_set_close_on_unref, METH_VARARGS | METH_KEYWORDS },
689     { "get_close_on_unref", (PyCFunction)py_io_channel_get_close_on_unref, METH_NOARGS },
690     { "add_watch", (PyCFunction)py_io_channel_add_watch, METH_VARARGS|METH_KEYWORDS },
691     { "seek", (PyCFunction)py_io_channel_seek, METH_VARARGS|METH_KEYWORDS },
692 #ifdef G_OS_WIN32
693     { "win32_make_pollfd", (PyCFunction)py_io_channel_win32_make_pollfd, METH_VARARGS | METH_KEYWORDS },
694     { "win32_poll", (PyCFunction)py_io_channel_win32_poll, METH_VARARGS|METH_KEYWORDS|METH_STATIC },
695 #endif
696     { NULL, NULL, 0 }
697 };
698
699
700 static int
701 py_io_channel_init(PyGIOChannel *self, PyObject *args, PyObject *kwargs)
702 {
703     static char *kwlist[] = { "filedes", "filename", "mode",
704 #ifdef G_OS_WIN32
705                               "hwnd",
706 #endif
707                               NULL };
708     int fd = -1;
709     char *mode = "r", *filename = NULL;
710     GError *error = NULL;
711 #ifdef G_OS_WIN32
712     guint hwnd = 0;
713 #endif
714
715     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iss"
716 #ifdef G_OS_WIN32
717                                      "I"
718 #endif
719                                      ":gi._glib.IOChannel.__init__",
720                                      kwlist, &fd, &filename, &mode
721 #ifdef G_OS_WIN32
722                                      , &hwnd
723 #endif
724             ))
725         return -1;
726
727     if (fd != -1)
728         self->channel = g_io_channel_unix_new(fd);
729     else if (filename != NULL) {
730         self->channel = g_io_channel_new_file(filename, mode, &error);
731         if (pyglib_error_check(&error))
732             return -1;
733     }
734 #ifdef G_OS_WIN32
735     else if (hwnd != 0) {
736         self->channel = g_io_channel_win32_new_messages(hwnd);
737     }
738 #endif
739     else {
740 #ifdef G_OS_WIN32
741         PyErr_SetString(PyExc_TypeError, "either a valid file descriptor, "
742                         "file name, or window handle must be supplied");
743 #else
744         PyErr_SetString(PyExc_TypeError, "either a valid file descriptor "
745                         "or file name must be supplied");
746 #endif
747         return -1;
748     }
749     return 0;
750 }
751
752 void
753 pyglib_iochannel_register_types(PyObject *d)
754 {
755     PyGIOChannel_Type.tp_init = (initproc)py_io_channel_init;
756     PyGIOChannel_Type.tp_dealloc = (destructor)py_io_channel_dealloc;
757     PyGIOChannel_Type.tp_flags = Py_TPFLAGS_DEFAULT;
758     PyGIOChannel_Type.tp_members = py_io_channel_members;
759     PyGIOChannel_Type.tp_methods = py_io_channel_methods;
760     PyGIOChannel_Type.tp_hash = (hashfunc)py_io_channel_hash;
761     PyGIOChannel_Type.tp_richcompare = (richcmpfunc)py_io_channel_richcompare;
762     PyGIOChannel_Type.tp_iter = (getiterfunc)py_io_channel_get_iter;
763     PyGIOChannel_Type.tp_iternext = (iternextfunc)py_io_channel_next;
764
765     PYGLIB_REGISTER_TYPE(d, PyGIOChannel_Type, "IOChannel");
766 }