dynconfig: added SBINDIR and BINDIR as updated dynconfig variables
[nivanova/samba-autobuild/.git] / lib / tevent / pytevent.c
1 /*
2    Unix SMB/CIFS implementation.
3    Python bindings for tevent
4
5    Copyright (C) Jelmer Vernooij 2010
6
7      ** NOTE! The following LGPL license applies to the tevent
8      ** library. This does NOT imply that all of Samba is released
9      ** under the LGPL
10
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Lesser General Public
13    License as published by the Free Software Foundation; either
14    version 3 of the License, or (at your option) any later version.
15
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Lesser General Public License for more details.
20
21    You should have received a copy of the GNU Lesser General Public
22    License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include <Python.h>
26 #include <tevent.h>
27
28 void init_tevent(void);
29
30 typedef struct {
31         PyObject_HEAD
32         struct tevent_context *ev;
33 } TeventContext_Object;
34
35 typedef struct {
36         PyObject_HEAD
37         struct tevent_queue *queue;
38 } TeventQueue_Object;
39
40 typedef struct {
41         PyObject_HEAD
42         struct tevent_req *req;
43 } TeventReq_Object;
44
45 typedef struct {
46         PyObject_HEAD
47         struct tevent_signal *signal;
48 } TeventSignal_Object;
49
50 typedef struct {
51         PyObject_HEAD
52         struct tevent_timer *timer;
53 } TeventTimer_Object;
54
55 typedef struct {
56         PyObject_HEAD
57         struct tevent_fd *fd;
58 } TeventFd_Object;
59
60 staticforward PyTypeObject TeventContext_Type;
61 staticforward PyTypeObject TeventReq_Type;
62 staticforward PyTypeObject TeventQueue_Type;
63 staticforward PyTypeObject TeventSignal_Type;
64 staticforward PyTypeObject TeventTimer_Type;
65 staticforward PyTypeObject TeventFd_Type;
66
67 static int py_context_init(struct tevent_context *ev)
68 {
69         /* FIXME */
70         return 0;
71 }
72
73 static struct tevent_fd *py_add_fd(struct tevent_context *ev,
74                                     TALLOC_CTX *mem_ctx,
75                                     int fd, uint16_t flags,
76                                     tevent_fd_handler_t handler,
77                                     void *private_data,
78                                     const char *handler_name,
79                                     const char *location)
80 {
81         /* FIXME */
82         return NULL;
83 }
84
85 static void py_set_fd_close_fn(struct tevent_fd *fde,
86                                 tevent_fd_close_fn_t close_fn)
87 {
88         /* FIXME */
89 }
90
91 static uint16_t py_get_fd_flags(struct tevent_fd *fde)
92 {
93         /* FIXME */
94         return 0;
95 }
96
97 static void py_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
98 {
99         /* FIXME */
100 }
101
102 /* timed_event functions */
103 static struct tevent_timer *py_add_timer(struct tevent_context *ev,
104                                           TALLOC_CTX *mem_ctx,
105                                           struct timeval next_event,
106                                           tevent_timer_handler_t handler,
107                                           void *private_data,
108                                           const char *handler_name,
109                                           const char *location)
110 {
111         /* FIXME */
112         return NULL;
113 }
114
115 /* immediate event functions */
116 static void py_schedule_immediate(struct tevent_immediate *im,
117                                    struct tevent_context *ev,
118                                    tevent_immediate_handler_t handler,
119                                    void *private_data,
120                                    const char *handler_name,
121                                    const char *location)
122 {
123         /* FIXME */
124 }
125
126 /* signal functions */
127 static struct tevent_signal *py_add_signal(struct tevent_context *ev,
128                                             TALLOC_CTX *mem_ctx,
129                                             int signum, int sa_flags,
130                                             tevent_signal_handler_t handler,
131                                             void *private_data,
132                                             const char *handler_name,
133                                             const char *location)
134 {
135         /* FIXME */
136         return NULL;
137 }
138
139 /* loop functions */
140 static int py_loop_once(struct tevent_context *ev, const char *location)
141 {
142         /* FIXME */
143         return 0;
144 }
145
146 static int py_loop_wait(struct tevent_context *ev, const char *location)
147 {
148         /* FIXME */
149         return 0;
150 }
151
152 const static struct tevent_ops py_tevent_ops = {
153         .context_init = py_context_init,
154         .add_fd = py_add_fd,
155         .set_fd_close_fn = py_set_fd_close_fn,
156         .get_fd_flags = py_get_fd_flags,
157         .set_fd_flags = py_set_fd_flags,
158         .add_timer = py_add_timer,
159         .schedule_immediate = py_schedule_immediate,
160         .add_signal = py_add_signal,
161         .loop_wait = py_loop_wait,
162         .loop_once = py_loop_once,
163 };
164
165 static PyObject *py_register_backend(PyObject *self, PyObject *args)
166 {
167         PyObject *name, *py_backend;
168
169         if (!PyArg_ParseTuple(args, "O", &py_backend))
170                 return NULL;
171
172         name = PyObject_GetAttrString(py_backend, "name");
173         if (name == NULL) {
174                 PyErr_SetNone(PyExc_AttributeError);
175                 return NULL;
176         }
177
178         if (!PyString_Check(name)) {
179                 PyErr_SetNone(PyExc_TypeError);
180                 return NULL;
181         }
182
183         if (!tevent_register_backend(PyString_AsString(name), &py_tevent_ops)) { /* FIXME: What to do with backend */
184                 PyErr_SetNone(PyExc_RuntimeError);
185                 return NULL;
186         }
187
188         Py_RETURN_NONE;
189 }
190
191 static PyObject *py_tevent_context_reinitialise(TeventContext_Object *self)
192 {
193         int ret = tevent_re_initialise(self->ev);
194         if (ret != 0) {
195                 PyErr_SetNone(PyExc_RuntimeError);
196                 return NULL;
197         }
198         Py_RETURN_NONE;
199 }
200
201 static PyObject *py_tevent_queue_stop(TeventQueue_Object *self)
202 {
203         tevent_queue_stop(self->queue);
204         Py_RETURN_NONE;
205 }
206
207 static PyObject *py_tevent_queue_start(TeventQueue_Object *self)
208 {
209         tevent_queue_start(self->queue);
210         Py_RETURN_NONE;
211 }
212
213 static void py_queue_trigger(struct tevent_req *req, void *private_data)
214 {
215         PyObject *callback = private_data, *ret;
216
217         ret = PyObject_CallFunction(callback, "");
218         Py_XDECREF(ret);
219 }
220
221 static PyObject *py_tevent_queue_add(TeventQueue_Object *self, PyObject *args)
222 {
223         TeventContext_Object *py_ev;
224         TeventReq_Object *py_req;
225         PyObject *trigger;
226         bool ret;
227
228         if (!PyArg_ParseTuple(args, "O!O!O", 
229                                                   &TeventContext_Type, &py_ev,
230                                                   &TeventReq_Type, &py_req,
231                                                   &trigger))
232                 return NULL;
233
234         Py_INCREF(trigger);
235
236         ret = tevent_queue_add(self->queue, py_ev->ev, py_req->req,
237                                                    py_queue_trigger, trigger);
238         if (!ret) {
239                 PyErr_SetString(PyExc_RuntimeError, "queue add failed");
240                 Py_DECREF(trigger);
241                 return NULL;
242         }
243
244         Py_RETURN_NONE;
245 }
246
247 static PyMethodDef py_tevent_queue_methods[] = {
248         { "stop", (PyCFunction)py_tevent_queue_stop, METH_NOARGS,
249                 "S.stop()" },
250         { "start", (PyCFunction)py_tevent_queue_start, METH_NOARGS,
251                 "S.start()" },
252         { "add", (PyCFunction)py_tevent_queue_add, METH_VARARGS,
253                 "S.add(ctx, req, trigger, baton)" },
254         { NULL },
255 };
256
257 static PyObject *py_tevent_context_wakeup_send(PyObject *self, PyObject *args)
258 {
259         /* FIXME */
260
261         Py_RETURN_NONE;
262 }
263
264 static PyObject *py_tevent_context_loop_wait(TeventContext_Object *self)
265 {
266         if (tevent_loop_wait(self->ev) != 0) {
267                 PyErr_SetNone(PyExc_RuntimeError);
268                 return NULL;
269         }
270         Py_RETURN_NONE;
271 }
272
273 static PyObject *py_tevent_context_loop_once(TeventContext_Object *self)
274 {
275         if (tevent_loop_once(self->ev) != 0) {
276                 PyErr_SetNone(PyExc_RuntimeError);
277                 return NULL;
278         }
279         Py_RETURN_NONE;
280 }
281
282 #ifdef TEVENT_DEPRECATED
283 static bool py_tevent_finished(PyObject *callback)
284 {
285         PyObject *py_ret;
286         bool ret;
287
288         py_ret = PyObject_CallFunction(callback, "");
289         if (py_ret == NULL)
290                 return true;
291         ret = PyObject_IsTrue(py_ret);
292         Py_DECREF(py_ret);
293         return ret;
294 }
295
296 static PyObject *py_tevent_context_loop_until(TeventContext_Object *self, PyObject *args)
297 {
298         PyObject *callback;
299         if (!PyArg_ParseTuple(args, "O", &callback))
300                 return NULL;
301
302         if (tevent_loop_until(self->ev, py_tevent_finished, callback) != 0) {
303                 PyErr_SetNone(PyExc_RuntimeError);
304                 return NULL;
305         }
306
307         if (PyErr_Occurred())
308                 return NULL;
309
310         Py_RETURN_NONE;
311 }
312 #endif
313
314 static void py_tevent_signal_handler(struct tevent_context *ev,
315                                         struct tevent_signal *se,
316                                         int signum,
317                                         int count,
318                                         void *siginfo,
319                                         void *private_data)
320 {
321         PyObject *callback = (PyObject *)private_data, *ret;
322
323         ret = PyObject_CallFunction(callback, "ii", signum, count);
324         Py_XDECREF(ret);
325 }
326
327 static void py_tevent_signal_dealloc(TeventSignal_Object *self)
328 {
329         talloc_free(self->signal);
330         PyObject_Del(self);
331 }
332
333 static PyTypeObject TeventSignal_Type = {
334         .tp_name = "Signal",
335         .tp_basicsize = sizeof(TeventSignal_Object),
336         .tp_dealloc = (destructor)py_tevent_signal_dealloc,
337         .tp_flags = Py_TPFLAGS_DEFAULT,
338 };
339
340 static PyObject *py_tevent_context_add_signal(TeventContext_Object *self, PyObject *args)
341 {
342         int signum, sa_flags;
343         PyObject *handler;
344         struct tevent_signal *sig;
345         TeventSignal_Object *ret;
346
347         if (!PyArg_ParseTuple(args, "iiO", &signum, &sa_flags, &handler))
348                 return NULL;
349
350         Py_INCREF(handler);
351         sig = tevent_add_signal(self->ev, NULL, signum, sa_flags,
352                                                         py_tevent_signal_handler, handler);
353
354         ret = PyObject_New(TeventSignal_Object, &TeventSignal_Type);
355         if (ret == NULL) {
356                 PyErr_NoMemory();
357                 talloc_free(sig);
358                 return NULL;
359         }
360
361         ret->signal = sig;
362
363         return (PyObject *)ret;
364 }
365
366 static void py_timer_handler(struct tevent_context *ev,
367                                        struct tevent_timer *te,
368                                        struct timeval current_time,
369                                        void *private_data)
370 {
371         PyObject *callback = private_data, *ret;
372         ret = PyObject_CallFunction(callback, "l", te);
373         Py_XDECREF(ret);
374 }
375
376 static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args)
377 {
378         TeventTimer_Object *ret;
379         struct timeval next_event;
380         struct tevent_timer *timer;
381         PyObject *handler;
382         if (!PyArg_ParseTuple(args, "lO", &next_event, &handler))
383                 return NULL;
384
385         timer = tevent_add_timer(self->ev, NULL, next_event, py_timer_handler,
386                                                          handler);
387         if (timer == NULL) {
388                 PyErr_SetNone(PyExc_RuntimeError);
389                 return NULL;
390         }
391
392         ret = PyObject_New(TeventTimer_Object, &TeventTimer_Type);
393         if (ret == NULL) {
394                 PyErr_NoMemory();
395                 talloc_free(timer);
396                 return NULL;
397         }
398         ret->timer = timer;
399
400         return (PyObject *)ret;
401 }
402
403 static void py_fd_handler(struct tevent_context *ev,
404                                     struct tevent_fd *fde,
405                                     uint16_t flags,
406                                     void *private_data)
407 {
408         PyObject *callback = private_data, *ret;
409
410         ret = PyObject_CallFunction(callback, "i", flags);
411         Py_XDECREF(ret);
412 }
413
414 static PyObject *py_tevent_context_add_fd(TeventContext_Object *self, PyObject *args)
415 {
416         int fd, flags;
417         PyObject *handler;
418         struct tevent_fd *tfd;
419         TeventFd_Object *ret;
420
421         if (!PyArg_ParseTuple(args, "iiO", &fd, &flags, &handler))
422                 return NULL;
423
424         tfd = tevent_add_fd(self->ev, NULL, fd, flags, py_fd_handler, handler);
425         if (tfd == NULL) {
426                 PyErr_SetNone(PyExc_RuntimeError);
427                 return NULL;
428         }
429
430         ret = PyObject_New(TeventFd_Object, &TeventFd_Type);
431         if (ret == NULL) {
432                 talloc_free(tfd);
433                 return NULL;
434         }
435         ret->fd = tfd;
436
437         return (PyObject *)ret;
438 }
439
440 #ifdef TEVENT_DEPRECATED
441 static PyObject *py_tevent_context_set_allow_nesting(TeventContext_Object *self)
442 {
443         tevent_loop_allow_nesting(self->ev);
444         Py_RETURN_NONE;
445 }
446 #endif
447
448 static PyMethodDef py_tevent_context_methods[] = {
449         { "reinitialise", (PyCFunction)py_tevent_context_reinitialise, METH_NOARGS,
450                 "S.reinitialise()" },
451         { "wakeup_send", (PyCFunction)py_tevent_context_wakeup_send, 
452                 METH_VARARGS, "S.wakeup_send(wakeup_time) -> req" },
453         { "loop_wait", (PyCFunction)py_tevent_context_loop_wait,
454                 METH_NOARGS, "S.loop_wait()" },
455         { "loop_once", (PyCFunction)py_tevent_context_loop_once,
456                 METH_NOARGS, "S.loop_once()" },
457 #ifdef TEVENT_DEPRECATED
458         { "loop_until", (PyCFunction)py_tevent_context_loop_until,
459                 METH_VARARGS, "S.loop_until(callback)" },
460 #endif
461         { "add_signal", (PyCFunction)py_tevent_context_add_signal,
462                 METH_VARARGS, "S.add_signal(signum, sa_flags, handler) -> signal" },
463         { "add_timer", (PyCFunction)py_tevent_context_add_timer,
464                 METH_VARARGS, "S.add_timer(next_event, handler) -> timer" },
465         { "add_fd", (PyCFunction)py_tevent_context_add_fd, 
466                 METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" },
467 #ifdef TEVENT_DEPRECATED
468         { "allow_nesting", (PyCFunction)py_tevent_context_set_allow_nesting, 
469                 METH_NOARGS, "Whether to allow nested tevent loops." },
470 #endif
471         { NULL },
472 };
473
474 static PyObject *py_tevent_req_wakeup_recv(PyObject *self)
475 {
476         /* FIXME */
477         Py_RETURN_NONE;
478 }
479
480 static PyObject *py_tevent_req_received(PyObject *self)
481 {
482         /* FIXME */
483         Py_RETURN_NONE;
484 }
485
486 static PyObject *py_tevent_req_is_error(PyObject *self)
487 {
488         /* FIXME */
489         Py_RETURN_NONE;
490 }
491
492 static PyObject *py_tevent_req_poll(PyObject *self)
493 {
494         /* FIXME */
495         Py_RETURN_NONE;
496 }
497
498 static PyObject *py_tevent_req_is_in_progress(PyObject *self)
499 {
500         /* FIXME */
501         Py_RETURN_NONE;
502 }
503
504 static PyGetSetDef py_tevent_req_getsetters[] = {
505         { "in_progress", (getter)py_tevent_req_is_in_progress, NULL,
506                 "Whether the request is in progress" },
507         { NULL }
508 };
509
510 static PyObject *py_tevent_req_post(PyObject *self, PyObject *args)
511 {
512         /* FIXME */
513         Py_RETURN_NONE;
514 }
515
516 static PyObject *py_tevent_req_set_error(PyObject *self, PyObject *args)
517 {
518         /* FIXME */
519         Py_RETURN_NONE;
520 }
521
522 static PyObject *py_tevent_req_done(PyObject *self)
523 {
524         /* FIXME */
525         Py_RETURN_NONE;
526 }
527
528 static PyObject *py_tevent_req_notify_callback(PyObject *self)
529 {
530         /* FIXME */
531         Py_RETURN_NONE;
532 }
533
534 static PyObject *py_tevent_req_set_endtime(PyObject *self, PyObject *args)
535 {
536         /* FIXME */
537         Py_RETURN_NONE;
538 }
539
540 static PyObject *py_tevent_req_cancel(TeventReq_Object *self)
541 {
542         if (!tevent_req_cancel(self->req)) {
543                 PyErr_SetNone(PyExc_RuntimeError);
544                 return NULL;
545         }
546         Py_RETURN_NONE;
547 }
548
549 static PyMethodDef py_tevent_req_methods[] = {
550         { "wakeup_recv", (PyCFunction)py_tevent_req_wakeup_recv, METH_NOARGS,
551                 "Wakeup received" },
552         { "received", (PyCFunction)py_tevent_req_received, METH_NOARGS,
553                 "Receive finished" },
554         { "is_error", (PyCFunction)py_tevent_req_is_error, METH_NOARGS,
555                 "is_error() -> (error, state)" },
556         { "poll", (PyCFunction)py_tevent_req_poll, METH_VARARGS,
557                 "poll(ctx)" },
558         { "post", (PyCFunction)py_tevent_req_post, METH_VARARGS,
559                 "post(ctx) -> req" },
560         { "set_error", (PyCFunction)py_tevent_req_set_error, METH_VARARGS,
561                 "set_error(error)" },
562         { "done", (PyCFunction)py_tevent_req_done, METH_NOARGS,
563                 "done()" },
564         { "notify_callback", (PyCFunction)py_tevent_req_notify_callback,
565                 METH_NOARGS, "notify_callback()" },
566         { "set_endtime", (PyCFunction)py_tevent_req_set_endtime,
567                 METH_VARARGS, "set_endtime(ctx, endtime)" },
568         { "cancel", (PyCFunction)py_tevent_req_cancel,
569                 METH_NOARGS, "cancel()" },
570         { NULL }
571 };
572
573 static void py_tevent_req_dealloc(TeventReq_Object *self)
574 {
575         talloc_free(self->req);
576         PyObject_DEL(self);
577 }
578
579 static PyTypeObject TeventReq_Type = {
580         .tp_name = "tevent.Request",
581         .tp_basicsize = sizeof(TeventReq_Object),
582         .tp_methods = py_tevent_req_methods,
583         .tp_dealloc = (destructor)py_tevent_req_dealloc,
584         .tp_getset = py_tevent_req_getsetters,
585         /* FIXME: .tp_new = py_tevent_req_new, */
586 };
587
588 static PyObject *py_tevent_queue_get_length(TeventQueue_Object *self)
589 {
590         return PyInt_FromLong(tevent_queue_length(self->queue));
591 }
592
593 static PyGetSetDef py_tevent_queue_getsetters[] = {
594         { "length", (getter)py_tevent_queue_get_length,
595                 NULL, "The number of elements in the queue." },
596         { NULL },
597 };
598
599 static void py_tevent_queue_dealloc(TeventQueue_Object *self)
600 {
601         talloc_free(self->queue);
602         PyObject_Del(self);
603 }
604
605 static PyTypeObject TeventQueue_Type = {
606         .tp_name = "tevent.Queue",
607         .tp_basicsize = sizeof(TeventQueue_Object),
608         .tp_dealloc = (destructor)py_tevent_queue_dealloc,
609         .tp_flags = Py_TPFLAGS_DEFAULT,
610         .tp_getset = py_tevent_queue_getsetters,
611         .tp_methods = py_tevent_queue_methods,
612 };
613
614 static PyObject *py_tevent_context_signal_support(PyObject *_self)
615 {
616         TeventContext_Object *self = (TeventContext_Object *)_self;
617         return PyBool_FromLong(tevent_signal_support(self->ev));
618 }
619
620 static PyGetSetDef py_tevent_context_getsetters[] = {
621         { "signal_support", (getter)py_tevent_context_signal_support,
622                 NULL, "if this platform and tevent context support signal handling" },
623         { NULL }
624 };
625
626 static void py_tevent_context_dealloc(TeventContext_Object *self)
627 {
628         talloc_free(self->ev);
629         PyObject_Del(self);
630 }
631
632 static PyObject *py_tevent_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
633 {
634         const char * const kwnames[] = { "name", NULL };
635         char *name = NULL;
636         struct tevent_context *ev;
637         TeventContext_Object *ret;
638
639         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwnames, &name))
640                 return NULL;
641
642         if (name == NULL) {
643                 ev = tevent_context_init(NULL);
644         } else {
645                 ev = tevent_context_init_byname(NULL, name);
646         }
647
648         if (ev == NULL) {
649                 PyErr_SetNone(PyExc_RuntimeError);
650                 return NULL;
651         }
652
653         ret = PyObject_New(TeventContext_Object, type);
654         if (ret == NULL) {
655                 PyErr_NoMemory();
656                 talloc_free(ev);
657                 return NULL;
658         }
659
660         ret->ev = ev;
661         return (PyObject *)ret;
662 }
663
664 static PyTypeObject TeventContext_Type = {
665         .tp_name = "_tevent.Context",
666         .tp_new = py_tevent_context_new,
667         .tp_basicsize = sizeof(TeventContext_Object),
668         .tp_dealloc = (destructor)py_tevent_context_dealloc,
669         .tp_methods = py_tevent_context_methods,
670         .tp_getset = py_tevent_context_getsetters,
671         .tp_flags = Py_TPFLAGS_DEFAULT,
672 };
673
674 static PyObject *py_set_default_backend(PyObject *self, PyObject *args)
675 {
676         char *backend_name;
677         if (!PyArg_ParseTuple(args, "s", &backend_name))
678                 return NULL;
679
680         tevent_set_default_backend(backend_name);
681
682         Py_RETURN_NONE;
683 }
684
685 static PyObject *py_backend_list(PyObject *self)
686 {
687         PyObject *ret;
688         int i;
689         const char **backends;
690
691         ret = PyList_New(0);
692         if (ret == NULL) {
693                 return NULL;
694         }
695
696         backends = tevent_backend_list(NULL);
697         if (backends == NULL) {
698                 PyErr_SetNone(PyExc_RuntimeError);
699                 Py_DECREF(ret);
700                 return NULL;
701         }
702         for (i = 0; backends[i]; i++) {
703                 PyList_Append(ret, PyString_FromString(backends[i]));
704         }
705
706         talloc_free(backends);
707
708         return ret;
709 }
710
711 static PyMethodDef tevent_methods[] = {
712         { "register_backend", (PyCFunction)py_register_backend, METH_VARARGS,
713                 "register_backend(backend)" },
714         { "set_default_backend", (PyCFunction)py_set_default_backend, 
715                 METH_VARARGS, "set_default_backend(backend)" },
716         { "backend_list", (PyCFunction)py_backend_list, 
717                 METH_NOARGS, "backend_list() -> list" },
718         { NULL },
719 };
720
721 void init_tevent(void)
722 {
723         PyObject *m;
724
725         if (PyType_Ready(&TeventContext_Type) < 0)
726                 return;
727
728         if (PyType_Ready(&TeventQueue_Type) < 0)
729                 return;
730
731         if (PyType_Ready(&TeventReq_Type) < 0)
732                 return;
733
734         if (PyType_Ready(&TeventSignal_Type) < 0)
735                 return;
736
737         if (PyType_Ready(&TeventTimer_Type) < 0)
738                 return;
739
740         if (PyType_Ready(&TeventFd_Type) < 0)
741                 return;
742
743         m = Py_InitModule3("_tevent", tevent_methods, "Tevent integration for twisted.");
744         if (m == NULL)
745                 return;
746
747         Py_INCREF(&TeventContext_Type);
748         PyModule_AddObject(m, "Context", (PyObject *)&TeventContext_Type);
749
750         Py_INCREF(&TeventQueue_Type);
751         PyModule_AddObject(m, "Queue", (PyObject *)&TeventQueue_Type);
752
753         Py_INCREF(&TeventReq_Type);
754         PyModule_AddObject(m, "Request", (PyObject *)&TeventReq_Type);
755
756         Py_INCREF(&TeventSignal_Type);
757         PyModule_AddObject(m, "Signal", (PyObject *)&TeventSignal_Type);
758
759         Py_INCREF(&TeventTimer_Type);
760         PyModule_AddObject(m, "Timer", (PyObject *)&TeventTimer_Type);
761
762         Py_INCREF(&TeventFd_Type);
763         PyModule_AddObject(m, "Fd", (PyObject *)&TeventFd_Type);
764
765         PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION));
766 }