aboutsummaryrefslogtreecommitdiffstats
path: root/lang/python/gpgme.i
diff options
context:
space:
mode:
authorJustus Winter <[email protected]>2016-06-08 15:56:33 +0000
committerJustus Winter <[email protected]>2016-06-16 12:19:17 +0000
commit616929b6edf00b4a774b727385d39b785a112b90 (patch)
treec39e618d99d3257888ac68d2fed08b70fab81435 /lang/python/gpgme.i
parentpython: Add properties to wrapped object. (diff)
downloadgpgme-616929b6edf00b4a774b727385d39b785a112b90.tar.gz
gpgme-616929b6edf00b4a774b727385d39b785a112b90.zip
python: Wrap objects implementing the buffer protocol.
* lang/python/Makefile.am: Add the toplevel source directory to CFLAGS when compiling the bindings so that we can use private header files. * lang/python/gpgme.i (gpgme_data_t): Rework the object wrapping. Do not create a Python wrapper object, merely a gpgme_data_t object, and keep references to buffer objects, if any. If necessary, update the buffer after the function call. (pygpgme_wrap_gpgme_data_t): New function. * lang/python/helpers.c (object_to_gpgme_data_t): Rework object wrapping. Also wrap objects implementing the buffer protocol. * lang/python/helpers.h (object_to_gpgme_data_t): Update prototype. (pygpgme_wrap_gpgme_data_t): New prototype. * lang/python/tests/t-idiomatic.py: Demonstrate this. Signed-off-by: Justus Winter <[email protected]>
Diffstat (limited to 'lang/python/gpgme.i')
-rw-r--r--lang/python/gpgme.i98
1 files changed, 91 insertions, 7 deletions
diff --git a/lang/python/gpgme.i b/lang/python/gpgme.i
index 98f30d55..1e4c9ff6 100644
--- a/lang/python/gpgme.i
+++ b/lang/python/gpgme.i
@@ -114,17 +114,19 @@
}
// Special handling for references to our objects.
-%typemap(in) gpgme_data_t DATAIN (PyObject *wrapper) {
+%typemap(in) gpgme_data_t DATAIN (gpgme_data_t wrapper = NULL,
+ PyObject *bytesio = NULL, Py_buffer view) {
/* If we create a temporary wrapper object, we will store it in
wrapperN, where N is $argnum. Here in this fragment, SWIG will
automatically append $argnum. */
- wrapper = NULL;
+ memset(&view, 0, sizeof view);
if ($input == Py_None)
$1 = NULL;
else {
- PyObject *pypointer = NULL;
-
- if((pypointer=object_to_gpgme_data_t($input, $argnum, &wrapper)) == NULL)
+ PyObject *pypointer;
+ pypointer = object_to_gpgme_data_t($input, $argnum, &wrapper,
+ &bytesio, &view);
+ if (pypointer == NULL)
return NULL;
/* input = $input, 1 = $1, 1_descriptor = $1_descriptor */
@@ -141,8 +143,79 @@
}
%typemap(freearg) gpgme_data_t DATAIN {
+ /* See whether we need to update the Python buffer. */
+ if (resultobj && wrapper$argnum && view$argnum.buf
+ && wrapper$argnum->data.mem.buffer != NULL)
+ {
+ /* The buffer is dirty. */
+ if (view$argnum.readonly)
+ {
+ Py_XDECREF(resultobj);
+ resultobj = NULL;
+ PyErr_SetString(PyExc_ValueError, "cannot update read-only buffer");
+ }
+
+ /* See if we need to truncate the buffer. */
+ if (resultobj && view$argnum.len != wrapper$argnum->data.mem.length)
+ {
+ if (bytesio$argnum == NULL)
+ {
+ Py_XDECREF(resultobj);
+ resultobj = NULL;
+ PyErr_SetString(PyExc_ValueError, "cannot resize buffer");
+ }
+ else
+ {
+ PyObject *retval;
+ PyBuffer_Release(&view$argnum);
+ retval = PyObject_CallMethod(bytesio$argnum, "truncate", "l",
+ (long)
+ wrapper$argnum->data.mem.length);
+ if (retval == NULL)
+ {
+ Py_XDECREF(resultobj);
+ resultobj = NULL;
+ }
+ else
+ {
+ Py_DECREF(retval);
+
+ retval = PyObject_CallMethod(bytesio$argnum, "getbuffer", NULL);
+ if (retval == NULL
+ || PyObject_GetBuffer(retval, &view$argnum,
+ PyBUF_SIMPLE|PyBUF_WRITABLE) < 0)
+ {
+ Py_XDECREF(resultobj);
+ resultobj = NULL;
+ }
+
+ Py_XDECREF(retval);
+
+ if (resultobj && view$argnum.len
+ != wrapper$argnum->data.mem.length)
+ {
+ Py_XDECREF(resultobj);
+ resultobj = NULL;
+ PyErr_Format(PyExc_ValueError,
+ "Expected buffer of length %zu, got %zi",
+ wrapper$argnum->data.mem.length,
+ view$argnum.len);
+ }
+ }
+ }
+ }
+
+ if (resultobj)
+ memcpy(view$argnum.buf, wrapper$argnum->data.mem.buffer,
+ wrapper$argnum->data.mem.length);
+ }
+
/* Free the temporary wrapper, if any. */
- Py_XDECREF(wrapper$argnum);
+ if (wrapper$argnum)
+ gpgme_data_release(wrapper$argnum);
+ Py_XDECREF (bytesio$argnum);
+ if (wrapper$argnum && view$argnum.buf)
+ PyBuffer_Release(&view$argnum);
}
%apply gpgme_data_t DATAIN {gpgme_data_t plain, gpgme_data_t cipher,
@@ -240,7 +313,10 @@
version for SWIG. We do, however, want to hide certain fields on
some structs, which we provide prior to including the version for
SWIG. */
- %{ #include <gpgme.h> %}
+%{
+#include <gpgme.h>
+#include "src/data.h" /* For struct gpgme_data. */
+%}
/* This is for notations, where we want to hide the length fields, and
the unused bit field block. */
@@ -291,5 +367,13 @@ FILE *fdopen(int fildes, const char *mode);
%{
#include "helpers.h"
+
+/* SWIG support for helpers.c */
+PyObject *
+pygpgme_wrap_gpgme_data_t(gpgme_data_t data)
+{
+ return SWIG_NewPointerObj(data, SWIGTYPE_p_gpgme_data, 0);
+}
%}
+
%include "helpers.h"