]> git.ipfire.org Git - people/ms/python-rrdtool.git/blobdiff - rrdtool-py3k.c
* Added support for Python 2.7 (other 2.x versions might also work, but its not tested)
[people/ms/python-rrdtool.git] / rrdtool-py3k.c
diff --git a/rrdtool-py3k.c b/rrdtool-py3k.c
deleted file mode 100644 (file)
index b5804e3..0000000
+++ /dev/null
@@ -1,747 +0,0 @@
-/*
- * rrdtool-py3k, rrdtool bindings for Python 3.
- * Based on the rrdtool Python bindings for Python 2 from
- * Hye-Shik Chang <perky@fallin.lv>.
- *
- * Copyright 2012 Christian Jurk <commx@commx.ws>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as 
- * published by the Free Software Foundation; either version 3 of the 
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- */
-
-#include <Python.h>
-#include <rrd.h>
-
-static const char *_version = "0.1.0";
-
-/* Exception types */
-static PyObject *rrdtool_OperationalError;
-static PyObject *rrdtool_ProgrammingError;
-
-static char **rrdtool_argv = NULL;
-static int rrdtool_argc = 0;
-
-static void
-destroy_args(void)
-{
-    PyMem_Del(rrdtool_argv);
-    rrdtool_argv = NULL;
-}
-
-/* Helper function to convert Python objects into a representation that the
- * rrdtool functions can work with.
- */
-static int
-convert_args(char *command, PyObject *args)
-{
-    PyObject *o, *lo;
-    int i, j, args_count, argv_count, element_count;
-
-    args_count = PyTuple_Size(args);
-    element_count = 0;
-    for (i = 0; i < args_count; i++)
-    {
-        o = PyTuple_GET_ITEM(args, i);
-        if (PyUnicode_Check(o) || PyBytes_Check(o))
-            element_count++;
-        else if (PyList_CheckExact(o))
-            element_count += PyList_Size(o);
-        else {
-            PyErr_Format(rrdtool_ProgrammingError,
-                         "Argument %d must be string, bytes or list of " \
-                         "string/bytes", i);
-            return -1;
-        }
-    }
-
-    rrdtool_argv = PyMem_New(char *, element_count + 1);
-
-    if (rrdtool_argv == NULL)
-        return -1;
-
-    argv_count = 0;
-    for (i = 0; i < args_count; i++) {
-        o = PyTuple_GET_ITEM(args, i);
-
-        if (PyUnicode_Check(o))
-            rrdtool_argv[++argv_count] = PyBytes_AsString(
-              PyUnicode_AsUTF8String(o));
-        else if (PyBytes_Check(o))
-            rrdtool_argv[++argv_count] = PyBytes_AS_STRING(o);
-        else if (PyList_CheckExact(o)) {
-            for (j = 0; j < PyList_Size(o); j++) {
-                lo = PyList_GetItem(o, j);
-                if (PyUnicode_Check(lo))
-                    rrdtool_argv[++argv_count] = PyBytes_AS_STRING(
-                      PyUnicode_AsUTF8String(lo));
-                else if (PyBytes_Check(lo))
-                    rrdtool_argv[++argv_count] = PyBytes_AS_STRING(lo);
-                else {
-                    PyMem_Del(rrdtool_argv);
-                    PyErr_Format(rrdtool_ProgrammingError,
-                      "Element %d in argument %d must be string", j, i);
-                    return -1;
-                }
-            }
-        } else {
-            PyMem_Del(rrdtool_argv);
-            PyErr_Format(rrdtool_ProgrammingError,
-              "Argument %d must be string or list of strings", i);
-            return -1;
-        }
-    }
-
-    rrdtool_argv[0] = command;
-    rrdtool_argc = element_count + 1;
-
-    return 0;
-}
-
-static PyObject *
-_rrdtool_util_info2dict(const rrd_info_t *data)
-{
-    PyObject *dict, *val;
-
-    dict = PyDict_New();
-
-    while (data) {
-        val = NULL;
-
-        switch (data->type) {
-            case RD_I_VAL:
-                if (isnan(data->value.u_val)) {
-                    Py_INCREF(Py_None);
-                    val = Py_None;
-                } else
-                    PyFloat_FromDouble(data->value.u_val);
-                break;
-
-            case RD_I_CNT:
-                val = PyLong_FromUnsignedLong(data->value.u_cnt);
-                break;
-
-            case RD_I_INT:
-                val = PyLong_FromLong(data->value.u_int);
-                break;
-
-            case RD_I_STR:
-                val = PyUnicode_FromString(data->value.u_str);
-                break;
-
-            case RD_I_BLO:
-                val = PyUnicode_FromStringAndSize(
-                  (char *)data->value.u_blo.ptr, data->value.u_blo.size);
-                break;
-            default:
-                break;
-        }
-
-        if (val != NULL) {
-            PyDict_SetItemString(dict, data->key, val);
-            Py_DECREF(val);
-        }
-
-        data = data->next;
-    }
-
-    return dict;
-}
-
-static char _rrdtool_create__doc__[] = "Create a new Round Robin Database.\n\n\
-  Usage: create(args...)\n\
-  Arguments:\n\n\
-    filename\n\
-    [--start|-b start time]\n\
-    [--step|-s step]\n\
-    [DS:ds-name:DST:heartbeat:min:max]\n\
-    [RRA:CF:xff:steps:rows]\n\n\
-    Full documentation can be found at:\n\
-    http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html";
-
-static PyObject *
-_rrdtool_create(PyObject *self, PyObject *args)
-{
-    PyObject *ret;
-
-    if (convert_args("create", args) == -1)
-        return NULL;
-
-       if (rrd_create(rrdtool_argc, rrdtool_argv) == -1) {
-               PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-               rrd_clear_error();
-               ret = NULL;
-       } else {
-        Py_INCREF(Py_None);
-        ret = Py_None;
-    }
-
-       destroy_args();
-    return ret;
-}
-
-static char _rrdtool_update__doc__[] = "Store a new set of values into\
- the RRD.\n\n\
- Usage: update(args..)\n\
- Arguments:\n\n\
-   filename\n\
-   [--template|-t ds-name[:ds-name]...]\n\
-   N|timestamp:value[:value...]\n\
-   [timestamp:value[:value...] ...]\n\n\
-   Full documentation can be found at:\n\
-   http://oss.oetiker.ch/rrdtool/doc/rrdupdate.en.html";
-
-static PyObject *
-_rrdtool_update(PyObject *self, PyObject *args)
-{
-    PyObject *ret;
-
-    if (convert_args("update", args) == -1)
-        return NULL;
-
-    if (rrd_update(rrdtool_argc, rrdtool_argv) == -1) {
-        PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-        rrd_clear_error();
-        ret = NULL;
-    } else {
-        Py_INCREF(Py_None);
-        ret = Py_None;
-    }
-
-       destroy_args();
-    return ret;
-}
-
-static char _rrdtool_updatev__doc__[] = "Store a new set of values into "\
-  "the Round Robin Database and return an info dictionary.\n\n\
-  This function works in the same manner as 'update', but will return an\n\
-  info dictionary instead of None.";
-
-static PyObject *
-_rrdtool_updatev(PyObject *self, PyObject *args)
-{
-    PyObject *ret;
-    rrd_info_t *data;
-
-    if (convert_args("updatev", args) == -1)
-        return NULL;
-
-    if ((data = rrd_update_v(rrdtool_argc, rrdtool_argv)) == NULL) {
-        PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-        rrd_clear_error();
-        ret = NULL;
-    } else {
-        ret = _rrdtool_util_info2dict(data);
-        rrd_info_free(data);
-    }
-
-       destroy_args();
-    return ret;
-}
-
-static char _rrdtool_fetch__doc__[] = "Fetch data from an RRD.\n\n\
-  Usage: fetch(args..)\n\
-  Arguments:\n\n\
-    filename\n\
-    CF\n\
-    [--resolution|-r resolution]\n\
-    [--start|-s start]\n\
-    [--end|-e end]\n\n\
-    Full documentation can be found at:\n\
-    http://oss.oetiker.ch/rrdtool/doc/rrdfetch.en.html";
-
-static PyObject *
-_rrdtool_fetch(PyObject *self, PyObject *args)
-{
-    PyObject *ret, *range_tup, *dsnam_tup, *data_list, *t;
-    rrd_value_t *data, *datai, dv;
-    unsigned long step, ds_cnt, i, j, row;
-    time_t start, end;
-    char **ds_namv;
-
-    if (convert_args("fetch", args) == -1)
-        return NULL;
-
-    if (rrd_fetch(rrdtool_argc, rrdtool_argv, &start, &end, &step, &ds_cnt,
-                  &ds_namv, &data) == -1) {
-        PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-        rrd_clear_error();
-        ret = NULL;
-    } else {
-        row = (end - start) / step;
-        ret = PyTuple_New(3);
-        range_tup = PyTuple_New(3);
-        dsnam_tup = PyTuple_New(ds_cnt);
-        data_list = PyList_New(row);
-
-        PyTuple_SET_ITEM(ret, 0, range_tup);
-        PyTuple_SET_ITEM(ret, 1, dsnam_tup);
-        PyTuple_SET_ITEM(ret, 2, data_list);
-
-        datai = data;
-
-        PyTuple_SET_ITEM(range_tup, 0, PyLong_FromLong((long)start));
-        PyTuple_SET_ITEM(range_tup, 1, PyLong_FromLong((long)end));
-        PyTuple_SET_ITEM(range_tup, 2, PyLong_FromLong((long)step));
-
-        for (i = 0; i < ds_cnt; i++)
-            PyTuple_SET_ITEM(dsnam_tup, i, PyUnicode_FromString(ds_namv[i]));
-
-        for (i = 0; i < row; i++) {
-            t = PyTuple_New(ds_cnt);
-            PyList_SET_ITEM(data_list, i, t);
-
-            for (j = 0; j < ds_cnt; j++) {
-                dv = *(datai++);
-                if (isnan(dv)) {
-                    PyTuple_SET_ITEM(t, j, Py_None);
-                    Py_INCREF(Py_None);
-                } else
-                    PyTuple_SET_ITEM(t, j, PyFloat_FromDouble((double)dv));
-            }
-        }
-
-        for (i = 0; i < ds_cnt; i++)
-            rrd_freemem(ds_namv[i]);
-
-        rrd_freemem(ds_namv);
-        rrd_freemem(data);
-    }
-
-    destroy_args();
-    return ret;
-}
-
-static char _rrdtool_flushcached__doc__[] = "Flush RRD files from memory.\n\n\
-  Usage: flushcached(args..)\n\
-  Arguments:\n\n\
-    [--daemon address]\n\
-    filename\n\
-    [filename ...]\n\n\
-    Full documentation can be found at:\n\
-    http://oss.oetiker.ch/rrdtool/doc/rrdflushcached.en.html";
-
-static PyObject *
-_rrdtool_flushcached(PyObject *self, PyObject *args)
-{
-    PyObject *ret;
-
-    if (convert_args("flushcached", args) == -1)
-        return NULL;
-
-    if (rrd_flushcached(rrdtool_argc, rrdtool_argv) != 0) {
-        PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-        rrd_clear_error();
-        ret = NULL;
-    } else {
-        Py_INCREF(Py_None);
-        ret = Py_None;
-    }
-
-       destroy_args();
-    return ret;
-}
-
-static char _rrdtool_graph__doc__[] = "Create a graph based on one or more " \
-  "RRDs.\n\n\
-  Usage: graph(args..)\n\
-  Arguments:\n\n\
-    filename | -\n\
-    [-s|--start start]\n\
-    [-e|--end end]\n\
-    [-S|--step step]\n\
-    [-t|--title string]\n\
-    [-v|--vertical-label string]\n\
-    [-w|--width pixels]\n\
-    [-h|--height pixels]\n\
-    [-j|--only-graph]\n\
-    [-D|--full-size-mode]\n\
-    [-u|--upper-limit value]\n\
-    [-l|--lower-limit value]\n\
-    [-r|--rigid]\n\
-    [-A|--alt-autoscale]\n\
-    [-J|--alt-autoscale-min]\n\
-    [-M|--alt-autoscale-max]\n\
-    [-N|--no-gridfit]\n\
-    [-x|--x-grid (GTM:GST:MTM:MST:LTM:LST:LPR:LFM|none)]\n\
-    [-y|--y-grid (grid step:label factor|none)]\n\
-    [-Y|--alt-y-grid]\n\
-    [-o|--logarithmic]\n\
-    [-X|--units-exponent value]\n\
-    [-L|--units-length value]\n\
-    [--units=si]\n\
-    [--right-axis scale:shift]\n\
-    [--right-axis-label label]\n\
-    [--right-axis-format format-string]\n\
-    [-g|--no-legend]\n\
-    [-F|--force-rules-legend]\n\
-    [--legend-position=(north|south|west|east)]\n\
-    [--legend-direction=(topdown|bottomup)]\n\
-    [-z|--lazy]\n\
-    [--daemon address]\n\
-    [-f|--imginfo printfstr]\n\
-    [-c|--color COLORTAG#rrggbb[aa]]\n\
-    [--grid-dash on:off]\n\
-    [--border width]\n\
-    [--dynamic-labels]\n\
-    [-m|--zoom factor]\n\
-    [-n|--font FONTTAG:size:[font]]\n\
-    [-R|--font-render-mode {normal,light,mono}]\n\
-    [-B|--font-smoothing-threshold size]\n\
-    [-P|--pango-markup]\n\
-    [-G|--graph-render-mode {normal,mono}]\n\
-    [-E|--slope-mode]\n\
-    [-a|--imgformat {PNG,SVG,EPS,PDF}]\n\
-    [-T|--tabwidth value]\n\
-    [-b|--base value]\n\
-    [-W|--watermark string]\n\
-    DEF:vname=rrdfile:ds-name:CF[:step=step][:start=time][:end=time]\n\
-    CDEF:vname=RPN expression\n\
-    VDEF=vname:RPN expression\n\n\
-    Full documentation can be found at:\n\
-    http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html";
-
-static PyObject *
-_rrdtool_graph(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    PyObject *ret;
-    int xsize, ysize, i;
-    int keep_in_mem = 0;
-    double ymin, ymax;
-    char **calcpr, *bp;
-#ifdef _POSIX_C_SOURCE
-    FILE *orig_stdout = stdout;
-    size_t bsize;
-#endif
-
-    if (convert_args("graph", args) == -1)
-        return NULL;
-
-    if (rrdtool_argc >= 2 && strcmp(rrdtool_argv[1], "-") == 0) {
-#ifdef _POSIX_C_SOURCE
-        keep_in_mem = 1;
-#else
-        PyErr_SetString(rrdtool_ProgrammingError,
-          "Output filename cannot be '-', because this platform does not "\
-          "support output buffering");
-        destroy_args();
-        return NULL;
-#endif
-    }
-
-#ifdef _POSIX_C_SOURCE
-    if (keep_in_mem)
-        stdout = open_memstream(&bp, &bsize);
-#endif
-
-    if (rrd_graph(rrdtool_argc, rrdtool_argv, &calcpr, &xsize, &ysize, NULL,
-                  &ymin, &ymax) == -1) {
-        PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-        rrd_clear_error();
-        ret = NULL;
-    } else {
-        ret = PyTuple_New(keep_in_mem ? 4 : 3);
-
-        PyTuple_SET_ITEM(ret, 0, PyLong_FromLong((long)xsize));
-        PyTuple_SET_ITEM(ret, 1, PyLong_FromLong((long)ysize));
-
-        if (calcpr) {
-            PyObject *e, *t;
-
-            e = PyList_New(0);
-            PyTuple_SET_ITEM(ret, 2, e);
-
-            for (i = 0; calcpr[i]; i++) {
-                t = PyUnicode_FromString(calcpr[i]);
-                PyList_Append(e, t);
-                Py_DECREF(t);
-                rrd_freemem(calcpr[i]);
-            }
-        } else {
-            Py_INCREF(Py_None);
-            PyTuple_SET_ITEM(ret, 2, Py_None);
-        }
-
-        /* feed buffered contents into a PyBytes object */
-        if (keep_in_mem) {
-            PyObject *pb;
-
-            fflush(stdout);
-            pb = PyBytes_FromStringAndSize(bp, bsize);
-
-            PyTuple_SET_ITEM(ret, 3, pb);
-        }
-    }
-
-    if (keep_in_mem) {
-        fclose(stdout);
-        stdout = orig_stdout;
-    }
-
-    destroy_args();
-    return ret;
-}
-
-static char _rrdtool_graphv__doc__[] = "Create a graph based on one or more "\
-  "RRDs and return header information.\n\n\
-  This function works in the same manner as 'graph', but will return a info\n\
-  dictionary instead of None.";
-
-static PyObject *
-_rrdtool_graphv(PyObject *self, PyObject *args)
-{
-    PyObject *ret;
-    rrd_info_t *data;
-
-    if (convert_args("graphv", args) == -1)
-        return NULL;
-
-    if ((data = rrd_graph_v(rrdtool_argc, rrdtool_argv)) == NULL) {
-        PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-        rrd_clear_error();
-        ret = NULL;
-    } else {
-        ret = _rrdtool_util_info2dict(data);
-        rrd_info_free(data);
-    }
-
-    destroy_args();
-    return ret;
-}
-
-static char _rrdtool_tune__doc__[] = "Modify some basic properties of a " \
-  "Round Robin Database.\n\n\
-  Usage: tune(args..)\n\
-  Arguments:\n\n\
-    filename\n\
-    [-h|--heartbeat ds-name:heartbeat]\n\
-    [-i|--minimum ds-name:min]\n\
-    [-a|--maximum ds-name:max]\n\
-    [-d|--data-source-type ds-name:DST]\n\
-    [-r|--data-source-rename old-name:new-name]\n\n\
-    Full documentation can be found at:\n\
-    http://oss.oetiker.ch/rrdtool/doc/rrdtune.en.html";
-
-static PyObject *
-_rrdtool_tune(PyObject *self, PyObject *args)
-{
-    PyObject *ret;
-
-    if (convert_args("tune", args) == -1)
-        return NULL;
-
-    if (rrd_tune(rrdtool_argc, rrdtool_argv) == -1) {
-        PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-        rrd_clear_error();
-        ret = NULL;
-    } else {
-        Py_INCREF(Py_None);
-        ret = Py_None;
-    }
-
-    destroy_args();
-    return ret;
-}
-
-static char _rrdtool_first__doc__[] = "Get the first UNIX timestamp of the "\
-  "first data sample in an Round Robin Database.\n\n\
-  Usage: first(args..)\n\
-  Arguments:\n\n\
-    filename\n\
-    [--rraindex number]\n\n\
-    Full documentation can be found at:\n\
-    http://oss.oetiker.ch/rrdtool/doc/rrdfirst.en.html";
-
-static PyObject *
-_rrdtool_first(PyObject *self, PyObject *args)
-{
-    PyObject *ret;
-    int ts;
-
-    if (convert_args("first", args) == -1)
-        return NULL;
-
-    if ((ts = rrd_first(rrdtool_argc, rrdtool_argv)) == -1) {
-        PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-        rrd_clear_error();
-        ret = NULL;
-    } else
-        ret = PyLong_FromLong((long)ts);
-
-    destroy_args();
-    return ret;
-}
-
-static char _rrdtool_last__doc__[] = "Get the UNIX timestamp of the most "\
-  "recent data sample in an Round Robin Database.\n\n\
-  Usage: last(args..)\n\
-  Arguments:\n\n\
-    filename\n\
-    [--daemon address]\n\n\
-    Full documentation can be found at:\n\
-    http://oss.oetiker.ch/rrdtool/doc/rrdlast.en.html";
-
-static PyObject *
-_rrdtool_last(PyObject *self, PyObject *args)
-{
-    PyObject *ret;
-    int ts;
-
-    if (convert_args("last", args) == -1)
-        return NULL;
-
-    if ((ts = rrd_last(rrdtool_argc, rrdtool_argv)) == -1) {
-        PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-        rrd_clear_error();
-        ret = NULL;
-    } else
-        ret = PyLong_FromLong((long)ts);
-
-    destroy_args();
-    return ret;
-}
-
-static char _rrdtool_resize__doc__[] = "Modify the number of rows in a "\
- "Round Robin Database.\n\n\
-  Usage: resize(args..)\n\
-  Arguments:\n\n\
-    filename\n\
-    rra-num\n\
-    GROW|SHRINK\n\
-    rows\n\n\
-    Full documentation can be found at:\n\
-    http://oss.oetiker.ch/rrdtool/doc/rrdlast.en.html";
-
-static PyObject *
-_rrdtool_resize(PyObject *self, PyObject *args)
-{
-    PyObject *ret;
-    int ts;
-
-    if (convert_args("resize", args) == -1)
-        return NULL;
-
-    if ((ts = rrd_resize(rrdtool_argc, rrdtool_argv)) == -1) {
-        PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-        rrd_clear_error();
-        ret = NULL;
-    } else {
-        Py_INCREF(Py_None);
-        ret = Py_None;
-    }
-
-    destroy_args();
-    return ret;
-}
-
-static char _rrdtool_info__doc__[] = "Extract header information from an "\
- "Round Robin Database.\n\n\
-  Usage: info(filename)\n\
-  Arguments:\n\n\
-    filename\n\n\
-    Full documentation can be found at:\n\
-    http://oss.oetiker.ch/rrdtool/doc/rrdinfo.en.html";
-
-static PyObject *
-_rrdtool_info(PyObject *self, PyObject *args)
-{
-    PyObject *ret;
-    rrd_info_t *data;
-
-    if (convert_args("info", args) == -1)
-        return NULL;
-
-    if ((data = rrd_info(rrdtool_argc, rrdtool_argv)) == NULL) {
-        PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
-        rrd_clear_error();
-        ret = NULL;
-    } else {
-        ret = _rrdtool_util_info2dict(data);
-        rrd_info_free(data);
-    }
-
-    destroy_args();
-    return ret;
-}
-
-static char _rrdtool_lib_version__doc__[] = "Get the version this binding "\
-  "was compiled against.";
-
-static PyObject *
-_rrdtool_lib_version(PyObject *self, PyObject *args)
-{
-    return PyUnicode_FromString(rrd_strversion());
-}
-
-static PyMethodDef rrdtool_methods[] = {
-       {"create", (PyCFunction)_rrdtool_create,
-     METH_VARARGS, _rrdtool_create__doc__},
-    {"update", (PyCFunction)_rrdtool_update,
-     METH_VARARGS, _rrdtool_update__doc__},
-    {"updatev", (PyCFunction)_rrdtool_updatev,
-     METH_VARARGS, _rrdtool_updatev__doc__},
-    {"fetch", (PyCFunction)_rrdtool_fetch,
-     METH_VARARGS, _rrdtool_fetch__doc__},
-    {"flushcached", (PyCFunction)_rrdtool_flushcached,
-     METH_VARARGS, _rrdtool_flushcached__doc__},
-    {"graph", (PyCFunction)_rrdtool_graph,
-     METH_VARARGS, _rrdtool_graph__doc__},
-    {"graphv", (PyCFunction)_rrdtool_graphv,
-     METH_VARARGS, _rrdtool_graphv__doc__},
-    {"tune", (PyCFunction)_rrdtool_tune,
-     METH_VARARGS, _rrdtool_tune__doc__},
-    {"first", (PyCFunction)_rrdtool_first,
-     METH_VARARGS, _rrdtool_first__doc__},
-    {"last", (PyCFunction)_rrdtool_last,
-     METH_VARARGS, _rrdtool_last__doc__},
-    {"resize", (PyCFunction)_rrdtool_resize,
-     METH_VARARGS, _rrdtool_resize__doc__},
-    {"info", (PyCFunction)_rrdtool_info,
-     METH_VARARGS, _rrdtool_info__doc__},
-    {"lib_version", (PyCFunction)_rrdtool_lib_version,
-     METH_VARARGS, _rrdtool_lib_version__doc__},
-       {NULL, NULL, 0, NULL}
-};
-
-static struct PyModuleDef rrdtoolmodule = {
-       PyModuleDef_HEAD_INIT,
-       "rrdtool",
-       "rrdtool bindings for Python 3",
-       -1,
-       rrdtool_methods
-};
-
-PyMODINIT_FUNC
-PyInit_rrdtool(void)
-{
-       PyObject *m;
-
-       m = PyModule_Create(&rrdtoolmodule);
-       if (m == NULL)
-               return NULL;
-
-       rrdtool_ProgrammingError = PyErr_NewException("rrdtool.ProgrammingError",
-                                                     NULL, NULL);
-       Py_INCREF(rrdtool_ProgrammingError);
-       PyModule_AddObject(m, "ProgrammingError", rrdtool_ProgrammingError);
-
-       rrdtool_OperationalError = PyErr_NewException("rrdtool.OperationalError",
-                                                     NULL, NULL);
-       Py_INCREF(rrdtool_OperationalError);
-       PyModule_AddObject(m, "OperationalError", rrdtool_OperationalError);
-    PyModule_AddObject(m, "__version__", PyUnicode_FromString(_version));
-
-       return m;
-}