python: Improve progress callbacks.

* lang/python/helpers.c (pyProgressCb): Stash python errors, convert
'what' to Unicode object.
* lang/python/pyme/core.py (Context.set_progress_cb): Hand in 'self'.
* lang/python/tests/t-callbacks.py: Test progress callbacks.

Signed-off-by: Justus Winter <justus@gnupg.org>
This commit is contained in:
Justus Winter 2016-05-19 15:53:19 +02:00
parent d90857a08c
commit 0d4e95621e
3 changed files with 54 additions and 6 deletions

View File

@ -229,17 +229,25 @@ static void pyProgressCb(void *hook, const char *what, int type, int current,
int total) {
PyObject *func = NULL, *dataarg = NULL, *args = NULL, *retval = NULL;
PyObject *pyhook = (PyObject *) hook;
PyObject *self = NULL;
if (PyTuple_Check(pyhook)) {
func = PyTuple_GetItem(pyhook, 0);
assert (PyTuple_Check(pyhook));
self = PyTuple_GetItem(pyhook, 0);
func = PyTuple_GetItem(pyhook, 1);
if (PyTuple_Size(pyhook) == 3) {
dataarg = PyTuple_GetItem(pyhook, 1);
args = PyTuple_New(5);
} else {
func = pyhook;
args = PyTuple_New(4);
}
PyTuple_SetItem(args, 0, PyBytes_FromString(what));
PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(what, strlen (what),
"strict"));
if (PyErr_Occurred()) {
pygpgme_stash_callback_exception(self);
Py_DECREF(args);
return;
}
PyTuple_SetItem(args, 1, PyLong_FromLong((long) type));
PyTuple_SetItem(args, 2, PyLong_FromLong((long) current));
PyTuple_SetItem(args, 3, PyLong_FromLong((long) total));
@ -249,6 +257,8 @@ static void pyProgressCb(void *hook, const char *what, int type, int current,
}
retval = PyObject_CallObject(func, args);
if (PyErr_Occurred())
pygpgme_stash_callback_exception(self);
Py_DECREF(args);
Py_XDECREF(retval);
}

View File

@ -185,9 +185,9 @@ class Context(GpgmeWrapper):
else:
self.last_progresscb = pygpgme.new_PyObject_p_p()
if hook == None:
hookdata = func
hookdata = (self, func)
else:
hookdata = (func, hook)
hookdata = (self, func, hook)
pygpgme.pygpgme_set_progress_cb(self.wrapped, hookdata, self.last_progresscb)
def get_engine_info(self):

View File

@ -75,3 +75,41 @@ except Exception as e:
assert type(e) == TypeError
else:
assert False, "Expected an error, got none"
# Test the progress callback.
parms = """<GnupgKeyParms format="internal">
Key-Type: RSA
Key-Length: 1024
Name-Real: Joe Tester
Name-Comment: with stupid passphrase
Name-Email: joe+pyme@example.org
Passphrase: Crypt0R0cks
Expire-Date: 2020-12-31
</GnupgKeyParms>
"""
messages = []
def progress_cb(what, typ, current, total, hook=None):
messages.append(
"PROGRESS UPDATE: what = {}, type = {}, current = {}, total = {}"
.format(what, typ, current, total))
c = core.Context()
c.set_progress_cb(progress_cb, None)
c.op_genkey(parms, None, None)
assert len(messages) > 0
# Test exception handling.
def progress_cb(what, typ, current, total, hook=None):
raise myException
c = core.Context()
c.set_progress_cb(progress_cb, None)
try:
c.op_genkey(parms, None, None)
except Exception as e:
assert e == myException
else:
assert False, "Expected an error, got none"