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) ...@@ -94,12 +94,58 @@ api_sieve_machine_init (PyObject *self, PyObject *args)
94 { 94 {
95 int status; 95 int status;
96 PySieveMachine *py_mach; 96 PySieveMachine *py_mach;
97 mu_stream_t str, estr;
97 98
98 if (!PyArg_ParseTuple (args, "O!", &PySieveMachineType, &py_mach)) 99 if (!PyArg_ParseTuple (args, "O!", &PySieveMachineType, &py_mach))
99 return NULL; 100 return NULL;
100 101
101 status = mu_sieve_machine_init (&py_mach->mach); 102 status = mu_memory_stream_create (&str, MU_STREAM_RDWR);
103 if (status)
102 return _ro (PyInt_FromLong (status)); 104 return _ro (PyInt_FromLong (status));
105 status = mu_log_stream_create (&estr, str);
106 mu_stream_unref (str);
107 if (status)
108 return _ro (PyInt_FromLong (status));
109
110 status = mu_sieve_machine_init_ex (&py_mach->mach, NULL, estr);
111 mu_stream_unref (estr);
112 return _ro (PyInt_FromLong (status));
113 }
114
115 static PyObject *
116 api_sieve_machine_error_text (PyObject *self, PyObject *args)
117 {
118 int status;
119 PySieveMachine *py_mach;
120 mu_stream_t estr;
121 mu_transport_t trans[2];
122 PyObject *retval;
123 size_t length = 0;
124
125 if (!PyArg_ParseTuple (args, "O!", &PySieveMachineType, &py_mach))
126 return NULL;
127 if (!py_mach->mach)
128 PyErr_SetString (PyExc_RuntimeError, "Uninitialized Sieve machine");
129
130 mu_sieve_get_diag_stream (py_mach->mach, &estr);
131 status = mu_stream_ioctl (estr, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET,
132 trans);
133 if (status == 0)
134 {
135 mu_stream_t str = (mu_stream_t) trans[0];
136
137 mu_stream_size (str, &length);
138 status = mu_stream_ioctl (str, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET,
139 trans);
140 mu_stream_truncate (str, 0);
141 }
142
143 if (status)
144 PyErr_SetString (PyExc_RuntimeError, mu_strerror (status));
145 retval = PyString_FromStringAndSize ((char*) trans[0], length);
146
147 mu_stream_unref (estr);
148 return _ro (retval);
103 } 149 }
104 150
105 static PyObject * 151 static PyObject *
...@@ -110,7 +156,8 @@ api_sieve_machine_destroy (PyObject *self, PyObject *args) ...@@ -110,7 +156,8 @@ api_sieve_machine_destroy (PyObject *self, PyObject *args)
110 if (!PyArg_ParseTuple (args, "O!", &PySieveMachineType, &py_mach)) 156 if (!PyArg_ParseTuple (args, "O!", &PySieveMachineType, &py_mach))
111 return NULL; 157 return NULL;
112 158
113 if (py_mach->mach) { 159 if (py_mach->mach)
160 {
114 struct _mu_py_sieve_logger *s = mu_sieve_get_data (py_mach->mach); 161 struct _mu_py_sieve_logger *s = mu_sieve_get_data (py_mach->mach);
115 if (s) 162 if (s)
116 free (s); 163 free (s);
...@@ -280,6 +327,9 @@ static PyMethodDef methods[] = { ...@@ -280,6 +327,9 @@ static PyMethodDef methods[] = {
280 { "machine_destroy", (PyCFunction) api_sieve_machine_destroy, METH_VARARGS, 327 { "machine_destroy", (PyCFunction) api_sieve_machine_destroy, METH_VARARGS,
281 "Destroy Sieve 'machine'." }, 328 "Destroy Sieve 'machine'." },
282 329
330 { "errortext", (PyCFunction) api_sieve_machine_error_text, METH_VARARGS,
331 "Return the most recent error description." },
332
283 { "compile", (PyCFunction) api_sieve_compile, METH_VARARGS, 333 { "compile", (PyCFunction) api_sieve_compile, METH_VARARGS,
284 "Compile the sieve script from the file 'name'." }, 334 "Compile the sieve script from the file 'name'." },
285 335
......
...@@ -126,6 +126,25 @@ api_stdio_stream_create (PyObject *self, PyObject *args) ...@@ -126,6 +126,25 @@ api_stdio_stream_create (PyObject *self, PyObject *args)
126 } 126 }
127 127
128 static PyObject * 128 static PyObject *
129 api_memory_stream_create (PyObject *self, PyObject *args)
130 {
131 int status;
132 char *s;
133 PyStream *py_stm;
134
135 if (!PyArg_ParseTuple (args, "O!s", &PyStreamType, &py_stm, &s))
136 return NULL;
137
138 status = mu_memory_stream_create (&py_stm->stm, MU_STREAM_RDWR);
139 if (status == 0)
140 {
141 status = mu_stream_write (py_stm->stm, s, strlen (s), NULL);
142 mu_stream_seek (py_stm->stm, MU_SEEK_SET, 0, NULL);
143 }
144 return _ro (PyInt_FromLong (status));
145 }
146
147 static PyObject *
129 api_prog_stream_create (PyObject *self, PyObject *args) 148 api_prog_stream_create (PyObject *self, PyObject *args)
130 { 149 {
131 int status, flags; 150 int status, flags;
...@@ -317,6 +336,22 @@ api_stream_readline (PyObject *self, PyObject *args) ...@@ -317,6 +336,22 @@ api_stream_readline (PyObject *self, PyObject *args)
317 return _ro (py_ret); 336 return _ro (py_ret);
318 } 337 }
319 338
339 static PyObject *
340 api_stream_to_message (PyObject *self, PyObject *args)
341 {
342 int status;
343 PyStream *py_stm;
344 PyMessage *py_msg = PyMessage_NEW ();
345
346 if (!PyArg_ParseTuple (args, "O!", &PyStreamType, &py_stm))
347 return NULL;
348
349 Py_INCREF (py_msg);
350
351 status = mu_stream_to_message (py_stm->stm, &py_msg->msg);
352 return status_object (status, (PyObject *)py_msg);
353 }
354
320 static PyMethodDef methods[] = { 355 static PyMethodDef methods[] = {
321 { "tcp_stream_create", (PyCFunction) api_tcp_stream_create, METH_VARARGS, 356 { "tcp_stream_create", (PyCFunction) api_tcp_stream_create, METH_VARARGS,
322 "" }, 357 "" },
...@@ -327,6 +362,10 @@ static PyMethodDef methods[] = { ...@@ -327,6 +362,10 @@ static PyMethodDef methods[] = {
327 { "stdio_stream_create", (PyCFunction) api_stdio_stream_create, METH_VARARGS, 362 { "stdio_stream_create", (PyCFunction) api_stdio_stream_create, METH_VARARGS,
328 "" }, 363 "" },
329 364
365 { "memory_stream_create",
366 (PyCFunction) api_memory_stream_create, METH_VARARGS,
367 "" },
368
330 { "prog_stream_create", (PyCFunction) api_prog_stream_create, METH_VARARGS, 369 { "prog_stream_create", (PyCFunction) api_prog_stream_create, METH_VARARGS,
331 "" }, 370 "" },
332 371
...@@ -364,6 +403,9 @@ static PyMethodDef methods[] = { ...@@ -364,6 +403,9 @@ static PyMethodDef methods[] = {
364 { "readline", (PyCFunction) api_stream_readline, METH_VARARGS, 403 { "readline", (PyCFunction) api_stream_readline, METH_VARARGS,
365 "" }, 404 "" },
366 405
406 { "to_message", (PyCFunction) api_stream_to_message, METH_VARARGS,
407 "" },
408
367 { NULL, NULL, 0, NULL } 409 { NULL, NULL, 0, NULL }
368 }; 410 };
369 411
......
...@@ -22,9 +22,9 @@ def strerror (status): ...@@ -22,9 +22,9 @@ def strerror (status):
22 return error.strerror (status) 22 return error.strerror (status)
23 23
24 class Error (Exception): 24 class Error (Exception):
25 def __init__ (self, status): 25 def __init__ (self, status, str_error=None):
26 self.status = status 26 self.status = status
27 self.strerror = strerror (status) 27 self.strerror = str_error or strerror (status)
28 def __str__ (self): 28 def __str__ (self):
29 return "%d: %s" % (self.status, self.strerror) 29 return "%d: %s" % (self.status, self.strerror)
30 30
......
...@@ -26,6 +26,9 @@ class Machine: ...@@ -26,6 +26,9 @@ class Machine:
26 raise SieveMachineError (status) 26 raise SieveMachineError (status)
27 27
28 def __del__ (self): 28 def __del__ (self):
29 s = sieve.errortext (self.mach)
30 if s:
31 raise SieveMachineError (MU_ERR_FAILURE, s)
29 sieve.machine_destroy (self.mach) 32 sieve.machine_destroy (self.mach)
30 del self.mach 33 del self.mach
31 34
...@@ -38,7 +41,7 @@ class Machine: ...@@ -38,7 +41,7 @@ class Machine:
38 """Compile the sieve script from the file 'name'.""" 41 """Compile the sieve script from the file 'name'."""
39 status = sieve.compile (self.mach, name) 42 status = sieve.compile (self.mach, name)
40 if status: 43 if status:
41 raise SieveMachineError (status) 44 raise SieveMachineError (status, sieve.errortext (self.mach))
42 45
43 def disass (self): 46 def disass (self):
44 """Dump the disassembled code of the sieve machine.""" 47 """Dump the disassembled code of the sieve machine."""
...@@ -58,4 +61,4 @@ class Machine: ...@@ -58,4 +61,4 @@ class Machine:
58 over the 'msg'.""" 61 over the 'msg'."""
59 status = sieve.message (self.mach, msg.msg) 62 status = sieve.message (self.mach, msg.msg)
60 if status: 63 if status:
61 raise SieveMachineError (status) 64 raise SieveMachineError (status, sieve.errortext (self.mach))
......
...@@ -103,6 +103,13 @@ class Stream: ...@@ -103,6 +103,13 @@ class Stream:
103 raise StreamError (status) 103 raise StreamError (status)
104 return rbuf 104 return rbuf
105 105
106 def to_message (self):
107 from mailutils import message
108 status, msg = stream.to_message (self.stm)
109 if status:
110 raise StreamError (status)
111 return message.Message (msg)
112
106 class TcpStream (Stream): 113 class TcpStream (Stream):
107 def __init__ (self, host, port, flags=MU_STREAM_READ): 114 def __init__ (self, host, port, flags=MU_STREAM_READ):
108 Stream.__init__ (self) 115 Stream.__init__ (self)
...@@ -124,6 +131,13 @@ class StdioStream (Stream): ...@@ -124,6 +131,13 @@ class StdioStream (Stream):
124 if status: 131 if status:
125 raise StreamError (status) 132 raise StreamError (status)
126 133
134 class MemoryStream (Stream):
135 def __init__ (self, s):
136 Stream.__init__ (self)
137 status = stream.memory_stream_create (self.stm, s)
138 if status:
139 raise StreamError (status)
140
127 class ProgStream (Stream): 141 class ProgStream (Stream):
128 def __init__ (self, progname, flags=MU_STREAM_READ): 142 def __init__ (self, progname, flags=MU_STREAM_READ):
129 Stream.__init__ (self) 143 Stream.__init__ (self)
......