python: Support the Assuan engine.
[gpgme.git] / lang / python / helpers.c
index 5380ff2..90173e4 100644 (file)
@@ -24,7 +24,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include "Python.h"
+
 #include "helpers.h"
+#include "private.h"
 
 static PyObject *GPGMEError = NULL;
 
@@ -150,12 +152,18 @@ PyObject *pygpgme_raise_callback_exception(PyObject *self)
   else
     Py_INCREF(ptraceback);
 
+  /* We now have references for the extracted items.  */
   Py_DECREF(excinfo);
-  PyErr_Restore(ptype, pvalue, ptraceback);
 
+  /* Clear the exception information.  It is important to do this
+     before setting the error, because setting the attribute may
+     execute python code, and the runtime system raises a SystemError
+     if an exception is set but values are returned.  */
   Py_INCREF(Py_None);
   PyObject_SetAttrString(self, EXCINFO, Py_None);
 
+  /* Restore exception.  */
+  PyErr_Restore(ptype, pvalue, ptraceback);
   return NULL; /* Raise exception.  */
 
  leave:
@@ -171,7 +179,7 @@ PyObject *
 object_to_gpgme_t(PyObject *input, const char *objtype, int argnum)
 {
   PyObject *pyname = NULL, *pypointer = NULL;
-  pyname = PyObject_CallMethod(input, "_getctype", NULL);
+  pyname = PyObject_GetAttrString(input, "_ctype");
   if (pyname && PyUnicode_Check(pyname))
     {
       if (strcmp(PyUnicode_AsUTF8(pyname), objtype) != 0)
@@ -248,6 +256,7 @@ object_to_gpgme_data_t(PyObject *input, int argnum, gpgme_data_t *wrapper,
       if (data != input)
         Py_DECREF(data);
 
+      assert (view->obj);
       assert (view->ndim == 1);
       assert (view->shape == NULL);
       assert (view->strides == NULL);
@@ -261,7 +270,7 @@ object_to_gpgme_data_t(PyObject *input, int argnum, gpgme_data_t *wrapper,
     }
 
   /* As last resort we assume it is a wrapped data object.  */
-  if (PyObject_HasAttrString(data, "_getctype"))
+  if (PyObject_HasAttrString(data, "_ctype"))
     return object_to_gpgme_t(data, "gpgme_data_t", argnum);
 
   return PyErr_Format(PyExc_TypeError,
@@ -272,6 +281,38 @@ object_to_gpgme_data_t(PyObject *input, int argnum, gpgme_data_t *wrapper,
 
 \f
 
+PyObject *
+pygpgme_wrap_fragile_result(PyObject *fragile, const char *classname)
+{
+  static PyObject *results;
+  PyObject *class;
+  PyObject *replacement;
+
+  if (results == NULL)
+    {
+      PyObject *from_list = PyList_New(0);
+      if (from_list == NULL)
+        return NULL;
+
+      results = PyImport_ImportModuleLevel("results", PyEval_GetGlobals(),
+                                           PyEval_GetLocals(), from_list, 1);
+      Py_DECREF(from_list);
+
+      if (results == NULL)
+        return NULL;
+    }
+
+  class = PyMapping_GetItemString(PyModule_GetDict(results), classname);
+  if (class == NULL)
+    return NULL;
+
+  replacement = PyObject_CallFunctionObjArgs(class, fragile, NULL);
+  Py_DECREF(class);
+  return replacement;
+}
+
+\f
+
 /* Callback support.  */
 static gpgme_error_t pyPassphraseCb(void *hook,
                                    const char *uid_hint,
@@ -896,3 +937,119 @@ pygpgme_data_new_from_cbs(PyObject *self,
   Py_INCREF(Py_None);
   return Py_None;
 }
+
+\f
+
+/* The assuan callbacks.  */
+
+gpgme_error_t
+_pyme_assuan_data_cb (void *hook, const void *data, size_t datalen)
+{
+  gpgme_error_t err = 0;
+  PyObject *pyhook = (PyObject *) hook;
+  PyObject *self = NULL;
+  PyObject *func = NULL;
+  PyObject *py_data = NULL;
+  PyObject *retval = NULL;
+
+  assert (PyTuple_Check(pyhook));
+  assert (PyTuple_Size(pyhook) == 2);
+  self = PyTuple_GetItem(pyhook, 0);
+  func = PyTuple_GetItem(pyhook, 1);
+  assert (PyCallable_Check(func));
+
+  py_data = PyBytes_FromStringAndSize(data, datalen);
+  if (py_data == NULL)
+    return NULL;       /* raise */
+
+  retval = PyObject_CallFunctionObjArgs(func, py_data, NULL);
+  if (PyErr_Occurred())
+    err = pygpgme_exception2code();
+  Py_DECREF(py_data);
+  Py_XDECREF(retval);
+
+ leave:
+  if (err)
+    pygpgme_stash_callback_exception(self);
+  return err;
+}
+
+gpgme_error_t
+_pyme_assuan_inquire_cb (void *hook, const char *name, const char *args,
+                         gpgme_data_t *r_data)
+{
+  gpgme_error_t err = 0;
+  PyObject *pyhook = (PyObject *) hook;
+  PyObject *self = NULL;
+  PyObject *func = NULL;
+  PyObject *py_name = NULL;
+  PyObject *py_args = NULL;
+  PyObject *retval = NULL;
+
+  assert (PyTuple_Check(pyhook));
+  assert (PyTuple_Size(pyhook) == 2);
+  self = PyTuple_GetItem(pyhook, 0);
+  func = PyTuple_GetItem(pyhook, 1);
+  assert (PyCallable_Check(func));
+
+  py_name = PyUnicode_FromString(name);
+  if (py_name == NULL)
+    return NULL;       /* raise */
+
+  py_args = PyUnicode_FromString(args);
+  if (py_args == NULL)
+    return NULL;       /* raise */
+
+  retval = PyObject_CallFunctionObjArgs(func, py_name, py_args, NULL);
+  if (PyErr_Occurred())
+    err = pygpgme_exception2code();
+  Py_DECREF(py_name);
+  Py_DECREF(py_args);
+  Py_XDECREF(retval);
+
+  /* FIXME: Returning data is not yet implemented.  */
+  r_data = NULL;
+
+ leave:
+  if (err)
+    pygpgme_stash_callback_exception(self);
+  return err;
+}
+
+gpgme_error_t
+_pyme_assuan_status_cb (void *hook, const char *status, const char *args)
+{
+  gpgme_error_t err = 0;
+  PyObject *pyhook = (PyObject *) hook;
+  PyObject *self = NULL;
+  PyObject *func = NULL;
+  PyObject *py_status = NULL;
+  PyObject *py_args = NULL;
+  PyObject *retval = NULL;
+
+  assert (PyTuple_Check(pyhook));
+  assert (PyTuple_Size(pyhook) == 2);
+  self = PyTuple_GetItem(pyhook, 0);
+  func = PyTuple_GetItem(pyhook, 1);
+  assert (PyCallable_Check(func));
+
+  py_status = PyUnicode_FromString(status);
+  if (py_status == NULL)
+    return NULL;       /* raise */
+
+  py_args = PyUnicode_FromString(args);
+  if (py_args == NULL)
+    return NULL;       /* raise */
+
+  retval = PyObject_CallFunctionObjArgs(func, py_status, py_args, NULL);
+  if (PyErr_Occurred())
+    err = pygpgme_exception2code();
+  Py_DECREF(py_status);
+  Py_DECREF(py_args);
+  Py_XDECREF(retval);
+
+ leave:
+  if (err)
+    pygpgme_stash_callback_exception(self);
+  return err;
+}