diff options
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); } |