Changeset 988 for vendor/current/lib/tevent/pytevent.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/lib/tevent/pytevent.c
r740 r988 24 24 25 25 #include <Python.h> 26 #include "replace.h" 26 27 #include <tevent.h> 28 29 #if PY_MAJOR_VERSION >= 3 30 #define PyStr_Check PyUnicode_Check 31 #define PyStr_FromString PyUnicode_FromString 32 #define PyStr_AsUTF8 PyUnicode_AsUTF8 33 #define PyInt_FromLong PyLong_FromLong 34 #else 35 #define PyStr_Check PyString_Check 36 #define PyStr_FromString PyString_FromString 37 #define PyStr_AsUTF8 PyString_AsString 38 #endif 39 40 void init_tevent(void); 27 41 28 42 typedef struct { … … 49 63 PyObject_HEAD 50 64 struct tevent_timer *timer; 65 PyObject *callback; 51 66 } TeventTimer_Object; 52 67 … … 56 71 } TeventFd_Object; 57 72 58 static forwardPyTypeObject TeventContext_Type;59 static forwardPyTypeObject TeventReq_Type;60 static forwardPyTypeObject TeventQueue_Type;61 static forwardPyTypeObject TeventSignal_Type;62 static forwardPyTypeObject TeventTimer_Type;63 static forwardPyTypeObject TeventFd_Type;73 static PyTypeObject TeventContext_Type; 74 static PyTypeObject TeventReq_Type; 75 static PyTypeObject TeventQueue_Type; 76 static PyTypeObject TeventSignal_Type; 77 static PyTypeObject TeventTimer_Type; 78 static PyTypeObject TeventFd_Type; 64 79 65 80 static int py_context_init(struct tevent_context *ev) … … 87 102 } 88 103 89 uint16_t py_get_fd_flags(struct tevent_fd *fde)104 static uint16_t py_get_fd_flags(struct tevent_fd *fde) 90 105 { 91 106 /* FIXME */ … … 174 189 } 175 190 176 if (!PyStr ing_Check(name)) {191 if (!PyStr_Check(name)) { 177 192 PyErr_SetNone(PyExc_TypeError); 178 return NULL; 179 } 180 181 if (!tevent_register_backend(PyString_AsString(name), &py_tevent_ops)) { /* FIXME: What to do with backend */ 193 Py_DECREF(name); 194 return NULL; 195 } 196 197 if (!tevent_register_backend(PyStr_AsUTF8(name), &py_tevent_ops)) { /* FIXME: What to do with backend */ 182 198 PyErr_SetNone(PyExc_RuntimeError); 183 return NULL; 184 } 199 Py_DECREF(name); 200 return NULL; 201 } 202 203 Py_DECREF(name); 185 204 186 205 Py_RETURN_NONE; … … 213 232 PyObject *callback = private_data, *ret; 214 233 215 ret = PyObject_CallFunction(callback, "");234 ret = PyObject_CallFunction(callback, discard_const_p(char, "")); 216 235 Py_XDECREF(ret); 217 236 } … … 278 297 } 279 298 280 #ifdef TEVENT_DEPRECATED281 static bool py_tevent_finished(PyObject *callback)282 {283 PyObject *py_ret;284 bool ret;285 286 py_ret = PyObject_CallFunction(callback, "");287 if (py_ret == NULL)288 return true;289 ret = PyObject_IsTrue(py_ret);290 Py_DECREF(py_ret);291 return ret;292 }293 294 static PyObject *py_tevent_context_loop_until(TeventContext_Object *self, PyObject *args)295 {296 PyObject *callback;297 if (!PyArg_ParseTuple(args, "O", &callback))298 return NULL;299 300 if (tevent_loop_until(self->ev, py_tevent_finished, callback) != 0) {301 PyErr_SetNone(PyExc_RuntimeError);302 return NULL;303 }304 305 if (PyErr_Occurred())306 return NULL;307 308 Py_RETURN_NONE;309 }310 #endif311 312 299 static void py_tevent_signal_handler(struct tevent_context *ev, 313 300 struct tevent_signal *se, … … 319 306 PyObject *callback = (PyObject *)private_data, *ret; 320 307 321 ret = PyObject_CallFunction(callback, "ii", signum, count);308 ret = PyObject_CallFunction(callback, discard_const_p(char, "ii"), signum, count); 322 309 Py_XDECREF(ret); 323 310 } … … 330 317 331 318 static PyTypeObject TeventSignal_Type = { 332 .tp_name = " Signal",319 .tp_name = "tevent.Signal", 333 320 .tp_basicsize = sizeof(TeventSignal_Object), 334 321 .tp_dealloc = (destructor)py_tevent_signal_dealloc, … … 367 354 void *private_data) 368 355 { 369 PyObject *callback = private_data, *ret; 370 ret = PyObject_CallFunction(callback, "l", te); 356 TeventTimer_Object *self = private_data; 357 PyObject *ret; 358 359 ret = PyObject_CallFunction(self->callback, discard_const_p(char, "l"), te); 360 if (ret == NULL) { 361 /* No Python stack to propagate exception to; just print traceback */ 362 PyErr_PrintEx(0); 363 } 371 364 Py_XDECREF(ret); 372 365 } 373 366 374 static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args) 375 { 367 static void py_tevent_timer_dealloc(TeventTimer_Object *self) 368 { 369 if (self->timer) { 370 talloc_free(self->timer); 371 } 372 Py_DECREF(self->callback); 373 PyObject_Del(self); 374 } 375 376 static int py_tevent_timer_traverse(TeventTimer_Object *self, visitproc visit, void *arg) 377 { 378 Py_VISIT(self->callback); 379 return 0; 380 } 381 382 static PyObject* py_tevent_timer_get_active(TeventTimer_Object *self) { 383 return PyBool_FromLong(self->timer != NULL); 384 } 385 386 struct PyGetSetDef py_tevent_timer_getset[] = { 387 { 388 .name = discard_const_p(char, "active"), 389 .get = (getter)py_tevent_timer_get_active, 390 .doc = discard_const_p(char, "true if the timer is scheduled to run"), 391 }, 392 {NULL}, 393 }; 394 395 static PyTypeObject TeventTimer_Type = { 396 .tp_name = "tevent.Timer", 397 .tp_basicsize = sizeof(TeventTimer_Object), 398 .tp_dealloc = (destructor)py_tevent_timer_dealloc, 399 .tp_traverse = (traverseproc)py_tevent_timer_traverse, 400 .tp_getset = py_tevent_timer_getset, 401 .tp_flags = Py_TPFLAGS_DEFAULT, 402 }; 403 404 struct TeventTimer_Object_ref { 405 TeventTimer_Object *obj; 406 }; 407 408 static int TeventTimer_Object_ref_destructor(struct TeventTimer_Object_ref *ref) 409 { 410 ref->obj->timer = NULL; 411 Py_DECREF(ref->obj); 412 return 0; 413 } 414 415 static PyObject *py_tevent_context_add_timer_internal(TeventContext_Object *self, 416 struct timeval next_event, 417 PyObject *callback) 418 { 419 /* Ownership notes: 420 * 421 * There are 5 pieces in play; two tevent contexts and 3 Python objects: 422 * - The tevent timer 423 * - The tevent context 424 * - The Python context -- "self" 425 * - The Python timer (TeventTimer_Object) -- "ret" 426 * - The Python callback function -- "callback" 427 * 428 * We only use the Python context for getting the tevent context, 429 * afterwards it can be destroyed. 430 * 431 * The tevent context owns the tevent timer. 432 * 433 * The tevent timer holds a reference to the Python timer, so the Python 434 * timer must always outlive the tevent timer. 435 * The Python timer has a pointer to the tevent timer; a destructor is 436 * used to set this to NULL when the tevent timer is deallocated. 437 * 438 * The tevent timer can be deallocated in these cases: 439 * 1) when the context is destroyed 440 * 2) after the event fires 441 * Posssibly, API might be added to cancel (free the tevent timer). 442 * 443 * The Python timer holds a reference to the callback. 444 */ 376 445 TeventTimer_Object *ret; 377 struct timeval next_event; 378 struct tevent_timer *timer; 379 PyObject *handler; 380 if (!PyArg_ParseTuple(args, "lO", &next_event, &handler)) 381 return NULL; 382 383 timer = tevent_add_timer(self->ev, NULL, next_event, py_timer_handler, 384 handler); 385 if (timer == NULL) { 386 PyErr_SetNone(PyExc_RuntimeError); 387 return NULL; 388 } 446 struct TeventTimer_Object_ref *ref; 389 447 390 448 ret = PyObject_New(TeventTimer_Object, &TeventTimer_Type); 391 449 if (ret == NULL) { 392 450 PyErr_NoMemory(); 393 talloc_free(timer); 394 return NULL; 395 } 396 ret->timer = timer; 451 return NULL; 452 } 453 Py_INCREF(callback); 454 ret->callback = callback; 455 ret->timer = tevent_add_timer(self->ev, NULL, next_event, py_timer_handler, 456 ret); 457 if (ret->timer == NULL) { 458 Py_DECREF(ret); 459 PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); 460 return NULL; 461 } 462 ref = talloc(ret->timer, struct TeventTimer_Object_ref); 463 if (ref == NULL) { 464 talloc_free(ret->timer); 465 Py_DECREF(ret); 466 PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); 467 return NULL; 468 } 469 Py_INCREF(ret); 470 ref->obj = ret; 471 472 talloc_set_destructor(ref, TeventTimer_Object_ref_destructor); 397 473 398 474 return (PyObject *)ret; 475 } 476 477 static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args) 478 { 479 struct timeval next_event; 480 PyObject *callback; 481 if (!PyArg_ParseTuple(args, "lO", &next_event, &callback)) 482 return NULL; 483 484 return py_tevent_context_add_timer_internal(self, next_event, callback); 485 } 486 487 static PyObject *py_tevent_context_add_timer_offset(TeventContext_Object *self, PyObject *args) 488 { 489 struct timeval next_event; 490 double offset; 491 int seconds; 492 PyObject *callback; 493 if (!PyArg_ParseTuple(args, "dO", &offset, &callback)) 494 return NULL; 495 496 seconds = offset; 497 offset -= seconds; 498 next_event = tevent_timeval_current_ofs(seconds, (int)(offset*1000000)); 499 return py_tevent_context_add_timer_internal(self, next_event, callback); 399 500 } 400 501 … … 406 507 PyObject *callback = private_data, *ret; 407 508 408 ret = PyObject_CallFunction(callback, "i", flags);509 ret = PyObject_CallFunction(callback, discard_const_p(char, "i"), flags); 409 510 Py_XDECREF(ret); 410 511 } 512 513 static void py_tevent_fp_dealloc(TeventFd_Object *self) 514 { 515 talloc_free(self->fd); 516 PyObject_Del(self); 517 } 518 519 static PyTypeObject TeventFd_Type = { 520 .tp_name = "tevent.Fd", 521 .tp_basicsize = sizeof(TeventFd_Object), 522 .tp_dealloc = (destructor)py_tevent_fp_dealloc, 523 .tp_flags = Py_TPFLAGS_DEFAULT, 524 }; 411 525 412 526 static PyObject *py_tevent_context_add_fd(TeventContext_Object *self, PyObject *args) … … 435 549 return (PyObject *)ret; 436 550 } 437 438 #ifdef TEVENT_DEPRECATED439 static PyObject *py_tevent_context_set_allow_nesting(TeventContext_Object *self)440 {441 tevent_loop_allow_nesting(self->ev);442 Py_RETURN_NONE;443 }444 #endif445 551 446 552 static PyMethodDef py_tevent_context_methods[] = { … … 453 559 { "loop_once", (PyCFunction)py_tevent_context_loop_once, 454 560 METH_NOARGS, "S.loop_once()" }, 455 #ifdef TEVENT_DEPRECATED456 { "loop_until", (PyCFunction)py_tevent_context_loop_until,457 METH_VARARGS, "S.loop_until(callback)" },458 #endif459 561 { "add_signal", (PyCFunction)py_tevent_context_add_signal, 460 562 METH_VARARGS, "S.add_signal(signum, sa_flags, handler) -> signal" }, 461 563 { "add_timer", (PyCFunction)py_tevent_context_add_timer, 462 564 METH_VARARGS, "S.add_timer(next_event, handler) -> timer" }, 565 { "add_timer_offset", (PyCFunction)py_tevent_context_add_timer_offset, 566 METH_VARARGS, "S.add_timer(offset_seconds, handler) -> timer" }, 463 567 { "add_fd", (PyCFunction)py_tevent_context_add_fd, 464 568 METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" }, 465 #ifdef TEVENT_DEPRECATED466 { "allow_nesting", (PyCFunction)py_tevent_context_set_allow_nesting,467 METH_NOARGS, "Whether to allow nested tevent loops." },468 #endif469 569 { NULL }, 470 570 }; … … 501 601 502 602 static PyGetSetDef py_tevent_req_getsetters[] = { 503 { "in_progress", (getter)py_tevent_req_is_in_progress, NULL, 504 "Whether the request is in progress" }, 603 { 604 .name = discard_const_p(char, "in_progress"), 605 .get = (getter)py_tevent_req_is_in_progress, 606 .doc = discard_const_p(char, "Whether the request is in progress"), 607 }, 505 608 { NULL } 506 609 }; … … 590 693 591 694 static PyGetSetDef py_tevent_queue_getsetters[] = { 592 { "length", (getter)py_tevent_queue_get_length, 593 NULL, "The number of elements in the queue." }, 695 { 696 .name = discard_const_p(char, "length"), 697 .get = (getter)py_tevent_queue_get_length, 698 .doc = discard_const_p(char, "The number of elements in the queue."), 699 }, 594 700 { NULL }, 595 701 }; … … 617 723 618 724 static PyGetSetDef py_tevent_context_getsetters[] = { 619 { "signal_support", (getter)py_tevent_context_signal_support, 620 NULL, "if this platform and tevent context support signal handling" }, 725 { 726 .name = discard_const_p(char, "signal_support"), 727 .get = (getter)py_tevent_context_signal_support, 728 .doc = discard_const_p(char, "if this platform and tevent context support signal handling"), 729 }, 621 730 { NULL } 622 731 }; … … 635 744 TeventContext_Object *ret; 636 745 637 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwnames, &name))746 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", discard_const_p(char *, kwnames), &name)) 638 747 return NULL; 639 748 … … 661 770 662 771 static PyTypeObject TeventContext_Type = { 663 .tp_name = " _tevent.Context",772 .tp_name = "tevent.Context", 664 773 .tp_new = py_tevent_context_new, 665 774 .tp_basicsize = sizeof(TeventContext_Object), … … 683 792 static PyObject *py_backend_list(PyObject *self) 684 793 { 685 PyObject *ret; 686 int i; 687 const char **backends; 794 PyObject *ret = NULL; 795 PyObject *string = NULL; 796 int i, result; 797 const char **backends = NULL; 688 798 689 799 ret = PyList_New(0); … … 695 805 if (backends == NULL) { 696 806 PyErr_SetNone(PyExc_RuntimeError); 697 Py_DECREF(ret); 698 return NULL; 807 goto err; 699 808 } 700 809 for (i = 0; backends[i]; i++) { 701 PyList_Append(ret, PyString_FromString(backends[i])); 810 string = PyStr_FromString(backends[i]); 811 if (!string) { 812 goto err; 813 } 814 result = PyList_Append(ret, string); 815 if (result) { 816 goto err; 817 } 818 Py_DECREF(string); 819 string = NULL; 702 820 } 703 821 … … 705 823 706 824 return ret; 825 826 err: 827 Py_XDECREF(ret); 828 Py_XDECREF(string); 829 talloc_free(backends); 830 return NULL; 707 831 } 708 832 … … 717 841 }; 718 842 719 void init_tevent(void) 843 #define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.") 844 845 #if PY_MAJOR_VERSION >= 3 846 static struct PyModuleDef moduledef = { 847 PyModuleDef_HEAD_INIT, 848 .m_name = "_tevent", 849 .m_doc = MODULE_DOC, 850 .m_size = -1, 851 .m_methods = tevent_methods, 852 }; 853 #endif 854 855 PyObject * module_init(void); 856 PyObject * module_init(void) 720 857 { 721 858 PyObject *m; 722 859 723 860 if (PyType_Ready(&TeventContext_Type) < 0) 724 return ;861 return NULL; 725 862 726 863 if (PyType_Ready(&TeventQueue_Type) < 0) 727 return ;864 return NULL; 728 865 729 866 if (PyType_Ready(&TeventReq_Type) < 0) 730 return ;867 return NULL; 731 868 732 869 if (PyType_Ready(&TeventSignal_Type) < 0) 733 return ;870 return NULL; 734 871 735 872 if (PyType_Ready(&TeventTimer_Type) < 0) 736 return ;873 return NULL; 737 874 738 875 if (PyType_Ready(&TeventFd_Type) < 0) 739 return; 740 741 m = Py_InitModule3("_tevent", tevent_methods, "Tevent integration for twisted."); 876 return NULL; 877 878 #if PY_MAJOR_VERSION >= 3 879 m = PyModule_Create(&moduledef); 880 #else 881 m = Py_InitModule3("_tevent", tevent_methods, MODULE_DOC); 882 #endif 742 883 if (m == NULL) 743 return ;884 return NULL; 744 885 745 886 Py_INCREF(&TeventContext_Type); … … 760 901 Py_INCREF(&TeventFd_Type); 761 902 PyModule_AddObject(m, "Fd", (PyObject *)&TeventFd_Type); 762 } 903 904 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION); 905 906 return m; 907 } 908 909 #if PY_MAJOR_VERSION >= 3 910 PyMODINIT_FUNC PyInit__tevent(void); 911 PyMODINIT_FUNC PyInit__tevent(void) 912 { 913 return module_init(); 914 } 915 #else 916 void init_tevent(void); 917 void init_tevent(void) 918 { 919 module_init(); 920 } 921 #endif
Note:
See TracChangeset
for help on using the changeset viewer.