diff options
author | Justus Winter <[email protected]> | 2016-06-13 17:16:30 +0000 |
---|---|---|
committer | Justus Winter <[email protected]> | 2016-06-16 12:19:17 +0000 |
commit | f3618bc615e3eff1f52fb5849cbf0f0b95515a61 (patch) | |
tree | bfd2d2020b558bc8db7bd028cdc6d24167f657f3 /lang/python/helpers.c | |
parent | python: Wrap objects implementing the buffer protocol. (diff) | |
download | gpgme-f3618bc615e3eff1f52fb5849cbf0f0b95515a61.tar.gz gpgme-f3618bc615e3eff1f52fb5849cbf0f0b95515a61.zip |
python: Rework callbacks.
Simplify how the lifetime of callback arguments is managed.
* lang/python/gpgme.i (gpgme_edit_cb_t): Check arguments.
(PyObject_p_p, void_p_p): Drop rather dangerous interface.
(pygpgme_unwrap_gpgme_ctx_t): New function.
* lang/python/helpers.c (pygpgme_clear_generic_cb): Drop dangerous
function.
(pyPassphraseCb): Assert contract.
(pygpgme_set_passphrase_cb): Use Python's calling convention so that
we can raise exceptions. Hand in 'self', get the wrapped object, and
simply store the hook data as attribute of the wrapper object.
(pyProgressCb, pygpgme_set_progress_cb): Likewise.
(pygpgme_set_status_cb): Likewise.
(pygpgme_data_new_from_cbs): Likewise.
* lang/python/helpers.h (pygpgme_clear_generic_cb): Drop prototype.
(pygpgme_set_passphrase_cb): Update prototype.
(pygpgme_set_progress_cb): Likewise.
(pygpgme_set_status_cb): Likewise.
(pygpgme_data_new_from_cbs): Likewise.
(pygpgme_unwrap_gpgme_ctx_t): New prottotype.
* lang/python/pyme/core.py (Context, Data): Update callsites.
Signed-off-by: Justus Winter <[email protected]>
Diffstat (limited to 'lang/python/helpers.c')
-rw-r--r-- | lang/python/helpers.c | 156 |
1 files changed, 129 insertions, 27 deletions
diff --git a/lang/python/helpers.c b/lang/python/helpers.c index ad33d07b..5380ff26 100644 --- a/lang/python/helpers.c +++ b/lang/python/helpers.c @@ -76,10 +76,6 @@ gpgme_error_t pygpgme_exception2code(void) { return err_status; } -void pygpgme_clear_generic_cb(PyObject **cb) { - Py_DECREF(*cb); -} - /* Exception support for callbacks. */ #define EXCINFO "_callback_excinfo" @@ -293,6 +289,7 @@ static gpgme_error_t pyPassphraseCb(void *hook, pygpgme_exception_init(); assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3); self = PyTuple_GetItem(pyhook, 0); func = PyTuple_GetItem(pyhook, 1); if (PyTuple_Size(pyhook) == 3) { @@ -374,15 +371,47 @@ static gpgme_error_t pyPassphraseCb(void *hook, return err_status; } -void pygpgme_set_passphrase_cb(gpgme_ctx_t ctx, PyObject *cb, - PyObject **freelater) { +PyObject * +pygpgme_set_passphrase_cb(PyObject *self, PyObject *cb) { + PyObject *wrapped; + gpgme_ctx_t ctx; + + wrapped = PyObject_GetAttrString(self, "wrapped"); + if (wrapped == NULL) + { + assert (PyErr_Occurred ()); + return NULL; + } + + ctx = pygpgme_unwrap_gpgme_ctx_t(wrapped); + Py_DECREF(wrapped); + if (ctx == NULL) + { + if (cb == Py_None) + goto out; + else + return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL"); + } + if (cb == Py_None) { gpgme_set_passphrase_cb(ctx, NULL, NULL); - return; + PyObject_SetAttrString(self, "_passphrase_cb", Py_None); + goto out; } - Py_INCREF(cb); - *freelater = cb; - gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t)pyPassphraseCb, (void *) cb); + + if (! PyTuple_Check(cb)) + return PyErr_Format(PyExc_TypeError, "cb must be a tuple"); + if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3) + return PyErr_Format(PyExc_TypeError, + "cb must be a tuple of size 2 or 3"); + + gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t) pyPassphraseCb, + (void *) cb); + PyObject_SetAttrString(self, "_passphrase_cb", cb); + + out: + Py_INCREF(Py_None); + return Py_None; } static void pyProgressCb(void *hook, const char *what, int type, int current, @@ -392,6 +421,7 @@ static void pyProgressCb(void *hook, const char *what, int type, int current, PyObject *self = NULL; assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3); self = PyTuple_GetItem(pyhook, 0); func = PyTuple_GetItem(pyhook, 1); if (PyTuple_Size(pyhook) == 3) { @@ -423,14 +453,46 @@ static void pyProgressCb(void *hook, const char *what, int type, int current, Py_XDECREF(retval); } -void pygpgme_set_progress_cb(gpgme_ctx_t ctx, PyObject *cb, PyObject **freelater){ +PyObject * +pygpgme_set_progress_cb(PyObject *self, PyObject *cb) { + PyObject *wrapped; + gpgme_ctx_t ctx; + + wrapped = PyObject_GetAttrString(self, "wrapped"); + if (wrapped == NULL) + { + assert (PyErr_Occurred ()); + return NULL; + } + + ctx = pygpgme_unwrap_gpgme_ctx_t(wrapped); + Py_DECREF(wrapped); + if (ctx == NULL) + { + if (cb == Py_None) + goto out; + else + return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL"); + } + if (cb == Py_None) { gpgme_set_progress_cb(ctx, NULL, NULL); - return; + PyObject_SetAttrString(self, "_progress_cb", Py_None); + goto out; } - Py_INCREF(cb); - *freelater = cb; + + if (! PyTuple_Check(cb)) + return PyErr_Format(PyExc_TypeError, "cb must be a tuple"); + if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3) + return PyErr_Format(PyExc_TypeError, + "cb must be a tuple of size 2 or 3"); + gpgme_set_progress_cb(ctx, (gpgme_progress_cb_t) pyProgressCb, (void *) cb); + PyObject_SetAttrString(self, "_progress_cb", cb); + + out: + Py_INCREF(Py_None); + return Py_None; } /* Status callbacks. */ @@ -488,15 +550,46 @@ static gpgme_error_t pyStatusCb(void *hook, const char *keyword, return err; } -void pygpgme_set_status_cb(gpgme_ctx_t ctx, PyObject *cb, - PyObject **freelater) { +PyObject * +pygpgme_set_status_cb(PyObject *self, PyObject *cb) { + PyObject *wrapped; + gpgme_ctx_t ctx; + + wrapped = PyObject_GetAttrString(self, "wrapped"); + if (wrapped == NULL) + { + assert (PyErr_Occurred ()); + return NULL; + } + + ctx = pygpgme_unwrap_gpgme_ctx_t(wrapped); + Py_DECREF(wrapped); + if (ctx == NULL) + { + if (cb == Py_None) + goto out; + else + return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL"); + } + if (cb == Py_None) { gpgme_set_status_cb(ctx, NULL, NULL); - return; + PyObject_SetAttrString(self, "_status_cb", Py_None); + goto out; } - Py_INCREF(cb); - *freelater = cb; + + if (! PyTuple_Check(cb)) + return PyErr_Format(PyExc_TypeError, "cb must be a tuple"); + if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3) + return PyErr_Format(PyExc_TypeError, + "cb must be a tuple of size 2 or 3"); + gpgme_set_status_cb(ctx, (gpgme_status_cb_t) pyStatusCb, (void *) cb); + PyObject_SetAttrString(self, "_status_cb", cb); + + out: + Py_INCREF(Py_None); + return Py_None; } /* Edit callbacks. */ @@ -775,9 +868,10 @@ static void pyDataReleaseCb(void *hook) pygpgme_stash_callback_exception(self); } -gpgme_error_t pygpgme_data_new_from_cbs(gpgme_data_t *r_data, - PyObject *pycbs, - PyObject **freelater) +PyObject * +pygpgme_data_new_from_cbs(PyObject *self, + PyObject *pycbs, + gpgme_data_t *r_data) { static struct gpgme_data_cbs cbs = { pyDataReadCb, @@ -785,12 +879,20 @@ gpgme_error_t pygpgme_data_new_from_cbs(gpgme_data_t *r_data, pyDataSeekCb, pyDataReleaseCb, }; + gpgme_error_t err; + + if (! PyTuple_Check(pycbs)) + return PyErr_Format(PyExc_TypeError, "pycbs must be a tuple"); + if (PyTuple_Size(pycbs) != 5 && PyTuple_Size(pycbs) != 6) + return PyErr_Format(PyExc_TypeError, + "pycbs must be a tuple of size 5 or 6"); - assert (PyTuple_Check(pycbs)); - assert (PyTuple_Size(pycbs) == 5 || PyTuple_Size(pycbs) == 6); + err = gpgme_data_new_from_cbs(r_data, &cbs, (void *) pycbs); + if (err) + return pygpgme_raise_exception(err); - Py_INCREF(pycbs); - *freelater = pycbs; + PyObject_SetAttrString(self, "_data_cbs", pycbs); - return gpgme_data_new_from_cbs(r_data, &cbs, (void *) pycbs); + Py_INCREF(Py_None); + return Py_None; } |