Better and unicode compatible repr for PluginData.
[collectd.git] / src / pyvalues.c
index da7c21d..d459ea9 100644 (file)
@@ -1,3 +1,29 @@
+/**
+ * collectd - src/pyvalues.c
+ * Copyright (C) 2009  Sven Trenkel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Sven Trenkel <collectd at semidefinite.de>  
+ **/
+
 #include <Python.h>
 #include <structmember.h>
 
@@ -75,14 +101,84 @@ static int PluginData_init(PyObject *s, PyObject *args, PyObject *kwds) {
 }
 
 static PyObject *PluginData_repr(PyObject *s) {
+       PyObject *ret, *tmp;
+       static PyObject *l_type = NULL, *l_type_instance = NULL, *l_plugin = NULL, *l_plugin_instance = NULL;
+       static PyObject *l_host = NULL, *l_time = NULL, *l_closing = NULL;
        PluginData *self = (PluginData *) s;
        
-       return PyString_FromFormat("collectd.Values(type='%s%s%s%s%s%s%s%s%s',time=%lu)", self->type,
-                       *self->type_instance ? "',type_instance='" : "", self->type_instance,
-                       *self->plugin ? "',plugin='" : "", self->plugin,
-                       *self->plugin_instance ? "',plugin_instance='" : "", self->plugin_instance,
-                       *self->host ? "',host='" : "", self->host,
-                       (long unsigned) self->time);
+       if (l_type == NULL)
+               l_type = cpy_string_to_unicode_or_bytes("(type=");
+       if (l_type_instance == NULL)
+               l_type_instance = cpy_string_to_unicode_or_bytes(",type_instance=");
+       if (l_plugin == NULL)
+               l_plugin = cpy_string_to_unicode_or_bytes(",plugin=");
+       if (l_plugin_instance == NULL)
+               l_plugin_instance = cpy_string_to_unicode_or_bytes(",plugin_instance=");
+       if (l_host == NULL)
+               l_host = cpy_string_to_unicode_or_bytes(",host=");
+       if (l_time == NULL)
+               l_time = cpy_string_to_unicode_or_bytes(",time=");
+       if (l_closing == NULL)
+               l_closing = cpy_string_to_unicode_or_bytes(")");
+       
+       if (!l_type || !l_type_instance || !l_plugin || !l_plugin_instance || !l_host || !l_time)
+               return NULL;
+       
+       ret = cpy_string_to_unicode_or_bytes(s->ob_type->tp_name);
+
+       CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, l_type);
+       tmp = cpy_string_to_unicode_or_bytes(self->type);
+       CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+       if (tmp)
+               CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, tmp);
+       Py_XDECREF(tmp);
+
+       if (self->type_instance[0] != 0) {
+               CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, l_type_instance);
+               tmp = cpy_string_to_unicode_or_bytes(self->type_instance);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               if (tmp)
+                       CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, tmp);
+               Py_XDECREF(tmp);
+       }
+
+       if (self->plugin[0] != 0) {
+               CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, l_plugin);
+               tmp = cpy_string_to_unicode_or_bytes(self->plugin);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               if (tmp)
+                       CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, tmp);
+               Py_XDECREF(tmp);
+       }
+
+       if (self->plugin_instance[0] != 0) {
+               CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, l_plugin_instance);
+               tmp = cpy_string_to_unicode_or_bytes(self->plugin_instance);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               if (tmp)
+                       CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, tmp);
+               Py_XDECREF(tmp);
+       }
+
+       if (self->host[0] != 0) {
+               CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, l_host);
+               tmp = cpy_string_to_unicode_or_bytes(self->host);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               if (tmp)
+                       CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, tmp);
+               Py_XDECREF(tmp);
+       }
+
+       if (self->time != 0) {
+               CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, l_time);
+               tmp = PyInt_FromLong(self->time);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               if (tmp)
+                       CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, tmp);
+               Py_XDECREF(tmp);
+       }
+       CPY_SUBSTITUTE(CPY_STRCAT, ret, ret, l_closing);
+       return ret;
 }
 
 static PyMemberDef PluginData_members[] = {
@@ -93,7 +189,7 @@ static PyMemberDef PluginData_members[] = {
 static PyObject *PluginData_getstring(PyObject *self, void *data) {
        const char *value = ((char *) self) + (intptr_t) data;
        
-       return PyString_FromString(value);
+       return cpy_string_to_unicode_or_bytes(value);
 }
 
 static int PluginData_setstring(PyObject *self, PyObject *value, void *data) {
@@ -104,10 +200,15 @@ static int PluginData_setstring(PyObject *self, PyObject *value, void *data) {
                PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
                return -1;
        }
-       new = PyString_AsString(value);
-       if (new == NULL) return -1;
+       Py_INCREF(value);
+       new = cpy_unicode_or_bytes_to_string(&value);
+       if (new == NULL) {
+               Py_DECREF(value);
+               return -1;
+       }
        old = ((char *) self) + (intptr_t) data;
        sstrncpy(old, new, DATA_MAX_NAME_LEN);
+       Py_DECREF(value);
        return 0;
 }
 
@@ -119,16 +220,22 @@ static int PluginData_settype(PyObject *self, PyObject *value, void *data) {
                PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
                return -1;
        }
-       new = PyString_AsString(value);
-       if (new == NULL) return -1;
+       Py_INCREF(value);
+       new = cpy_unicode_or_bytes_to_string(&value);
+       if (new == NULL) {
+               Py_DECREF(value);
+               return -1;
+       }
 
        if (plugin_get_ds(new) == NULL) {
                PyErr_Format(PyExc_TypeError, "Dataset %s not found", new);
+               Py_DECREF(value);
                return -1;
        }
 
        old = ((char *) self) + (intptr_t) data;
        sstrncpy(old, new, DATA_MAX_NAME_LEN);
+       Py_DECREF(value);
        return 0;
 }
 
@@ -142,8 +249,7 @@ static PyGetSetDef PluginData_getseters[] = {
 };
 
 PyTypeObject PluginDataType = {
-       PyObject_HEAD_INIT(NULL)
-       0,                         /* Always 0 */
+       CPY_INIT_TYPE
        "collectd.PluginData",     /* tp_name */
        sizeof(PluginData),        /* tp_basicsize */
        0,                         /* Will be filled in later */
@@ -274,7 +380,7 @@ static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
 static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
        int i, ret;
        const data_set_t *ds;
-       Py_ssize_t size;
+       int size;
        value_t *value;
        value_list_t value_list = VALUE_LIST_INIT;
        PyObject *values = self->values;
@@ -288,7 +394,7 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
        
        static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "interval", NULL};
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sOssssdi", kwlist,
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sOzsssdi", kwlist,
                        &type, &values, &plugin_instance, &type_instance,
                        &plugin, &host, &time, &interval))
                return NULL;
