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