diff options
author | Justus Winter <[email protected]> | 2016-06-08 15:56:33 +0000 |
---|---|---|
committer | Justus Winter <[email protected]> | 2016-06-16 12:19:17 +0000 |
commit | 616929b6edf00b4a774b727385d39b785a112b90 (patch) | |
tree | c39e618d99d3257888ac68d2fed08b70fab81435 /lang/python/helpers.c | |
parent | python: Add properties to wrapped object. (diff) | |
download | gpgme-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/helpers.c')
-rw-r--r-- | lang/python/helpers.c | 100 |
1 files changed, 54 insertions, 46 deletions
diff --git a/lang/python/helpers.c b/lang/python/helpers.c index 810423d0..ad33d07b 100644 --- a/lang/python/helpers.c +++ b/lang/python/helpers.c @@ -206,64 +206,72 @@ object_to_gpgme_t(PyObject *input, const char *objtype, int argnum) objects with a fileno method, returning it in WRAPPER. This object must be de-referenced when no longer needed. */ PyObject * -object_to_gpgme_data_t(PyObject *input, int argnum, PyObject **wrapper) +object_to_gpgme_data_t(PyObject *input, int argnum, gpgme_data_t *wrapper, + PyObject **bytesio, Py_buffer *view) { - static PyObject *Data = NULL; - PyObject *data = input; + gpgme_error_t err; + PyObject *data; PyObject *fd; - PyObject *result; - *wrapper = NULL; - - if (Data == NULL) { - PyObject *core; - PyObject *from_list = PyList_New(0); - core = PyImport_ImportModuleLevel("core", PyEval_GetGlobals(), - PyEval_GetLocals(), from_list, 1); - Py_XDECREF(from_list); - if (core) { - Data = PyDict_GetItemString(PyModule_GetDict(core), "Data"); - Py_XINCREF(Data); - } - else - return NULL; - } + /* See if it is a file-like object with file number. */ fd = PyObject_CallMethod(input, "fileno", NULL); if (fd) { - /* File-like object with file number. */ - PyObject *args = NULL; - PyObject *kw = NULL; - - /* We don't need the fd, as we have no constructor accepting file - descriptors directly. */ + err = gpgme_data_new_from_fd(wrapper, (int) PyLong_AsLong(fd)); Py_DECREF(fd); + if (err) + return pygpgme_raise_exception (err); + + return pygpgme_wrap_gpgme_data_t(*wrapper); + } + else + PyErr_Clear(); - args = PyTuple_New(0); - kw = PyDict_New(); - if (args == NULL || kw == NULL) - { - fail: - Py_XDECREF(args); - Py_XDECREF(kw); + /* No? Maybe it implements the buffer protocol. */ + data = PyObject_CallMethod(input, "getbuffer", NULL); + if (data) + { + /* Save a reference to input, which seems to be a BytesIO + object. */ + Py_INCREF(input); + *bytesio = input; + } + else + { + PyErr_Clear(); + + /* No, but maybe the user supplied a buffer object? */ + data = input; + } + + /* Do we have a buffer object? */ + if (PyObject_CheckBuffer(data)) + { + if (PyObject_GetBuffer(data, view, PyBUF_SIMPLE) < 0) return NULL; - } - if (PyDict_SetItemString(kw, "file", input) < 0) - goto fail; + if (data != input) + Py_DECREF(data); - *wrapper = PyObject_Call(Data, args, kw); - if (*wrapper == NULL) - goto fail; + assert (view->ndim == 1); + assert (view->shape == NULL); + assert (view->strides == NULL); + assert (view->suboffsets == NULL); - Py_DECREF(args); - Py_DECREF(kw); - data = *wrapper; - } - else - PyErr_Clear(); + err = gpgme_data_new_from_mem(wrapper, view->buf, (size_t) view->len, 0); + if (err) + return pygpgme_raise_exception (err); - result = object_to_gpgme_t(data, "gpgme_data_t", argnum); - return result; + return pygpgme_wrap_gpgme_data_t(*wrapper); + } + + /* As last resort we assume it is a wrapped data object. */ + if (PyObject_HasAttrString(data, "_getctype")) + return object_to_gpgme_t(data, "gpgme_data_t", argnum); + + return PyErr_Format(PyExc_TypeError, + "arg %d: expected pyme.Data, file, or an object " + "implementing the buffer protocol, got %s", + argnum, data->ob_type->tp_name); } |