LCOV - code coverage report
Current view: top level - lib/tevent - pytevent.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 125 264 47.3 %
Date: 2024-02-14 10:14:15 Functions: 18 43 41.9 %

          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

Generated by: LCOV version 1.14