aboutsummaryrefslogtreecommitdiffstats
path: root/lang/python/helpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'lang/python/helpers.c')
-rw-r--r--lang/python/helpers.c100
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);
}