@@ -306,9 +412,9 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
                PyErr_Format(PyExc_TypeError, "values must be list or tuple");
                return NULL;
        }
-       size = PySequence_Length(values);
+       size = (int) PySequence_Length(values);
        if (size != ds->ds_num) {
-               PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %zd", type, ds->ds_num, size);
+               PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", type, ds->ds_num, size);
                return NULL;
        }
        value = malloc(size * sizeof(*value));
@@ -373,7 +479,7 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
 static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
        int i, ret;
        const data_set_t *ds;
-       Py_ssize_t size;
+       int size;
        value_t *value;
        value_list_t value_list = VALUE_LIST_INIT;
        PyObject *values = self->values;
@@ -406,9 +512,9 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
                PyErr_Format(PyExc_TypeError, "values must be list or tuple");
                return NULL;
        }
-       size = PySequence_Length(values);
+       size = (int) PySequence_Length(values);
        if (size != ds->ds_num) {
-               PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %zd", type, ds->ds_num, size);
+               PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", type, ds->ds_num, size);
                return NULL;
        }
        value = malloc(size * sizeof(*value));
@@ -470,7 +576,7 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
        Py_RETURN_NONE;
 }
 
-static PyObject *Values_repr(PyObject *s) {
+/*static PyObject *Values_repr(PyObject *s) {
        PyObject *ret, *valuestring = NULL;
        Values *self = (Values *) s;
        
@@ -485,10 +591,10 @@ static PyObject *Values_repr(PyObject *s) {
                        *self->data.plugin_instance ? "',plugin_instance='" : "", self->data.plugin_instance,
                        *self->data.host ? "',host='" : "", self->data.host,
                        (long unsigned) self->data.time, self->interval,
-                       valuestring ? PyString_AsString(valuestring) : "[]");
+                       valuestring ? cpy_unicode_or_bytes_to_string(valuestring) : "[]");
        Py_XDECREF(valuestring);
        return ret;
-}
+}*/
 
 static int Values_traverse(PyObject *self, visitproc visit, void *arg) {
        Values *v = (Values *) self;
@@ -520,8 +626,7 @@ static PyMethodDef Values_methods[] = {
 };
 
 PyTypeObject ValuesType = {
-       PyObject_HEAD_INIT(NULL)
-       0,                         /* Always 0 */
+       CPY_INIT_TYPE
        "collectd.Values",         /* tp_name */
        sizeof(Values),            /* tp_basicsize */
        0,                         /* Will be filled in later */
@@ -530,7 +635,7 @@ PyTypeObject ValuesType = {
        0,                         /* tp_getattr */
        0,                         /* tp_setattr */
        0,                         /* tp_compare */
-       Values_repr,               /* tp_repr */
+       0/*Values_repr*/,               /* tp_repr */
        0,                         /* tp_as_number */
        0,                         /* tp_as_sequence */
        0,                         /* tp_as_mapping */
@@ -675,14 +780,19 @@ static int Notification_setstring(PyObject *self, PyObject *value, void *data) {
                PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
                return -1;
        }
-       new = PyString_AsString(value);
-       if (new == NULL) return -1;
+       Py_INCREF(value);
+       new = cpy_unicode_or_bytes_to_string(&value);
+       if (new == NULL) {
+               Py_DECREF(value);
+               return -1;
+       }
        old = ((char *) self) + (intptr_t) data;
        sstrncpy(old, new, NOTIF_MAX_MSG_LEN);
+       Py_DECREF(value);
        return 0;
 }
 
-static PyObject *Notification_repr(PyObject *s) {
+/*static PyObject *Notification_repr(PyObject *s) {
        PyObject *ret;
        Notification *self = (Notification *) s;
        
@@ -694,7 +804,7 @@ static PyObject *Notification_repr(PyObject *s) {
                        *self->message ? "',message='" : "", self->message,
                        (long unsigned) self->data.time, self->severity);
        return ret;
-}
+}*/
 
 static PyMethodDef Notification_methods[] = {
        {"dispatch", (PyCFunction) Notification_dispatch, METH_VARARGS | METH_KEYWORDS, dispatch_doc},
@@ -712,8 +822,7 @@ static PyGetSetDef Notification_getseters[] = {
 };
 
 PyTypeObject NotificationType = {
-       PyObject_HEAD_INIT(NULL)
-       0,                         /* Always 0 */
+       CPY_INIT_TYPE
        "collectd.Notification",   /* tp_name */
        sizeof(Notification),      /* tp_basicsize */
        0,                         /* Will be filled in later */
@@ -722,7 +831,7 @@ PyTypeObject NotificationType = {
        0,                         /* tp_getattr */
        0,                         /* tp_setattr */
        0,                         /* tp_compare */
-       Notification_repr,         /* tp_repr */
+       0/*Notification_repr*/,         /* tp_repr */
        0,                         /* tp_as_number */
        0,                         /* tp_as_sequence */
        0,                         /* tp_as_mapping */