Support creating client objects in python.
authorJelmer Vernooij <jelmer@samba.org>
Sat, 11 Apr 2009 22:23:57 +0000 (00:23 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Sat, 11 Apr 2009 22:23:57 +0000 (00:23 +0200)
libirc/client.c
libirc/client.h
python/irc.c
python/tests/test_irc.py

index 43fd25232a6f4122dc08d89f49694a4d0bc1bfb7..00aff6f35c523529262d681df3c588268b701548 100644 (file)
@@ -387,7 +387,7 @@ void free_login_details(struct irc_login_details *details)
 /* 
  * @param desc Description of the client
  */
-struct irc_client *irc_client_new(struct irc_transport *transport, const char *default_origin, const char *desc, struct irc_client_callbacks *callbacks)
+struct irc_client *irc_client_new(struct irc_transport *transport, const char *default_origin, const char *desc, const struct irc_client_callbacks *callbacks)
 {
        struct irc_client *client;
 
index 3344a3a6cf534a8fd0b48d3b2a62c236b188d496..bc7574f7ed7ddb0a03dcd4b60fe67d847cfd50b8 100644 (file)
@@ -72,7 +72,7 @@ struct irc_client {
        gboolean connected;
        gboolean authenticated;
        struct irc_network_state *state;
-       struct irc_client_callbacks *callbacks;
+       const struct irc_client_callbacks *callbacks;
        struct irc_transport *transport;
        void *private_data;
 };
@@ -95,7 +95,7 @@ G_MODULE_EXPORT const char *client_get_own_hostmask(struct irc_client *c);
 G_MODULE_EXPORT struct irc_client *client_ref(struct irc_client *c);
 G_MODULE_EXPORT void client_ref_void(struct irc_client *c);
 G_MODULE_EXPORT void client_unref(struct irc_client *c);
-G_MODULE_EXPORT struct irc_client *irc_client_new(struct irc_transport *transport, const char *default_origin, const char *desc, struct irc_client_callbacks *callbacks);
+G_MODULE_EXPORT struct irc_client *irc_client_new(struct irc_transport *transport, const char *default_origin, const char *desc, const struct irc_client_callbacks *callbacks);
 G_MODULE_EXPORT void clients_send_state(GList *clients, 
                                                                                struct irc_network_state *s);
 
index b941ae0cc8097d26f2c9462abb020e0aabc7128b..6c69eb2b420ae4012852db2aa1964cb9f4151590 100644 (file)
@@ -22,7 +22,8 @@
 #include "ctrlproxy.h"
 #include "redirect.h"
 
-
+static const struct irc_client_callbacks py_client_callbacks;
+static struct irc_transport *wrap_py_transport(PyObject *obj);
 const char *get_my_hostname() { return NULL; /* FIXME */ }
 void log_global(enum log_level ll, const char *fmt, ...) { /* FIXME */}
 
@@ -1025,9 +1026,35 @@ static PyGetSetDef py_client_getsetters[] = {
     { NULL }
 };
 
+static PyObject *py_client_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyClientObject *ret;
+    PyObject *py_transport;
+    struct irc_transport *transport;
+    char *default_origin, *desc;
+    char *kwnames[] = { "transport", "default_origin", "desc", NULL };
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oss", kwnames, &py_transport, &default_origin, &desc))
+        return NULL;
+    
+    ret = (PyClientObject *)type->tp_alloc(type, 0);
+    if (ret == NULL) {
+        PyErr_NoMemory();
+        return NULL;
+    }
+
+    transport = wrap_py_transport(py_transport);
+
+    ret->client = irc_client_new(transport, default_origin, desc, &py_client_callbacks);
+    ret->client->private_data = ret;
+
+    return (PyObject *)ret;
+}
+
 PyTypeObject PyClientType = {
     .tp_name = "Client",
     .tp_flags = Py_TPFLAGS_DEFAULT,
+    .tp_new = py_client_new,
     .tp_methods = py_client_methods,
     .tp_getset = py_client_getsetters,
     .tp_basicsize = sizeof(PyClientObject)
@@ -1137,6 +1164,7 @@ static int py_process_from_client(struct irc_client *client, const struct irc_li
 {
     PyObject *self, *ret;
     PyLineObject *py_line;
+    self = client->private_data;
     py_line = PyObject_New(PyLineObject, &PyLineType);
     py_line->line = linedup(line);
     ret = PyObject_CallMethod(self, "process_from_client", "O", py_line);
@@ -1165,6 +1193,8 @@ static int py_process_to_client(struct irc_client *client, const struct irc_line
     ret = PyObject_CallMethod(self, "process_to_client", "O", py_line);
     Py_DECREF(py_line);
     Py_XDECREF(ret);
+
+    return 0;
 }
 
 static int py_welcome_client(struct irc_client *client)
@@ -1371,6 +1401,20 @@ static void py_transport_activate(struct irc_transport *transport)
     Py_XDECREF(ret);
 }
 
+static gboolean py_transport_set_charset(struct irc_transport *transport, const char *charsetname)
+{
+    PyObject *obj = (PyObject *)transport->backend_data, *ret;
+
+    ret = PyObject_CallMethod(obj, "set_charset", "s", charsetname);
+    if (ret == NULL) {
+        return FALSE;
+    }
+
+    Py_DECREF(ret);
+    return TRUE;
+}
+
+
 static struct irc_transport_ops py_transport_ops = {
     .free_data = (void (*) (void *))Py_DecRef,
     .is_connected = py_transport_is_connected,
@@ -1378,6 +1422,7 @@ static struct irc_transport_ops py_transport_ops = {
     .send_line = py_transport_send_line,
     .get_peer_name = py_transport_get_peer_name,
     .activate = py_transport_activate,
+    .set_charset = py_transport_set_charset,
 };
 
 static PyObject *py_transport_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
@@ -1397,9 +1442,22 @@ static PyObject *py_transport_new(PyTypeObject *type, PyObject *args, PyObject *
        self->transport->pending_lines = g_queue_new();
     self->transport->backend_data = self;
     self->transport->backend_ops = &py_transport_ops;
+
     return (PyObject *)self;
 }
 
+static struct irc_transport *wrap_py_transport(PyObject *obj)
+{
+    struct irc_transport *transport;
+
+    transport = g_new0(struct irc_transport, 1);
+       transport->pending_lines = g_queue_new();
+    transport->backend_data = obj;
+    transport->backend_ops = &py_transport_ops;
+
+    return transport;
+}
+
 static PyMethodDef py_transport_methods[] = {
     { NULL }
 };
index 14375c829540c747de4b1fd22e975a58c93bd02a..229a0060f66674d116271c245d1fd6db358a268a 100644 (file)
@@ -262,3 +262,16 @@ class TransportTests(unittest.TestCase):
 
     def test_create(self):
         t = irc.Transport()
+
+
+class DummyTransport(object):
+    """Trivial Transport."""
+
+    def send_line(self, line):
+        self._sent_lines.append(line)
+
+
+class ClientTests(unittest.TestCase):
+
+    def test_create(self):
+        c = irc.Client(DummyTransport(), "myorigin", "description")