Provide access to more Network attributes.
authorJelmer Vernooij <jelmer@samba.org>
Sun, 10 May 2009 22:12:27 +0000 (00:12 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Sun, 10 May 2009 22:12:27 +0000 (00:12 +0200)
libirc/connection.c
libirc/connection.h
libirc/python/irc.c
libirc/python/irc.h
libirc/python/state.c
python/ctrlproxy.c
src/client.c
src/listener.c
src/repl_backends.c

index 0067bf04bc0fd7df816b4219a78245365220de41..236d24bbab27a284629783e3c9b603f12419064e 100644 (file)
@@ -1009,7 +1009,7 @@ char *network_generate_feature_string(struct irc_network *n)
 /**
  * Increase the reference count for a network
  */
-struct irc_network *network_ref(struct irc_network *n)
+struct irc_network *irc_network_ref(struct irc_network *n)
 {
        if (n != NULL)
                n->references++;
index a717db4eaae1da7425f7d9c59ee5ae8fd413b5f4..ecf956361f964de04ff2bd8f05b1d114a72c155b 100644 (file)
@@ -169,7 +169,7 @@ G_MODULE_EXPORT gboolean virtual_network_recv_response(struct irc_network *n, in
 struct ctrlproxy_config;
 G_MODULE_EXPORT G_GNUC_MALLOC struct linestack_context *new_linestack(struct irc_network *network, struct ctrlproxy_config *settings);
 G_MODULE_EXPORT G_GNUC_MALLOC char *network_generate_feature_string(struct irc_network *n);
-G_MODULE_EXPORT struct irc_network *network_ref(struct irc_network *);
+G_MODULE_EXPORT struct irc_network *irc_network_ref(struct irc_network *);
 G_MODULE_EXPORT void irc_network_unref(struct irc_network *);
 G_MODULE_EXPORT void unregister_virtual_networks(void);
 
index 8e5b5e52d23c3ef6f3019d3596ee5ee684c2b0d7..e90f0b871082279aa0f2faec32ec2da3165ba1c1 100644 (file)
@@ -747,6 +747,7 @@ static PyMethodDef py_network_methods[] = {
 static void py_network_dealloc(PyNetworkObject *self)
 {
     irc_network_unref(self->network);
+    PyObject_Del(self);
 }
 
 static PyObject *py_network_repr(PyNetworkObject *self)
@@ -754,10 +755,144 @@ static PyObject *py_network_repr(PyNetworkObject *self)
     return PyString_FromFormat("<Network '%s'>", self->network->name);
 }
 
+static PyObject *py_network_get_name(PyNetworkObject *self, void *closure)
+{
+    return PyString_FromString(self->network->name);
+}
+
+static PyObject *py_network_get_reconnect_interval(PyNetworkObject *self, void *closure)
+{
+    return PyInt_FromLong(self->network->reconnect_interval);
+}   
+
+static int py_network_set_reconnect_interval(PyNetworkObject *self, PyObject *value, void *closure)
+{
+    if (!PyInt_Check(value)) {
+        PyErr_SetNone(PyExc_TypeError);
+        return -1;
+    }
+
+    self->network->reconnect_interval = PyInt_AsLong(value);
+    return 0;
+}
+
+static PyObject *py_network_get_info(PyNetworkObject *self, void *closure)
+{
+    PyNetworkInfoObject *pyinfo = PyObject_New(PyNetworkInfoObject, &PyNetworkInfoType);
+
+    if (pyinfo == NULL) {
+        PyErr_NoMemory();
+        return NULL;
+    }
+
+    Py_INCREF(self);
+    pyinfo->parent = (PyObject *)self;
+    pyinfo->info = self->network->info;
+
+    return (PyObject *)pyinfo;
+}
+
+static PyObject *py_network_get_internal_state(PyNetworkObject *self, void *closure)
+{
+    PyNetworkStateObject *ret;
+
+    if (self->network->internal_state == NULL)
+        Py_RETURN_NONE;
+    
+    ret = PyObject_New(PyNetworkStateObject, &PyNetworkStateType);
+    if (ret == NULL) {
+        PyErr_NoMemory();
+        return NULL;
+    }
+
+    Py_INCREF(self);
+    ret->parent = (PyObject *)self;
+    ret->state = self->network->internal_state;
+
+    return (PyObject *)ret;
+}
+
+static PyObject *py_network_get_external_state(PyNetworkObject *self, void *closure)
+{
+    PyNetworkStateObject *ret;
+
+    if (self->network->external_state == NULL)
+        Py_RETURN_NONE;
+    
+    ret = PyObject_New(PyNetworkStateObject, &PyNetworkStateType);
+    if (ret == NULL) {
+        PyErr_NoMemory();
+        return NULL;
+    }
+
+    Py_INCREF(self);
+    ret->parent = (PyObject *)self;
+    ret->state = self->network->external_state;
+
+    return (PyObject *)ret;
+}
+
+static PyObject *py_network_get_linestack_errors(PyNetworkObject *self, void *closure)
+{
+    return PyInt_FromLong(self->network->linestack_errors);
+}
+
+static PyObject *PyClientFromPtr(struct irc_client *c)
+{
+    PyClientObject *ret = PyObject_New(PyClientObject, &PyClientType);
+    if (ret == NULL) {
+        PyErr_NoMemory();
+        return NULL;
+    }
+    
+    ret->client = c;
+    client_ref(c);
+    return (PyObject *)ret;
+}
+
+static void *PyPtrFromClient(PyObject *obj)
+{
+    if (!PyObject_TypeCheck(obj, &PyClientType)) {
+        PyErr_SetNone(PyExc_TypeError);
+        return NULL;
+    }
+
+    return ((PyClientObject *)obj)->client;
+}   
+
+static PyObject *py_network_get_query_stack(PyNetworkObject *self, void *closure)
+{
+    PyQueryStackObject *ret = PyObject_New(PyQueryStackObject, &PyQueryStackType);
+    if (ret == NULL) {
+        PyErr_NoMemory();
+        return NULL;
+    }
+
+    ret->stack = self->network->queries;
+    ret->import_userdata = (PyObject *(*)(void *))PyClientFromPtr;
+    ret->export_userdata = PyPtrFromClient;
+    Py_INCREF(self);
+    ret->parent = (PyObject *)self;
+
+    return (PyObject *)ret;
+}
+
+static PyGetSetDef py_network_getsetters[] = {
+    { "name", (getter)py_network_get_name, NULL, "Name of the network" },
+    { "reconnect_interval", (getter)py_network_get_reconnect_interval, (setter)py_network_set_reconnect_interval, "Reconnect interval" },
+    { "info", (getter)py_network_get_info, NULL, "Info" },
+    { "internal_state", (getter) py_network_get_internal_state, NULL, "Internal state" },
+    { "external_state", (getter) py_network_get_external_state, NULL, "External state" },
+    { "linestack_errors", (getter) py_network_get_linestack_errors, NULL, "Number of linestack errors that has occurred so far" },
+    { "query_stack", (getter)py_network_get_query_stack, NULL, "Query stack" },
+    { NULL }
+};
+
 PyTypeObject PyNetworkType = {
     .tp_name = "Network",
     .tp_flags = Py_TPFLAGS_DEFAULT,
     .tp_methods = py_network_methods,
+    .tp_getset = py_network_getsetters,
     .tp_repr = (reprfunc)py_network_repr,
     .tp_basicsize = sizeof(PyNetworkObject),
     .tp_dealloc = (destructor)py_network_dealloc,
@@ -827,14 +962,10 @@ static const struct irc_client_callbacks py_client_callbacks = {
     .welcome = py_welcome_client
 };
 
-typedef struct {
-    PyObject_HEAD
-    struct query_stack *stack;
-} PyQueryStackObject;
-
 static PyObject *py_query_stack_record(PyQueryStackObject *self, PyObject *args)
 {
     PyObject *py_token, *py_line;
+    void *userdata;
     struct irc_line *line;
 
     if (!PyArg_ParseTuple(args, "OO", &py_token, &py_line))
@@ -844,7 +975,16 @@ static PyObject *py_query_stack_record(PyQueryStackObject *self, PyObject *args)
     if (line == NULL)
         return NULL;
 
-    return PyBool_FromLong(query_stack_record(self->stack, py_token, line));
+    if (self->export_userdata == NULL) {
+        userdata = py_token;
+    } else {
+        userdata = self->export_userdata(py_token);
+        if (userdata == NULL) {
+            free_line(line);
+            return NULL;
+        }
+    }
+    return PyBool_FromLong(query_stack_record(self->stack, userdata, line));
 }
 
 static PyObject *py_query_stack_redirect(PyQueryStackObject *self, PyObject *args)
@@ -884,11 +1024,20 @@ static PyMethodDef py_query_stack_methods[] = {
 
 static int py_query_stack_dealloc(PyQueryStackObject *self)
 {
-    query_stack_free(self->stack);
+    if (self->parent != NULL) {
+        Py_DECREF(self->parent);
+    } else {
+        query_stack_free(self->stack);
+    }
     PyObject_Del(self);
     return 0;
 }
 
+static PyObject *Py_Id(void *obj)
+{
+    return obj;
+}
+
 static PyObject *py_query_stack_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
     PyQueryStackObject *self = (PyQueryStackObject *)type->tp_alloc(type, 0);
@@ -898,13 +1047,16 @@ static PyObject *py_query_stack_new(PyTypeObject *type, PyObject *args, PyObject
     }
 
     self->stack = new_query_stack((void (*)(void *))Py_IncRef, (void (*)(void *))Py_DecRef);
+    self->import_userdata = Py_Id;
+    self->export_userdata = NULL;
+    self->parent = NULL;
 
     return (PyObject *)self;
 }
 
 static PyObject *py_query_stack_entry_from_ptr(PyQueryStackObject *parent, struct query_stack_entry *e)
 {
-    return Py_BuildValue("(Osl)", e->userdata, e->query->name, e->time);
+    return Py_BuildValue("(O&sl)", parent->import_userdata, e->userdata, e->query->name, e->time);
 }
 
 static PyObject *py_query_stack_iter(PyQueryStackObject *self)
@@ -912,6 +1064,15 @@ static PyObject *py_query_stack_iter(PyQueryStackObject *self)
     return py_g_list_iter(self->stack->entries, (PyObject *)self, (PyObject *(*)(PyObject *, void*))py_query_stack_entry_from_ptr);
 }
 
+static Py_ssize_t py_query_stack_len(PyQueryStackObject *self)
+{
+    return g_list_length(self->stack->entries);
+}
+
+static PySequenceMethods py_query_stack_sequence = {
+    .sq_length = (lenfunc)py_query_stack_len,
+};
+
 PyTypeObject PyQueryStackType = {
     .tp_name = "QueryStack",
     .tp_flags = Py_TPFLAGS_DEFAULT,
@@ -920,6 +1081,7 @@ PyTypeObject PyQueryStackType = {
     .tp_iter = (getiterfunc)py_query_stack_iter,
     .tp_basicsize = sizeof(PyQueryStackObject),
     .tp_dealloc = (destructor)py_query_stack_dealloc,
+    .tp_as_sequence = &py_query_stack_sequence,
 };
 
 
index 6302baa33988d70257c5b388693007aa3b32472d..1655eddb59d1e23d3dc13109a81fa52e10730472 100644 (file)
@@ -33,6 +33,13 @@ typedef struct {
 
 /* network info */
 PyTypeObject PyNetworkInfoType;
+typedef struct {
+    PyObject_HEAD
+    struct irc_network_info *info;
+    PyObject *parent;
+} PyNetworkInfoObject;
+
+
 PyTypeObject PyNetworkChannelDictType;
 PyTypeObject PyChannelNickDictType;
 PyTypeObject PyChannelModeDictType;
@@ -92,4 +99,15 @@ typedef struct {
     struct irc_network *network;
 } PyNetworkObject;
 
+/* query stack */
+typedef struct {
+    PyObject_HEAD
+    struct query_stack *stack;
+    PyObject *parent;
+    void *(*export_userdata) (PyObject *);
+    PyObject *(*import_userdata) (void *);
+} PyQueryStackObject;
+PyTypeObject PyQueryStackType;
+
+
 #endif
index 55f95e3b76e545cab868be1bf04d6e48bfb28a2a..a81d576253f70e34d291c6a3c82cd9aed10e3906 100644 (file)
 #include "redirect.h"
 #include "libirc/python/irc.h"
 
-typedef struct {
-    PyObject_HEAD
-    struct irc_network_info *info;
-    PyObject *parent;
-} PyNetworkInfoObject;
-
 static PyObject *py_networkinfo_is_prefix(PyNetworkInfoObject *self, PyObject *args)
 {
     char *prefix;
@@ -1055,5 +1049,3 @@ PyTypeObject PyNetworkStateType = {
     .tp_dealloc = (destructor)py_network_state_dealloc,
     .tp_as_mapping = &py_network_state_mapping,
 };
-
-
index 3caa6451bf18b144f2efd50073e6860286e26902..bd8964b0b8bc64da8dc0bdef27cf7e0e78b0061a 100644 (file)
@@ -76,7 +76,8 @@ static PyObject *py_network_dict_get(PyNetworkDictObject *self, PyObject *py_nam
                PyErr_NoMemory();
                return NULL;
        }
-       ret->network = n;
+       Py_INCREF(self);
+       ret->network = irc_network_ref(n);
        return (PyObject *)ret;
 }      
 
index 98ae56fd1f3b6f69adda2b6854be82b90d540525..c186b90ee235a3d8d8988d681997fc176710241c 100644 (file)
@@ -284,7 +284,7 @@ static void client_connect_command(struct irc_client *client, const char *hostna
 
        struct irc_network *network;
 
-       network = network_ref(find_network_by_hostname(my_global, 
+       network = irc_network_ref(find_network_by_hostname(my_global, 
                                                                                                   hostname, port, my_global->config->create_implicit, 
                                                                                                   client->login_details));
 
@@ -337,7 +337,7 @@ struct irc_client *client_init(struct irc_network *n, struct irc_transport *tran
        client = irc_client_new(transport, n?n->name:get_my_hostname(), desc, &default_callbacks);
        client->authenticated = FALSE;
 
-       client->network = network_ref(n);
+       client->network = irc_network_ref(n);
 
        if (n != NULL && n->global != NULL)
                client_set_charset(client, n->global->config->client_charset);
index 125f2a9e24a625ec460ea23bc57b8f20d46cad4c..d74e9eafb5a82885581b3563581be848724079f2 100644 (file)
@@ -316,7 +316,7 @@ struct irc_listener *listener_init(struct global *global, struct listener_config
        l->log_fn = default_listener_log_fn;
 
        if (l->config->network != NULL) {
-               l->network = network_ref(find_network(global->networks, l->config->network));
+               l->network = irc_network_ref(find_network(global->networks, l->config->network));
                if (l->network == NULL) {
                        listener_log(LOG_WARNING, l, "Network `%s' for listener not found", l->config->network);
                }
index b157d04d823fddb57fa0c9639aa5be23c6936fea..7a4a009333ea8e84ed029ec5d7b817015d232f8d 100644 (file)
@@ -55,7 +55,7 @@ static void highlight_replicate(struct irc_client *c)
                return;
 
        linestack_traverse(c->network->linestack, lm, NULL, check_highlight, c);
-       g_hash_table_replace(markers, network_ref(c->network), linestack_get_marker(c->network->linestack));
+       g_hash_table_replace(markers, irc_network_ref(c->network), linestack_get_marker(c->network->linestack));
 }
 
 static void none_replicate(struct irc_client *c)
@@ -70,7 +70,7 @@ static void lastdisconnect_mark(struct irc_client *c, void *userdata)
                return;
 
        if (c->network->linestack != NULL) 
-               g_hash_table_replace(lastdisconnect_backlog, network_ref(c->network), 
+               g_hash_table_replace(lastdisconnect_backlog, irc_network_ref(c->network), 
                                                         linestack_get_marker(c->network->linestack));
 }
 
@@ -101,7 +101,7 @@ static gboolean log_data(struct irc_network *n, const struct irc_line *l, enum d
                g_strcasecmp(l->args[0], "NOTICE")) return TRUE;
 
        if (n->linestack != NULL) 
-               g_hash_table_replace(simple_backlog, network_ref(n), 
+               g_hash_table_replace(simple_backlog, irc_network_ref(n), 
                                                         linestack_get_marker(n->linestack));
 
        return TRUE;