LCOV - code coverage report
Current view: top level - lib/tevent - pytevent.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 125 264 47.3 %
Date: 2023-11-21 12:31:41 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 "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             : }

Generated by: LCOV version 1.14