Line data Source code
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 "replace.h"
27 : #include <tevent.h>
28 :
29 : #if PY_MAJOR_VERSION >= 3
30 : #define PyLong_FromLong PyLong_FromLong
31 : #endif
32 :
33 : /* discard signature of 'func' in favour of 'target_sig' */
34 : #define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func
35 :
36 : void init_tevent(void);
37 :
38 : typedef struct {
39 : PyObject_HEAD
40 : struct tevent_context *ev;
41 : } TeventContext_Object;
42 :
43 : typedef struct {
44 : PyObject_HEAD
45 : struct tevent_queue *queue;
46 : } TeventQueue_Object;
47 :
48 : typedef struct {
49 : PyObject_HEAD
50 : struct tevent_req *req;
51 : } TeventReq_Object;
52 :
53 : typedef struct {
54 : PyObject_HEAD
55 : struct tevent_signal *signal;
56 : } TeventSignal_Object;
57 :
58 : typedef struct {
59 : PyObject_HEAD
60 : struct tevent_timer *timer;
61 : PyObject *callback;
62 : } TeventTimer_Object;
63 :
64 : typedef struct {
65 : PyObject_HEAD
66 : struct tevent_fd *fd;
67 : } TeventFd_Object;
68 :
69 : static PyTypeObject TeventContext_Type;
70 : static PyTypeObject TeventReq_Type;
71 : static PyTypeObject TeventQueue_Type;
72 : static PyTypeObject TeventSignal_Type;
73 : static PyTypeObject TeventTimer_Type;
74 : static PyTypeObject TeventFd_Type;
75 :
76 1 : static PyObject *py_tevent_context_reinitialise(TeventContext_Object *self,
77 : PyObject *Py_UNUSED(ignored))
78 : {
79 1 : int ret = tevent_re_initialise(self->ev);
80 1 : if (ret != 0) {
81 0 : PyErr_SetNone(PyExc_RuntimeError);
82 0 : return NULL;
83 : }
84 1 : Py_RETURN_NONE;
85 : }
86 :
87 0 : static PyObject *py_tevent_queue_stop(TeventQueue_Object *self,
88 : PyObject *Py_UNUSED(ignored))
89 : {
90 0 : tevent_queue_stop(self->queue);
91 0 : Py_RETURN_NONE;
92 : }
93 :
94 0 : static PyObject *py_tevent_queue_start(TeventQueue_Object *self,
95 : PyObject *Py_UNUSED(ignored))
96 : {
97 0 : tevent_queue_start(self->queue);
98 0 : Py_RETURN_NONE;
99 : }
100 :
101 0 : static void py_queue_trigger(struct tevent_req *req, void *private_data)
102 : {
103 0 : PyObject *callback = private_data, *ret;
104 :
105 0 : ret = PyObject_CallFunction(callback, discard_const_p(char, ""));
106 0 : Py_XDECREF(ret);
107 0 : }
108 :
109 0 : static PyObject *py_tevent_queue_add(TeventQueue_Object *self, PyObject *args)
110 : {
111 : TeventContext_Object *py_ev;
112 : TeventReq_Object *py_req;
113 : PyObject *trigger;
114 : bool ret;
115 :
116 0 : if (!PyArg_ParseTuple(args, "O!O!O",
117 : &TeventContext_Type, &py_ev,
118 : &TeventReq_Type, &py_req,
119 : &trigger))
120 0 : return NULL;
121 :
122 0 : Py_INCREF(trigger);
123 :
124 0 : ret = tevent_queue_add(self->queue, py_ev->ev, py_req->req,
125 : py_queue_trigger, trigger);
126 0 : if (!ret) {
127 0 : PyErr_SetString(PyExc_RuntimeError, "queue add failed");
128 0 : Py_DECREF(trigger);
129 0 : return NULL;
130 : }
131 :
132 0 : Py_RETURN_NONE;
133 : }
134 :
135 : static PyMethodDef py_tevent_queue_methods[] = {
136 : { "stop", (PyCFunction)py_tevent_queue_stop,
137 : METH_NOARGS,
138 : "S.stop()" },
139 : { "start", (PyCFunction)py_tevent_queue_start,
140 : METH_NOARGS,
141 : "S.start()" },
142 : { "add", (PyCFunction)py_tevent_queue_add, METH_VARARGS,
143 : "S.add(ctx, req, trigger, baton)" },
144 : {0},
145 : };
146 :
147 0 : static PyObject *py_tevent_context_wakeup_send(PyObject *self, PyObject *args)
148 : {
149 : /* FIXME */
150 :
151 0 : Py_RETURN_NONE;
152 : }
153 :
154 1 : static PyObject *py_tevent_context_loop_wait(TeventContext_Object *self,
155 : PyObject *Py_UNUSED(ignored))
156 : {
157 1 : if (tevent_loop_wait(self->ev) != 0) {
158 0 : PyErr_SetNone(PyExc_RuntimeError);
159 0 : return NULL;
160 : }
161 1 : Py_RETURN_NONE;
162 : }
163 :
164 4 : static PyObject *py_tevent_context_loop_once(TeventContext_Object *self,
165 : PyObject *Py_UNUSED(ignored))
166 : {
167 4 : if (tevent_loop_once(self->ev) != 0) {
168 0 : PyErr_SetNone(PyExc_RuntimeError);
169 0 : return NULL;
170 : }
171 4 : Py_RETURN_NONE;
172 : }
173 :
174 0 : static void py_tevent_signal_handler(struct tevent_context *ev,
175 : struct tevent_signal *se,
176 : int signum,
177 : int count,
178 : void *siginfo,
179 : void *private_data)
180 : {
181 0 : PyObject *callback = (PyObject *)private_data, *ret;
182 :
183 0 : ret = PyObject_CallFunction(callback, discard_const_p(char, "ii"), signum, count);
184 0 : Py_XDECREF(ret);
185 0 : }
186 :
187 1 : static void py_tevent_signal_dealloc(TeventSignal_Object *self)
188 : {
189 1 : talloc_free(self->signal);
190 1 : PyObject_Del(self);
191 1 : }
192 :
193 : static PyTypeObject TeventSignal_Type = {
194 : .tp_name = "tevent.Signal",
195 : .tp_basicsize = sizeof(TeventSignal_Object),
196 : .tp_dealloc = (destructor)py_tevent_signal_dealloc,
197 : .tp_flags = Py_TPFLAGS_DEFAULT,
198 : };
199 :
200 1 : static PyObject *py_tevent_context_add_signal(TeventContext_Object *self, PyObject *args)
201 : {
202 : int signum, sa_flags;
203 : PyObject *handler;
204 : struct tevent_signal *sig;
205 : TeventSignal_Object *ret;
206 :
207 1 : if (!PyArg_ParseTuple(args, "iiO", &signum, &sa_flags, &handler))
208 0 : return NULL;
209 :
210 1 : Py_INCREF(handler);
211 1 : sig = tevent_add_signal(self->ev, NULL, signum, sa_flags,
212 : py_tevent_signal_handler, handler);
213 :
214 1 : ret = PyObject_New(TeventSignal_Object, &TeventSignal_Type);
215 1 : if (ret == NULL) {
216 0 : PyErr_NoMemory();
217 0 : talloc_free(sig);
218 0 : return NULL;
219 : }
220 :
221 1 : ret->signal = sig;
222 :
223 1 : return (PyObject *)ret;
224 : }
225 :
226 4 : static void py_timer_handler(struct tevent_context *ev,
227 : struct tevent_timer *te,
228 : struct timeval current_time,
229 : void *private_data)
230 : {
231 4 : TeventTimer_Object *self = private_data;
232 : PyObject *ret;
233 :
234 4 : ret = PyObject_CallFunction(self->callback, discard_const_p(char, "l"), te);
235 4 : if (ret == NULL) {
236 : /* No Python stack to propagate exception to; just print traceback */
237 0 : PyErr_PrintEx(0);
238 : }
239 4 : Py_XDECREF(ret);
240 4 : }
241 :
242 5 : static void py_tevent_timer_dealloc(TeventTimer_Object *self)
243 : {
244 5 : if (self->timer) {
245 0 : talloc_free(self->timer);
246 : }
247 5 : Py_DECREF(self->callback);
248 5 : PyObject_Del(self);
249 5 : }
250 :
251 0 : static int py_tevent_timer_traverse(TeventTimer_Object *self, visitproc visit, void *arg)
252 : {
253 0 : Py_VISIT(self->callback);
254 0 : return 0;
255 : }
256 :
257 4 : static PyObject* py_tevent_timer_get_active(TeventTimer_Object *self,
258 : PyObject *Py_UNUSED(ignored))
259 : {
260 4 : return PyBool_FromLong(self->timer != NULL);
261 : }
262 :
263 : struct PyGetSetDef py_tevent_timer_getset[] = {
264 : {
265 : .name = discard_const_p(char, "active"),
266 : .get = (getter)py_tevent_timer_get_active,
267 : .doc = discard_const_p(char, "true if the timer is scheduled to run"),
268 : },
269 : {0},
270 : };
271 :
272 : static PyTypeObject TeventTimer_Type = {
273 : .tp_name = "tevent.Timer",
274 : .tp_basicsize = sizeof(TeventTimer_Object),
275 : .tp_dealloc = (destructor)py_tevent_timer_dealloc,
276 : .tp_traverse = (traverseproc)py_tevent_timer_traverse,
277 : .tp_getset = py_tevent_timer_getset,
278 : .tp_flags = Py_TPFLAGS_DEFAULT,
279 : };
280 :
281 : struct TeventTimer_Object_ref {
282 : TeventTimer_Object *obj;
283 : };
284 :
285 5 : static int TeventTimer_Object_ref_destructor(struct TeventTimer_Object_ref *ref)
286 : {
287 5 : ref->obj->timer = NULL;
288 5 : Py_DECREF(ref->obj);
289 5 : return 0;
290 : }
291 :
292 5 : static PyObject *py_tevent_context_add_timer_internal(TeventContext_Object *self,
293 : struct timeval next_event,
294 : PyObject *callback)
295 : {
296 : /* Ownership notes:
297 : *
298 : * There are 5 pieces in play; two tevent contexts and 3 Python objects:
299 : * - The tevent timer
300 : * - The tevent context
301 : * - The Python context -- "self"
302 : * - The Python timer (TeventTimer_Object) -- "ret"
303 : * - The Python callback function -- "callback"
304 : *
305 : * We only use the Python context for getting the tevent context,
306 : * afterwards it can be destroyed.
307 : *
308 : * The tevent context owns the tevent timer.
309 : *
310 : * The tevent timer holds a reference to the Python timer, so the Python
311 : * timer must always outlive the tevent timer.
312 : * The Python timer has a pointer to the tevent timer; a destructor is
313 : * used to set this to NULL when the tevent timer is deallocated.
314 : *
315 : * The tevent timer can be deallocated in these cases:
316 : * 1) when the context is destroyed
317 : * 2) after the event fires
318 : * Posssibly, API might be added to cancel (free the tevent timer).
319 : *
320 : * The Python timer holds a reference to the callback.
321 : */
322 : TeventTimer_Object *ret;
323 : struct TeventTimer_Object_ref *ref;
324 :
325 5 : ret = PyObject_New(TeventTimer_Object, &TeventTimer_Type);
326 5 : if (ret == NULL) {
327 0 : PyErr_NoMemory();
328 0 : return NULL;
329 : }
330 5 : Py_INCREF(callback);
331 5 : ret->callback = callback;
332 5 : ret->timer = tevent_add_timer(self->ev, NULL, next_event, py_timer_handler,
333 : ret);
334 5 : if (ret->timer == NULL) {
335 0 : Py_DECREF(ret);
336 0 : PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer");
337 0 : return NULL;
338 : }
339 5 : ref = talloc(ret->timer, struct TeventTimer_Object_ref);
340 5 : if (ref == NULL) {
341 0 : talloc_free(ret->timer);
342 0 : Py_DECREF(ret);
343 0 : PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer");
344 0 : return NULL;
345 : }
346 5 : Py_INCREF(ret);
347 5 : ref->obj = ret;
348 :
349 5 : talloc_set_destructor(ref, TeventTimer_Object_ref_destructor);
350 :
351 5 : return (PyObject *)ret;
352 : }
353 :
354 3 : static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args)
355 : {
356 : struct timeval next_event;
357 : PyObject *callback;
358 : double secs, usecs;
359 3 : if (!PyArg_ParseTuple(args, "dO", &secs, &callback)){
360 0 : return NULL;
361 : }
362 3 : next_event.tv_sec = secs;
363 3 : usecs = (secs - next_event.tv_sec) * 1000000.0;
364 3 : next_event.tv_usec = usecs;
365 3 : return py_tevent_context_add_timer_internal(self, next_event, callback);
366 : }
367 :
368 2 : static PyObject *py_tevent_context_add_timer_offset(TeventContext_Object *self, PyObject *args)
369 : {
370 : struct timeval next_event;
371 : double offset;
372 : int seconds;
373 : PyObject *callback;
374 2 : if (!PyArg_ParseTuple(args, "dO", &offset, &callback))
375 0 : return NULL;
376 :
377 2 : seconds = offset;
378 2 : offset -= seconds;
379 2 : next_event = tevent_timeval_current_ofs(seconds, (int)(offset*1000000));
380 2 : return py_tevent_context_add_timer_internal(self, next_event, callback);
381 : }
382 :
383 0 : static void py_fd_handler(struct tevent_context *ev,
384 : struct tevent_fd *fde,
385 : uint16_t flags,
386 : void *private_data)
387 : {
388 0 : PyObject *callback = private_data, *ret;
389 :
390 0 : ret = PyObject_CallFunction(callback, discard_const_p(char, "i"), flags);
391 0 : Py_XDECREF(ret);
392 0 : }
393 :
394 0 : static void py_tevent_fp_dealloc(TeventFd_Object *self)
395 : {
396 0 : talloc_free(self->fd);
397 0 : PyObject_Del(self);
398 0 : }
399 :
400 : static PyTypeObject TeventFd_Type = {
401 : .tp_name = "tevent.Fd",
402 : .tp_basicsize = sizeof(TeventFd_Object),
403 : .tp_dealloc = (destructor)py_tevent_fp_dealloc,
404 : .tp_flags = Py_TPFLAGS_DEFAULT,
405 : };
406 :
407 0 : static PyObject *py_tevent_context_add_fd(TeventContext_Object *self, PyObject *args)
408 : {
409 : int fd, flags;
410 : PyObject *handler;
411 : struct tevent_fd *tfd;
412 : TeventFd_Object *ret;
413 :
414 0 : if (!PyArg_ParseTuple(args, "iiO", &fd, &flags, &handler))
415 0 : return NULL;
416 :
417 0 : tfd = tevent_add_fd(self->ev, NULL, fd, flags, py_fd_handler, handler);
418 0 : if (tfd == NULL) {
419 0 : PyErr_SetNone(PyExc_RuntimeError);
420 0 : return NULL;
421 : }
422 :
423 0 : ret = PyObject_New(TeventFd_Object, &TeventFd_Type);
424 0 : if (ret == NULL) {
425 0 : talloc_free(tfd);
426 0 : return NULL;
427 : }
428 0 : ret->fd = tfd;
429 :
430 0 : return (PyObject *)ret;
431 : }
432 :
433 : static PyMethodDef py_tevent_context_methods[] = {
434 : { "reinitialise", (PyCFunction)py_tevent_context_reinitialise,
435 : METH_NOARGS,
436 : "S.reinitialise()" },
437 : { "wakeup_send", (PyCFunction)py_tevent_context_wakeup_send,
438 : METH_VARARGS, "S.wakeup_send(wakeup_time) -> req" },
439 : { "loop_wait", (PyCFunction)py_tevent_context_loop_wait,
440 : METH_NOARGS, "S.loop_wait()" },
441 : { "loop_once", (PyCFunction)py_tevent_context_loop_once,
442 : METH_NOARGS, "S.loop_once()" },
443 : { "add_signal", (PyCFunction)py_tevent_context_add_signal,
444 : METH_VARARGS, "S.add_signal(signum, sa_flags, handler) -> signal" },
445 : { "add_timer", (PyCFunction)py_tevent_context_add_timer,
446 : METH_VARARGS, "S.add_timer(next_event, handler) -> timer" },
447 : { "add_timer_offset", (PyCFunction)py_tevent_context_add_timer_offset,
448 : METH_VARARGS, "S.add_timer_offset(offset_seconds, handler) -> timer" },
449 : { "add_fd", (PyCFunction)py_tevent_context_add_fd,
450 : METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" },
451 : {0},
452 : };
453 :
454 0 : static PyObject *py_tevent_req_wakeup_recv(PyObject *self,
455 : PyObject *Py_UNUSED(ignored))
456 : {
457 : /* FIXME */
458 0 : Py_RETURN_NONE;
459 : }
460 :
461 0 : static PyObject *py_tevent_req_received(PyObject *self,
462 : PyObject *Py_UNUSED(ignored))
463 : {
464 : /* FIXME */
465 0 : Py_RETURN_NONE;
466 : }
467 :
468 0 : static PyObject *py_tevent_req_is_error(PyObject *self,
469 : PyObject *Py_UNUSED(ignored))
470 : {
471 : /* FIXME */
472 0 : Py_RETURN_NONE;
473 : }
474 :
475 0 : static PyObject *py_tevent_req_poll(PyObject *self,
476 : PyObject *Py_UNUSED(ignored))
477 : {
478 : /* FIXME */
479 0 : Py_RETURN_NONE;
480 : }
481 :
482 0 : static PyObject *py_tevent_req_is_in_progress(PyObject *self,
483 : PyObject *Py_UNUSED(ignored))
484 : {
485 : /* FIXME */
486 0 : Py_RETURN_NONE;
487 : }
488 :
489 : static PyGetSetDef py_tevent_req_getsetters[] = {
490 : {
491 : .name = discard_const_p(char, "in_progress"),
492 : .get = (getter)py_tevent_req_is_in_progress,
493 : .doc = discard_const_p(char, "Whether the request is in progress"),
494 : },
495 : {0}
496 : };
497 :
498 0 : static PyObject *py_tevent_req_post(PyObject *self, PyObject *args)
499 : {
500 : /* FIXME */
501 0 : Py_RETURN_NONE;
502 : }
503 :
504 0 : static PyObject *py_tevent_req_set_error(PyObject *self, PyObject *args)
505 : {
506 : /* FIXME */
507 0 : Py_RETURN_NONE;
508 : }
509 :
510 0 : static PyObject *py_tevent_req_done(PyObject *self,
511 : PyObject *Py_UNUSED(ignored))
512 : {
513 : /* FIXME */
514 0 : Py_RETURN_NONE;
515 : }
516 :
517 0 : static PyObject *py_tevent_req_notify_callback(PyObject *self,
518 : PyObject *Py_UNUSED(ignored))
519 : {
520 : /* FIXME */
521 0 : Py_RETURN_NONE;
522 : }
523 :
524 0 : static PyObject *py_tevent_req_set_endtime(PyObject *self, PyObject *args)
525 : {
526 : /* FIXME */
527 0 : Py_RETURN_NONE;
528 : }
529 :
530 0 : static PyObject *py_tevent_req_cancel(TeventReq_Object *self,
531 : PyObject *Py_UNUSED(ignored))
532 : {
533 0 : if (!tevent_req_cancel(self->req)) {
534 0 : PyErr_SetNone(PyExc_RuntimeError);
535 0 : return NULL;
536 : }
537 0 : Py_RETURN_NONE;
538 : }
539 :
540 : static PyMethodDef py_tevent_req_methods[] = {
541 : { "wakeup_recv", (PyCFunction)py_tevent_req_wakeup_recv,
542 : METH_NOARGS,
543 : "Wakeup received" },
544 : { "received", (PyCFunction)py_tevent_req_received,
545 : METH_NOARGS,
546 : "Receive finished" },
547 : { "is_error", (PyCFunction)py_tevent_req_is_error, METH_NOARGS,
548 : "is_error() -> (error, state)" },
549 : { "poll", (PyCFunction)py_tevent_req_poll, METH_VARARGS,
550 : "poll(ctx)" },
551 : { "post", (PyCFunction)py_tevent_req_post, METH_VARARGS,
552 : "post(ctx) -> req" },
553 : { "set_error", (PyCFunction)py_tevent_req_set_error, METH_VARARGS,
554 : "set_error(error)" },
555 : { "done", (PyCFunction)py_tevent_req_done, METH_NOARGS,
556 : "done()" },
557 : { "notify_callback", (PyCFunction)py_tevent_req_notify_callback,
558 : METH_NOARGS, "notify_callback()" },
559 : { "set_endtime", (PyCFunction)py_tevent_req_set_endtime,
560 : METH_VARARGS, "set_endtime(ctx, endtime)" },
561 : { "cancel", (PyCFunction)py_tevent_req_cancel,
562 : METH_NOARGS, "cancel()" },
563 : {0}
564 : };
565 :
566 0 : static void py_tevent_req_dealloc(TeventReq_Object *self)
567 : {
568 0 : talloc_free(self->req);
569 0 : PyObject_DEL(self);
570 0 : }
571 :
572 : static PyTypeObject TeventReq_Type = {
573 : .tp_name = "tevent.Request",
574 : .tp_basicsize = sizeof(TeventReq_Object),
575 : .tp_methods = py_tevent_req_methods,
576 : .tp_dealloc = (destructor)py_tevent_req_dealloc,
577 : .tp_getset = py_tevent_req_getsetters,
578 : /* FIXME: .tp_new = py_tevent_req_new, */
579 : };
580 :
581 0 : static PyObject *py_tevent_queue_get_length(TeventQueue_Object *self,
582 : PyObject *Py_UNUSED(ignored))
583 : {
584 0 : return PyLong_FromLong(tevent_queue_length(self->queue));
585 : }
586 :
587 : static PyGetSetDef py_tevent_queue_getsetters[] = {
588 : {
589 : .name = discard_const_p(char, "length"),
590 : .get = (getter)py_tevent_queue_get_length,
591 : .doc = discard_const_p(char, "The number of elements in the queue."),
592 : },
593 : {0},
594 : };
595 :
596 0 : static void py_tevent_queue_dealloc(TeventQueue_Object *self)
597 : {
598 0 : talloc_free(self->queue);
599 0 : PyObject_Del(self);
600 0 : }
601 :
602 : static PyTypeObject TeventQueue_Type = {
603 : .tp_name = "tevent.Queue",
604 : .tp_basicsize = sizeof(TeventQueue_Object),
605 : .tp_dealloc = (destructor)py_tevent_queue_dealloc,
606 : .tp_flags = Py_TPFLAGS_DEFAULT,
607 : .tp_getset = py_tevent_queue_getsetters,
608 : .tp_methods = py_tevent_queue_methods,
609 : };
610 :
611 1 : static PyObject *py_tevent_context_signal_support(PyObject *_self,
612 : PyObject *Py_UNUSED(ignored))
613 : {
614 1 : TeventContext_Object *self = (TeventContext_Object *)_self;
615 1 : return PyBool_FromLong(tevent_signal_support(self->ev));
616 : }
617 :
618 : static PyGetSetDef py_tevent_context_getsetters[] = {
619 : {
620 : .name = discard_const_p(char, "signal_support"),
621 : .get = PY_DISCARD_FUNC_SIG(getter,
622 : py_tevent_context_signal_support),
623 : .doc = discard_const_p(char, "if this platform and tevent context support signal handling"),
624 : },
625 : {0}
626 : };
627 :
628 10 : static void py_tevent_context_dealloc(TeventContext_Object *self)
629 : {
630 10 : talloc_free(self->ev);
631 10 : PyObject_Del(self);
632 10 : }
633 :
634 10 : static PyObject *py_tevent_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
635 : {
636 10 : const char * const kwnames[] = { "name", NULL };
637 10 : char *name = NULL;
638 : struct tevent_context *ev;
639 : TeventContext_Object *ret;
640 :
641 10 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", discard_const_p(char *, kwnames), &name))
642 0 : return NULL;
643 :
644 10 : if (name == NULL) {
645 9 : ev = tevent_context_init(NULL);
646 : } else {
647 1 : ev = tevent_context_init_byname(NULL, name);
648 : }
649 :
650 10 : if (ev == NULL) {
651 0 : PyErr_SetNone(PyExc_RuntimeError);
652 0 : return NULL;
653 : }
654 :
655 10 : ret = PyObject_New(TeventContext_Object, type);
656 10 : if (ret == NULL) {
657 0 : PyErr_NoMemory();
658 0 : talloc_free(ev);
659 0 : return NULL;
660 : }
661 :
662 10 : ret->ev = ev;
663 10 : return (PyObject *)ret;
664 : }
665 :
666 : static PyTypeObject TeventContext_Type = {
667 : .tp_name = "tevent.Context",
668 : .tp_new = py_tevent_context_new,
669 : .tp_basicsize = sizeof(TeventContext_Object),
670 : .tp_dealloc = (destructor)py_tevent_context_dealloc,
671 : .tp_methods = py_tevent_context_methods,
672 : .tp_getset = py_tevent_context_getsetters,
673 : .tp_flags = Py_TPFLAGS_DEFAULT,
674 : };
675 :
676 0 : static PyObject *py_set_default_backend(PyObject *self, PyObject *args)
677 : {
678 : char *backend_name;
679 0 : if (!PyArg_ParseTuple(args, "s", &backend_name))
680 0 : return NULL;
681 :
682 0 : tevent_set_default_backend(backend_name);
683 :
684 0 : Py_RETURN_NONE;
685 : }
686 :
687 2 : static PyObject *py_backend_list(PyObject *self,
688 : PyObject *Py_UNUSED(ignored))
689 : {
690 2 : PyObject *ret = NULL;
691 2 : PyObject *string = NULL;
692 : int i, result;
693 2 : const char **backends = NULL;
694 :
695 2 : ret = PyList_New(0);
696 2 : if (ret == NULL) {
697 0 : return NULL;
698 : }
699 :
700 2 : backends = tevent_backend_list(NULL);
701 2 : if (backends == NULL) {
702 0 : PyErr_SetNone(PyExc_RuntimeError);
703 0 : goto err;
704 : }
705 10 : for (i = 0; backends[i]; i++) {
706 8 : string = PyUnicode_FromString(backends[i]);
707 8 : if (!string) {
708 0 : goto err;
709 : }
710 8 : result = PyList_Append(ret, string);
711 8 : if (result) {
712 0 : goto err;
713 : }
714 8 : Py_DECREF(string);
715 8 : string = NULL;
716 : }
717 :
718 2 : talloc_free(backends);
719 :
720 2 : return ret;
721 :
722 0 : err:
723 0 : Py_XDECREF(ret);
724 0 : Py_XDECREF(string);
725 0 : talloc_free(backends);
726 0 : return NULL;
727 : }
728 :
729 : static PyMethodDef tevent_methods[] = {
730 : { "set_default_backend", (PyCFunction)py_set_default_backend,
731 : METH_VARARGS, "set_default_backend(backend)" },
732 : { "backend_list", (PyCFunction)py_backend_list,
733 : METH_NOARGS, "backend_list() -> list" },
734 : {0},
735 : };
736 :
737 : #define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.")
738 :
739 : #if PY_MAJOR_VERSION >= 3
740 : static struct PyModuleDef moduledef = {
741 : PyModuleDef_HEAD_INIT,
742 : .m_name = "_tevent",
743 : .m_doc = MODULE_DOC,
744 : .m_size = -1,
745 : .m_methods = tevent_methods,
746 : };
747 : #endif
748 :
749 : PyObject * module_init(void);
750 1 : PyObject * module_init(void)
751 : {
752 : PyObject *m;
753 :
754 1 : if (PyType_Ready(&TeventContext_Type) < 0)
755 0 : return NULL;
756 :
757 1 : if (PyType_Ready(&TeventQueue_Type) < 0)
758 0 : return NULL;
759 :
760 1 : if (PyType_Ready(&TeventReq_Type) < 0)
761 0 : return NULL;
762 :
763 1 : if (PyType_Ready(&TeventSignal_Type) < 0)
764 0 : return NULL;
765 :
766 1 : if (PyType_Ready(&TeventTimer_Type) < 0)
767 0 : return NULL;
768 :
769 1 : if (PyType_Ready(&TeventFd_Type) < 0)
770 0 : return NULL;
771 :
772 : #if PY_MAJOR_VERSION >= 3
773 1 : m = PyModule_Create(&moduledef);
774 : #else
775 : m = Py_InitModule3("_tevent", tevent_methods, MODULE_DOC);
776 : #endif
777 1 : if (m == NULL)
778 0 : return NULL;
779 :
780 1 : Py_INCREF(&TeventContext_Type);
781 1 : PyModule_AddObject(m, "Context", (PyObject *)&TeventContext_Type);
782 :
783 1 : Py_INCREF(&TeventQueue_Type);
784 1 : PyModule_AddObject(m, "Queue", (PyObject *)&TeventQueue_Type);
785 :
786 1 : Py_INCREF(&TeventReq_Type);
787 1 : PyModule_AddObject(m, "Request", (PyObject *)&TeventReq_Type);
788 :
789 1 : Py_INCREF(&TeventSignal_Type);
790 1 : PyModule_AddObject(m, "Signal", (PyObject *)&TeventSignal_Type);
791 :
792 1 : Py_INCREF(&TeventTimer_Type);
793 1 : PyModule_AddObject(m, "Timer", (PyObject *)&TeventTimer_Type);
794 :
795 1 : Py_INCREF(&TeventFd_Type);
796 1 : PyModule_AddObject(m, "Fd", (PyObject *)&TeventFd_Type);
797 :
798 1 : PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
799 :
800 1 : return m;
801 : }
802 :
803 : #if PY_MAJOR_VERSION >= 3
804 : PyMODINIT_FUNC PyInit__tevent(void);
805 1 : PyMODINIT_FUNC PyInit__tevent(void)
806 : {
807 1 : return module_init();
808 : }
809 : #else
810 : void init_tevent(void);
811 : void init_tevent(void)
812 : {
813 : module_init();
814 : }
815 : #endif
|