python: Improve progress callbacks.
authorJustus Winter <justus@gnupg.org>
Thu, 19 May 2016 13:53:19 +0000 (15:53 +0200)
committerJustus Winter <justus@gnupg.org>
Thu, 19 May 2016 14:08:33 +0000 (16:08 +0200)
* 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>
lang/python/helpers.c
lang/python/pyme/core.py
lang/python/tests/t-callbacks.py

index c3cf3b3..7ced04a 100644 (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);
 }
index 8a4c197..9e7faf7 100644 (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):
index e89fcb8..bd88d86 100755 (executable)
@@ -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"