Commit aed829a6 aed829a6c5a640f3e92015004b933db898e00d87 by Wojciech Polak

Improve Python API. Add MemoryStream class.

* python/libmu_py/sieve.c (api_sieve_machine_init): Improve.
(api_sieve_machine_error_text): Add new function.
* python/libmu_py/stream.c (api_memory_stream_create): Likewise.
(api_stream_to_message): Likewise.
* python/mailutils/error.py (Error): Add optional str_error argument.
* python/mailutils/sieve.py: Update.
* python/mailutils/stream.py (to_message): Add new method.
(MemoryStream): Add new class.
1 parent c8a26bc9
......@@ -94,12 +94,58 @@ api_sieve_machine_init (PyObject *self, PyObject *args)
{
int status;
PySieveMachine *py_mach;
mu_stream_t str, estr;
if (!PyArg_ParseTuple (args, "O!", &PySieveMachineType, &py_mach))
return NULL;
status = mu_sieve_machine_init (&py_mach->mach);
status = mu_memory_stream_create (&str, MU_STREAM_RDWR);
if (status)
return _ro (PyInt_FromLong (status));
status = mu_log_stream_create (&estr, str);
mu_stream_unref (str);
if (status)
return _ro (PyInt_FromLong (status));
status = mu_sieve_machine_init_ex (&py_mach->mach, NULL, estr);
mu_stream_unref (estr);
return _ro (PyInt_FromLong (status));
}
static PyObject *
api_sieve_machine_error_text (PyObject *self, PyObject *args)
{
int status;
PySieveMachine *py_mach;
mu_stream_t estr;
mu_transport_t trans[2];
PyObject *retval;
size_t length = 0;
if (!PyArg_ParseTuple (args, "O!", &PySieveMachineType, &py_mach))
return NULL;
if (!py_mach->mach)
PyErr_SetString (PyExc_RuntimeError, "Uninitialized Sieve machine");
mu_sieve_get_diag_stream (py_mach->mach, &estr);
status = mu_stream_ioctl (estr, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET,
trans);
if (status == 0)
{
mu_stream_t str = (mu_stream_t) trans[0];
mu_stream_size (str, &length);
status = mu_stream_ioctl (str, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET,
trans);
mu_stream_truncate (str, 0);
}
if (status)
PyErr_SetString (PyExc_RuntimeError, mu_strerror (status));
retval = PyString_FromStringAndSize ((char*) trans[0], length);
mu_stream_unref (estr);
return _ro (retval);
}
static PyObject *
......@@ -110,7 +156,8 @@ api_sieve_machine_destroy (PyObject *self, PyObject *args)
if (!PyArg_ParseTuple (args, "O!", &PySieveMachineType, &py_mach))
return NULL;
if (py_mach->mach) {
if (py_mach->mach)
{
struct _mu_py_sieve_logger *s = mu_sieve_get_data (py_mach->mach);
if (s)
free (s);
......@@ -280,6 +327,9 @@ static PyMethodDef methods[] = {
{ "machine_destroy", (PyCFunction) api_sieve_machine_destroy, METH_VARARGS,
"Destroy Sieve 'machine'." },
{ "errortext", (PyCFunction) api_sieve_machine_error_text, METH_VARARGS,
"Return the most recent error description." },
{ "compile", (PyCFunction) api_sieve_compile, METH_VARARGS,
"Compile the sieve script from the file 'name'." },
......
......@@ -126,6 +126,25 @@ api_stdio_stream_create (PyObject *self, PyObject *args)
}
static PyObject *
api_memory_stream_create (PyObject *self, PyObject *args)
{
int status;
char *s;
PyStream *py_stm;
if (!PyArg_ParseTuple (args, "O!s", &PyStreamType, &py_stm, &s))
return NULL;
status = mu_memory_stream_create (&py_stm->stm, MU_STREAM_RDWR);
if (status == 0)
{
status = mu_stream_write (py_stm->stm, s, strlen (s), NULL);
mu_stream_seek (py_stm->stm, MU_SEEK_SET, 0, NULL);
}
return _ro (PyInt_FromLong (status));
}
static PyObject *
api_prog_stream_create (PyObject *self, PyObject *args)
{
int status, flags;
......@@ -317,6 +336,22 @@ api_stream_readline (PyObject *self, PyObject *args)
return _ro (py_ret);
}
static PyObject *
api_stream_to_message (PyObject *self, PyObject *args)
{
int status;
PyStream *py_stm;
PyMessage *py_msg = PyMessage_NEW ();
if (!PyArg_ParseTuple (args, "O!", &PyStreamType, &py_stm))
return NULL;
Py_INCREF (py_msg);
status = mu_stream_to_message (py_stm->stm, &py_msg->msg);
return status_object (status, (PyObject *)py_msg);
}
static PyMethodDef methods[] = {
{ "tcp_stream_create", (PyCFunction) api_tcp_stream_create, METH_VARARGS,
"" },
......@@ -327,6 +362,10 @@ static PyMethodDef methods[] = {
{ "stdio_stream_create", (PyCFunction) api_stdio_stream_create, METH_VARARGS,
"" },
{ "memory_stream_create",
(PyCFunction) api_memory_stream_create, METH_VARARGS,
"" },
{ "prog_stream_create", (PyCFunction) api_prog_stream_create, METH_VARARGS,
"" },
......@@ -364,6 +403,9 @@ static PyMethodDef methods[] = {
{ "readline", (PyCFunction) api_stream_readline, METH_VARARGS,
"" },
{ "to_message", (PyCFunction) api_stream_to_message, METH_VARARGS,
"" },
{ NULL, NULL, 0, NULL }
};
......
......@@ -22,9 +22,9 @@ def strerror (status):
return error.strerror (status)
class Error (Exception):
def __init__ (self, status):
def __init__ (self, status, str_error=None):
self.status = status
self.strerror = strerror (status)
self.strerror = str_error or strerror (status)
def __str__ (self):
return "%d: %s" % (self.status, self.strerror)
......
......@@ -26,6 +26,9 @@ class Machine:
raise SieveMachineError (status)
def __del__ (self):
s = sieve.errortext (self.mach)
if s:
raise SieveMachineError (MU_ERR_FAILURE, s)
sieve.machine_destroy (self.mach)
del self.mach
......@@ -38,7 +41,7 @@ class Machine:
"""Compile the sieve script from the file 'name'."""
status = sieve.compile (self.mach, name)
if status:
raise SieveMachineError (status)
raise SieveMachineError (status, sieve.errortext (self.mach))
def disass (self):
"""Dump the disassembled code of the sieve machine."""
......@@ -58,4 +61,4 @@ class Machine:
over the 'msg'."""
status = sieve.message (self.mach, msg.msg)
if status:
raise SieveMachineError (status)
raise SieveMachineError (status, sieve.errortext (self.mach))
......
......@@ -103,6 +103,13 @@ class Stream:
raise StreamError (status)
return rbuf
def to_message (self):
from mailutils import message
status, msg = stream.to_message (self.stm)
if status:
raise StreamError (status)
return message.Message (msg)
class TcpStream (Stream):
def __init__ (self, host, port, flags=MU_STREAM_READ):
Stream.__init__ (self)
......@@ -124,6 +131,13 @@ class StdioStream (Stream):
if status:
raise StreamError (status)
class MemoryStream (Stream):
def __init__ (self, s):
Stream.__init__ (self)
status = stream.memory_stream_create (self.stm, s)
if status:
raise StreamError (status)
class ProgStream (Stream):
def __init__ (self, progname, flags=MU_STREAM_READ):
Stream.__init__ (self)
......