Split python module. Added support for cyclic GC runs.
[collectd.git] / src / pyconfig.c
1 #include <Python.h>
2 #include <structmember.h>
3
4 #include "collectd.h"
5 #include "common.h"
6
7 #include "cpython.h"
8
9 static PyObject *Config_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
10         Config *self;
11         
12         self = (Config *) type->tp_alloc(type, 0);
13         if (self == NULL)
14                 return NULL;
15         
16         self->parent = NULL;
17         self->key = NULL;
18         self->values = NULL;
19         self->children = NULL;
20         return (PyObject *) self;
21 }
22
23 static int Config_init(PyObject *s, PyObject *args, PyObject *kwds) {
24         PyObject *key = NULL, *parent = NULL, *values = NULL, *children = NULL, *tmp;
25         Config *self = (Config *) s;
26         static char *kwlist[] = {"key", "parent", "values", "children", NULL};
27         
28         if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|OOO", kwlist,
29                         &key, &parent, &values, &children))
30                 return -1;
31         
32         if (values == NULL) {
33                 values = PyTuple_New(0);
34                 PyErr_Clear();
35         }
36         if (children == NULL) {
37                 children = PyTuple_New(0);
38                 PyErr_Clear();
39         }
40         tmp = self->key;
41         Py_INCREF(key);
42         self->key = key;
43         Py_XDECREF(tmp);
44         if (parent != NULL) {
45                 tmp = self->parent;
46                 Py_INCREF(parent);
47                 self->parent = parent;
48                 Py_XDECREF(tmp);
49         }
50         if (values != NULL) {
51                 tmp = self->values;
52                 Py_INCREF(values);
53                 self->values = values;
54                 Py_XDECREF(tmp);
55         }
56         if (children != NULL) {
57                 tmp = self->children;
58                 Py_INCREF(children);
59                 self->children = children;
60                 Py_XDECREF(tmp);
61         }
62         return 0;
63 }
64
65 static PyObject *Config_repr(PyObject *s) {
66         Config *self = (Config *) s;
67         
68         return PyString_FromFormat("<collectd.Config %snode %s>", self->parent == Py_None ? "root " : "", PyString_AsString(PyObject_Str(self->key)));
69 }
70
71 static int Config_traverse(PyObject *self, visitproc visit, void *arg) {
72         Config *c = (Config *) self;
73         Py_VISIT(c->parent);
74         Py_VISIT(c->key);
75         Py_VISIT(c->values);
76         Py_VISIT(c->children);
77         return 0;
78 }
79
80 static int Config_clear(PyObject *self) {
81         Config *c = (Config *) self;
82         Py_CLEAR(c->parent);
83         Py_CLEAR(c->key);
84         Py_CLEAR(c->values);
85         Py_CLEAR(c->children);
86         return 0;
87 }
88
89 static void Config_dealloc(PyObject *self) {
90         Config_clear(self);
91         self->ob_type->tp_free(self);
92 }
93
94 static PyMemberDef Config_members[] = {
95         {"Parent", T_OBJECT, offsetof(Config, parent), 0, "Parent node"},
96         {"Key", T_OBJECT_EX, offsetof(Config, key), 0, "Keyword of this node"},
97         {"Values", T_OBJECT_EX, offsetof(Config, values), 0, "Values after the key"},
98         {"Children", T_OBJECT_EX, offsetof(Config, children), 0, "Childnodes of this node"},
99         {NULL}
100 };
101
102 PyTypeObject ConfigType = {
103         PyObject_HEAD_INIT(NULL)
104         0,                         /* Always 0 */
105         "collectd.Config",         /* tp_name */
106         sizeof(Config),            /* tp_basicsize */
107         0,                         /* Will be filled in later */
108         Config_dealloc,            /* tp_dealloc */
109         0,                         /* tp_print */
110         0,                         /* tp_getattr */
111         0,                         /* tp_setattr */
112         0,                         /* tp_compare */
113         Config_repr,               /* tp_repr */
114         0,                         /* tp_as_number */
115         0,                         /* tp_as_sequence */
116         0,                         /* tp_as_mapping */
117         0,                         /* tp_hash */
118         0,                         /* tp_call */
119         0,                         /* tp_str */
120         0,                         /* tp_getattro */
121         0,                         /* tp_setattro */
122         0,                         /* tp_as_buffer */
123         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
124         "Cool help text later",    /* tp_doc */
125         Config_traverse,           /* tp_traverse */
126         Config_clear,              /* tp_clear */
127         0,                         /* tp_richcompare */
128         0,                         /* tp_weaklistoffset */
129         0,                         /* tp_iter */
130         0,                         /* tp_iternext */
131         0,                         /* tp_methods */
132         Config_members,            /* tp_members */
133         0,                         /* tp_getset */
134         0,                         /* tp_base */
135         0,                         /* tp_dict */
136         0,                         /* tp_descr_get */
137         0,                         /* tp_descr_set */
138         0,                         /* tp_dictoffset */
139         Config_init,               /* tp_init */
140         0,                         /* tp_alloc */
141         Config_new                 /* tp_new */
142 };
143