2 Unix SMB/CIFS implementation.
3 Python bindings for tevent
5 Copyright (C) Jelmer Vernooij 2010
7 ** NOTE! The following LGPL license applies to the tevent
8 ** library. This does NOT imply that all of Samba is released
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.
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.
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/>.
28 #if PY_MAJOR_VERSION >= 3
29 #define PyStr_Check PyUnicode_Check
30 #define PyStr_FromString PyUnicode_FromString
31 #define PyStr_AsUTF8 PyUnicode_AsUTF8
32 #define PyInt_FromLong PyLong_FromLong
34 #define PyStr_Check PyString_Check
35 #define PyStr_FromString PyString_FromString
36 #define PyStr_AsUTF8 PyString_AsString
39 void init_tevent(void);
43 struct tevent_context
*ev
;
44 } TeventContext_Object
;
48 struct tevent_queue
*queue
;
53 struct tevent_req
*req
;
58 struct tevent_signal
*signal
;
59 } TeventSignal_Object
;
63 struct tevent_timer
*timer
;
72 static PyTypeObject TeventContext_Type
;
73 static PyTypeObject TeventReq_Type
;
74 static PyTypeObject TeventQueue_Type
;
75 static PyTypeObject TeventSignal_Type
;
76 static PyTypeObject TeventTimer_Type
;
77 static PyTypeObject TeventFd_Type
;
79 static int py_context_init(struct tevent_context
*ev
)
85 static struct tevent_fd
*py_add_fd(struct tevent_context
*ev
,
87 int fd
, uint16_t flags
,
88 tevent_fd_handler_t handler
,
90 const char *handler_name
,
97 static void py_set_fd_close_fn(struct tevent_fd
*fde
,
98 tevent_fd_close_fn_t close_fn
)
103 static uint16_t py_get_fd_flags(struct tevent_fd
*fde
)
109 static void py_set_fd_flags(struct tevent_fd
*fde
, uint16_t flags
)
114 /* timed_event functions */
115 static struct tevent_timer
*py_add_timer(struct tevent_context
*ev
,
117 struct timeval next_event
,
118 tevent_timer_handler_t handler
,
120 const char *handler_name
,
121 const char *location
)
127 /* immediate event functions */
128 static void py_schedule_immediate(struct tevent_immediate
*im
,
129 struct tevent_context
*ev
,
130 tevent_immediate_handler_t handler
,
132 const char *handler_name
,
133 const char *location
)
138 /* signal functions */
139 static struct tevent_signal
*py_add_signal(struct tevent_context
*ev
,
141 int signum
, int sa_flags
,
142 tevent_signal_handler_t handler
,
144 const char *handler_name
,
145 const char *location
)
152 static int py_loop_once(struct tevent_context
*ev
, const char *location
)
158 static int py_loop_wait(struct tevent_context
*ev
, const char *location
)
164 const static struct tevent_ops py_tevent_ops
= {
165 .context_init
= py_context_init
,
167 .set_fd_close_fn
= py_set_fd_close_fn
,
168 .get_fd_flags
= py_get_fd_flags
,
169 .set_fd_flags
= py_set_fd_flags
,
170 .add_timer
= py_add_timer
,
171 .schedule_immediate
= py_schedule_immediate
,
172 .add_signal
= py_add_signal
,
173 .loop_wait
= py_loop_wait
,
174 .loop_once
= py_loop_once
,
177 static PyObject
*py_register_backend(PyObject
*self
, PyObject
*args
)
179 PyObject
*name
, *py_backend
;
181 if (!PyArg_ParseTuple(args
, "O", &py_backend
))
184 name
= PyObject_GetAttrString(py_backend
, "name");
186 PyErr_SetNone(PyExc_AttributeError
);
190 if (!PyStr_Check(name
)) {
191 PyErr_SetNone(PyExc_TypeError
);
196 if (!tevent_register_backend(PyStr_AsUTF8(name
), &py_tevent_ops
)) { /* FIXME: What to do with backend */
197 PyErr_SetNone(PyExc_RuntimeError
);
207 static PyObject
*py_tevent_context_reinitialise(TeventContext_Object
*self
)
209 int ret
= tevent_re_initialise(self
->ev
);
211 PyErr_SetNone(PyExc_RuntimeError
);
217 static PyObject
*py_tevent_queue_stop(TeventQueue_Object
*self
)
219 tevent_queue_stop(self
->queue
);
223 static PyObject
*py_tevent_queue_start(TeventQueue_Object
*self
)
225 tevent_queue_start(self
->queue
);
229 static void py_queue_trigger(struct tevent_req
*req
, void *private_data
)
231 PyObject
*callback
= private_data
, *ret
;
233 ret
= PyObject_CallFunction(callback
, "");
237 static PyObject
*py_tevent_queue_add(TeventQueue_Object
*self
, PyObject
*args
)
239 TeventContext_Object
*py_ev
;
240 TeventReq_Object
*py_req
;
244 if (!PyArg_ParseTuple(args
, "O!O!O",
245 &TeventContext_Type
, &py_ev
,
246 &TeventReq_Type
, &py_req
,
252 ret
= tevent_queue_add(self
->queue
, py_ev
->ev
, py_req
->req
,
253 py_queue_trigger
, trigger
);
255 PyErr_SetString(PyExc_RuntimeError
, "queue add failed");
263 static PyMethodDef py_tevent_queue_methods
[] = {
264 { "stop", (PyCFunction
)py_tevent_queue_stop
, METH_NOARGS
,
266 { "start", (PyCFunction
)py_tevent_queue_start
, METH_NOARGS
,
268 { "add", (PyCFunction
)py_tevent_queue_add
, METH_VARARGS
,
269 "S.add(ctx, req, trigger, baton)" },
273 static PyObject
*py_tevent_context_wakeup_send(PyObject
*self
, PyObject
*args
)
280 static PyObject
*py_tevent_context_loop_wait(TeventContext_Object
*self
)
282 if (tevent_loop_wait(self
->ev
) != 0) {
283 PyErr_SetNone(PyExc_RuntimeError
);
289 static PyObject
*py_tevent_context_loop_once(TeventContext_Object
*self
)
291 if (tevent_loop_once(self
->ev
) != 0) {
292 PyErr_SetNone(PyExc_RuntimeError
);
298 #ifdef TEVENT_DEPRECATED
299 static bool py_tevent_finished(PyObject
*callback
)
304 py_ret
= PyObject_CallFunction(callback
, "");
307 ret
= PyObject_IsTrue(py_ret
);
312 static PyObject
*py_tevent_context_loop_until(TeventContext_Object
*self
, PyObject
*args
)
315 if (!PyArg_ParseTuple(args
, "O", &callback
))
318 if (tevent_loop_until(self
->ev
, py_tevent_finished
, callback
) != 0) {
319 PyErr_SetNone(PyExc_RuntimeError
);
323 if (PyErr_Occurred())
330 static void py_tevent_signal_handler(struct tevent_context
*ev
,
331 struct tevent_signal
*se
,
337 PyObject
*callback
= (PyObject
*)private_data
, *ret
;
339 ret
= PyObject_CallFunction(callback
, "ii", signum
, count
);
343 static void py_tevent_signal_dealloc(TeventSignal_Object
*self
)
345 talloc_free(self
->signal
);
349 static PyTypeObject TeventSignal_Type
= {
350 .tp_name
= "tevent.Signal",
351 .tp_basicsize
= sizeof(TeventSignal_Object
),
352 .tp_dealloc
= (destructor
)py_tevent_signal_dealloc
,
353 .tp_flags
= Py_TPFLAGS_DEFAULT
,
356 static PyObject
*py_tevent_context_add_signal(TeventContext_Object
*self
, PyObject
*args
)
358 int signum
, sa_flags
;
360 struct tevent_signal
*sig
;
361 TeventSignal_Object
*ret
;
363 if (!PyArg_ParseTuple(args
, "iiO", &signum
, &sa_flags
, &handler
))
367 sig
= tevent_add_signal(self
->ev
, NULL
, signum
, sa_flags
,
368 py_tevent_signal_handler
, handler
);
370 ret
= PyObject_New(TeventSignal_Object
, &TeventSignal_Type
);
379 return (PyObject
*)ret
;
382 static void py_timer_handler(struct tevent_context
*ev
,
383 struct tevent_timer
*te
,
384 struct timeval current_time
,
387 TeventTimer_Object
*self
= private_data
;
390 ret
= PyObject_CallFunction(self
->callback
, "l", te
);
392 /* No Python stack to propagate exception to; just print traceback */
398 static void py_tevent_timer_dealloc(TeventTimer_Object
*self
)
401 talloc_free(self
->timer
);
403 Py_DECREF(self
->callback
);
407 static int py_tevent_timer_traverse(TeventTimer_Object
*self
, visitproc visit
, void *arg
)
409 Py_VISIT(self
->callback
);
413 static PyObject
* py_tevent_timer_get_active(TeventTimer_Object
*self
) {
414 return PyBool_FromLong(self
->timer
!= NULL
);
417 struct PyGetSetDef py_tevent_timer_getset
[] = {
420 .get
= (getter
)py_tevent_timer_get_active
,
421 .doc
= "true if the timer is scheduled to run",
426 static PyTypeObject TeventTimer_Type
= {
427 .tp_name
= "tevent.Timer",
428 .tp_basicsize
= sizeof(TeventTimer_Object
),
429 .tp_dealloc
= (destructor
)py_tevent_timer_dealloc
,
430 .tp_traverse
= (traverseproc
)py_tevent_timer_traverse
,
431 .tp_getset
= py_tevent_timer_getset
,
432 .tp_flags
= Py_TPFLAGS_DEFAULT
,
435 static int timer_destructor(void* ptr
)
437 TeventTimer_Object
*obj
= *(TeventTimer_Object
**)ptr
;
443 static PyObject
*py_tevent_context_add_timer_internal(TeventContext_Object
*self
,
444 struct timeval next_event
,
449 * There are 5 pieces in play; two tevent contexts and 3 Python objects:
451 * - The tevent context
452 * - The Python context -- "self"
453 * - The Python timer (TeventTimer_Object) -- "ret"
454 * - The Python callback function -- "callback"
456 * We only use the Python context for getting the tevent context,
457 * afterwards it can be destroyed.
459 * The tevent context owns the tevent timer.
461 * The tevent timer holds a reference to the Python timer, so the Python
462 * timer must always outlive the tevent timer.
463 * The Python timer has a pointer to the tevent timer; a destructor is
464 * used to set this to NULL when the tevent timer is deallocated.
466 * The tevent timer can be deallocated in these cases:
467 * 1) when the context is destroyed
468 * 2) after the event fires
469 * Posssibly, API might be added to cancel (free the tevent timer).
471 * The Python timer holds a reference to the callback.
473 TeventTimer_Object
*ret
;
474 TeventTimer_Object
**tmp_context
;
476 ret
= PyObject_New(TeventTimer_Object
, &TeventTimer_Type
);
482 ret
->callback
= callback
;
483 ret
->timer
= tevent_add_timer(self
->ev
, NULL
, next_event
, py_timer_handler
,
485 if (ret
->timer
== NULL
) {
487 PyErr_SetString(PyExc_RuntimeError
, "Could not initialize timer");
490 tmp_context
= talloc(ret
->timer
, TeventTimer_Object
*);
491 if (tmp_context
== NULL
) {
492 talloc_free(ret
->timer
);
494 PyErr_SetString(PyExc_RuntimeError
, "Could not initialize timer");
499 talloc_set_destructor(tmp_context
, timer_destructor
);
501 return (PyObject
*)ret
;
504 static PyObject
*py_tevent_context_add_timer(TeventContext_Object
*self
, PyObject
*args
)
506 struct timeval next_event
;
508 if (!PyArg_ParseTuple(args
, "lO", &next_event
, &callback
))
511 return py_tevent_context_add_timer_internal(self
, next_event
, callback
);
514 static PyObject
*py_tevent_context_add_timer_offset(TeventContext_Object
*self
, PyObject
*args
)
516 struct timeval next_event
;
520 if (!PyArg_ParseTuple(args
, "dO", &offset
, &callback
))
525 next_event
= tevent_timeval_current_ofs(seconds
, (int)(offset
*1000000));
526 return py_tevent_context_add_timer_internal(self
, next_event
, callback
);
529 static void py_fd_handler(struct tevent_context
*ev
,
530 struct tevent_fd
*fde
,
534 PyObject
*callback
= private_data
, *ret
;
536 ret
= PyObject_CallFunction(callback
, "i", flags
);
540 static void py_tevent_fp_dealloc(TeventFd_Object
*self
)
542 talloc_free(self
->fd
);
546 static PyTypeObject TeventFd_Type
= {
547 .tp_name
= "tevent.Fd",
548 .tp_basicsize
= sizeof(TeventFd_Object
),
549 .tp_dealloc
= (destructor
)py_tevent_fp_dealloc
,
550 .tp_flags
= Py_TPFLAGS_DEFAULT
,
553 static PyObject
*py_tevent_context_add_fd(TeventContext_Object
*self
, PyObject
*args
)
557 struct tevent_fd
*tfd
;
558 TeventFd_Object
*ret
;
560 if (!PyArg_ParseTuple(args
, "iiO", &fd
, &flags
, &handler
))
563 tfd
= tevent_add_fd(self
->ev
, NULL
, fd
, flags
, py_fd_handler
, handler
);
565 PyErr_SetNone(PyExc_RuntimeError
);
569 ret
= PyObject_New(TeventFd_Object
, &TeventFd_Type
);
576 return (PyObject
*)ret
;
579 #ifdef TEVENT_DEPRECATED
580 static PyObject
*py_tevent_context_set_allow_nesting(TeventContext_Object
*self
)
582 tevent_loop_allow_nesting(self
->ev
);
587 static PyMethodDef py_tevent_context_methods
[] = {
588 { "reinitialise", (PyCFunction
)py_tevent_context_reinitialise
, METH_NOARGS
,
589 "S.reinitialise()" },
590 { "wakeup_send", (PyCFunction
)py_tevent_context_wakeup_send
,
591 METH_VARARGS
, "S.wakeup_send(wakeup_time) -> req" },
592 { "loop_wait", (PyCFunction
)py_tevent_context_loop_wait
,
593 METH_NOARGS
, "S.loop_wait()" },
594 { "loop_once", (PyCFunction
)py_tevent_context_loop_once
,
595 METH_NOARGS
, "S.loop_once()" },
596 #ifdef TEVENT_DEPRECATED
597 { "loop_until", (PyCFunction
)py_tevent_context_loop_until
,
598 METH_VARARGS
, "S.loop_until(callback)" },
600 { "add_signal", (PyCFunction
)py_tevent_context_add_signal
,
601 METH_VARARGS
, "S.add_signal(signum, sa_flags, handler) -> signal" },
602 { "add_timer", (PyCFunction
)py_tevent_context_add_timer
,
603 METH_VARARGS
, "S.add_timer(next_event, handler) -> timer" },
604 { "add_timer_offset", (PyCFunction
)py_tevent_context_add_timer_offset
,
605 METH_VARARGS
, "S.add_timer(offset_seconds, handler) -> timer" },
606 { "add_fd", (PyCFunction
)py_tevent_context_add_fd
,
607 METH_VARARGS
, "S.add_fd(fd, flags, handler) -> fd" },
608 #ifdef TEVENT_DEPRECATED
609 { "allow_nesting", (PyCFunction
)py_tevent_context_set_allow_nesting
,
610 METH_NOARGS
, "Whether to allow nested tevent loops." },
615 static PyObject
*py_tevent_req_wakeup_recv(PyObject
*self
)
621 static PyObject
*py_tevent_req_received(PyObject
*self
)
627 static PyObject
*py_tevent_req_is_error(PyObject
*self
)
633 static PyObject
*py_tevent_req_poll(PyObject
*self
)
639 static PyObject
*py_tevent_req_is_in_progress(PyObject
*self
)
645 static PyGetSetDef py_tevent_req_getsetters
[] = {
646 { "in_progress", (getter
)py_tevent_req_is_in_progress
, NULL
,
647 "Whether the request is in progress" },
651 static PyObject
*py_tevent_req_post(PyObject
*self
, PyObject
*args
)
657 static PyObject
*py_tevent_req_set_error(PyObject
*self
, PyObject
*args
)
663 static PyObject
*py_tevent_req_done(PyObject
*self
)
669 static PyObject
*py_tevent_req_notify_callback(PyObject
*self
)
675 static PyObject
*py_tevent_req_set_endtime(PyObject
*self
, PyObject
*args
)
681 static PyObject
*py_tevent_req_cancel(TeventReq_Object
*self
)
683 if (!tevent_req_cancel(self
->req
)) {
684 PyErr_SetNone(PyExc_RuntimeError
);
690 static PyMethodDef py_tevent_req_methods
[] = {
691 { "wakeup_recv", (PyCFunction
)py_tevent_req_wakeup_recv
, METH_NOARGS
,
693 { "received", (PyCFunction
)py_tevent_req_received
, METH_NOARGS
,
694 "Receive finished" },
695 { "is_error", (PyCFunction
)py_tevent_req_is_error
, METH_NOARGS
,
696 "is_error() -> (error, state)" },
697 { "poll", (PyCFunction
)py_tevent_req_poll
, METH_VARARGS
,
699 { "post", (PyCFunction
)py_tevent_req_post
, METH_VARARGS
,
700 "post(ctx) -> req" },
701 { "set_error", (PyCFunction
)py_tevent_req_set_error
, METH_VARARGS
,
702 "set_error(error)" },
703 { "done", (PyCFunction
)py_tevent_req_done
, METH_NOARGS
,
705 { "notify_callback", (PyCFunction
)py_tevent_req_notify_callback
,
706 METH_NOARGS
, "notify_callback()" },
707 { "set_endtime", (PyCFunction
)py_tevent_req_set_endtime
,
708 METH_VARARGS
, "set_endtime(ctx, endtime)" },
709 { "cancel", (PyCFunction
)py_tevent_req_cancel
,
710 METH_NOARGS
, "cancel()" },
714 static void py_tevent_req_dealloc(TeventReq_Object
*self
)
716 talloc_free(self
->req
);
720 static PyTypeObject TeventReq_Type
= {
721 .tp_name
= "tevent.Request",
722 .tp_basicsize
= sizeof(TeventReq_Object
),
723 .tp_methods
= py_tevent_req_methods
,
724 .tp_dealloc
= (destructor
)py_tevent_req_dealloc
,
725 .tp_getset
= py_tevent_req_getsetters
,
726 /* FIXME: .tp_new = py_tevent_req_new, */
729 static PyObject
*py_tevent_queue_get_length(TeventQueue_Object
*self
)
731 return PyInt_FromLong(tevent_queue_length(self
->queue
));
734 static PyGetSetDef py_tevent_queue_getsetters
[] = {
735 { "length", (getter
)py_tevent_queue_get_length
,
736 NULL
, "The number of elements in the queue." },
740 static void py_tevent_queue_dealloc(TeventQueue_Object
*self
)
742 talloc_free(self
->queue
);
746 static PyTypeObject TeventQueue_Type
= {
747 .tp_name
= "tevent.Queue",
748 .tp_basicsize
= sizeof(TeventQueue_Object
),
749 .tp_dealloc
= (destructor
)py_tevent_queue_dealloc
,
750 .tp_flags
= Py_TPFLAGS_DEFAULT
,
751 .tp_getset
= py_tevent_queue_getsetters
,
752 .tp_methods
= py_tevent_queue_methods
,
755 static PyObject
*py_tevent_context_signal_support(PyObject
*_self
)
757 TeventContext_Object
*self
= (TeventContext_Object
*)_self
;
758 return PyBool_FromLong(tevent_signal_support(self
->ev
));
761 static PyGetSetDef py_tevent_context_getsetters
[] = {
762 { "signal_support", (getter
)py_tevent_context_signal_support
,
763 NULL
, "if this platform and tevent context support signal handling" },
767 static void py_tevent_context_dealloc(TeventContext_Object
*self
)
769 talloc_free(self
->ev
);
773 static PyObject
*py_tevent_context_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwargs
)
775 const char * const kwnames
[] = { "name", NULL
};
777 struct tevent_context
*ev
;
778 TeventContext_Object
*ret
;
780 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|s", kwnames
, &name
))
784 ev
= tevent_context_init(NULL
);
786 ev
= tevent_context_init_byname(NULL
, name
);
790 PyErr_SetNone(PyExc_RuntimeError
);
794 ret
= PyObject_New(TeventContext_Object
, type
);
802 return (PyObject
*)ret
;
805 static PyTypeObject TeventContext_Type
= {
806 .tp_name
= "tevent.Context",
807 .tp_new
= py_tevent_context_new
,
808 .tp_basicsize
= sizeof(TeventContext_Object
),
809 .tp_dealloc
= (destructor
)py_tevent_context_dealloc
,
810 .tp_methods
= py_tevent_context_methods
,
811 .tp_getset
= py_tevent_context_getsetters
,
812 .tp_flags
= Py_TPFLAGS_DEFAULT
,
815 static PyObject
*py_set_default_backend(PyObject
*self
, PyObject
*args
)
818 if (!PyArg_ParseTuple(args
, "s", &backend_name
))
821 tevent_set_default_backend(backend_name
);
826 static PyObject
*py_backend_list(PyObject
*self
)
828 PyObject
*ret
= NULL
;
829 PyObject
*string
= NULL
;
831 const char **backends
= NULL
;
838 backends
= tevent_backend_list(NULL
);
839 if (backends
== NULL
) {
840 PyErr_SetNone(PyExc_RuntimeError
);
843 for (i
= 0; backends
[i
]; i
++) {
844 string
= PyStr_FromString(backends
[i
]);
848 result
= PyList_Append(ret
, string
);
856 talloc_free(backends
);
863 talloc_free(backends
);
867 static PyMethodDef tevent_methods
[] = {
868 { "register_backend", (PyCFunction
)py_register_backend
, METH_VARARGS
,
869 "register_backend(backend)" },
870 { "set_default_backend", (PyCFunction
)py_set_default_backend
,
871 METH_VARARGS
, "set_default_backend(backend)" },
872 { "backend_list", (PyCFunction
)py_backend_list
,
873 METH_NOARGS
, "backend_list() -> list" },
877 #define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.")
879 #if PY_MAJOR_VERSION >= 3
880 static struct PyModuleDef moduledef
= {
881 PyModuleDef_HEAD_INIT
,
885 .m_methods
= tevent_methods
,
889 PyObject
* module_init(void);
890 PyObject
* module_init(void)
894 if (PyType_Ready(&TeventContext_Type
) < 0)
897 if (PyType_Ready(&TeventQueue_Type
) < 0)
900 if (PyType_Ready(&TeventReq_Type
) < 0)
903 if (PyType_Ready(&TeventSignal_Type
) < 0)
906 if (PyType_Ready(&TeventTimer_Type
) < 0)
909 if (PyType_Ready(&TeventFd_Type
) < 0)
912 #if PY_MAJOR_VERSION >= 3
913 m
= PyModule_Create(&moduledef
);
915 m
= Py_InitModule3("_tevent", tevent_methods
, MODULE_DOC
);
920 Py_INCREF(&TeventContext_Type
);
921 PyModule_AddObject(m
, "Context", (PyObject
*)&TeventContext_Type
);
923 Py_INCREF(&TeventQueue_Type
);
924 PyModule_AddObject(m
, "Queue", (PyObject
*)&TeventQueue_Type
);
926 Py_INCREF(&TeventReq_Type
);
927 PyModule_AddObject(m
, "Request", (PyObject
*)&TeventReq_Type
);
929 Py_INCREF(&TeventSignal_Type
);
930 PyModule_AddObject(m
, "Signal", (PyObject
*)&TeventSignal_Type
);
932 Py_INCREF(&TeventTimer_Type
);
933 PyModule_AddObject(m
, "Timer", (PyObject
*)&TeventTimer_Type
);
935 Py_INCREF(&TeventFd_Type
);
936 PyModule_AddObject(m
, "Fd", (PyObject
*)&TeventFd_Type
);
938 PyModule_AddStringConstant(m
, "__version__", PACKAGE_VERSION
);
943 #if PY_MAJOR_VERSION >= 3
944 PyMODINIT_FUNC
PyInit__tevent(void);
945 PyMODINIT_FUNC
PyInit__tevent(void)
947 return module_init();
950 void init_tevent(void);
951 void init_tevent(void)