2 * python-rrdtool, rrdtool bindings for Python.
3 * Based on the rrdtool Python bindings for Python 2 from
4 * Hye-Shik Chang <perky@fallin.lv>.
6 * Copyright 2012 Christian Jurk <commx@commx.ws>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as
10 * published by the Free Software Foundation; either version 3 of the
11 * License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
29 /* Some macros to maintain compatibility between Python 2.x and 3.x */
30 #if PY_MAJOR_VERSION >= 3
32 #define PyRRD_String_Check(x) PyUnicode_Check(x)
33 #define PyRRD_String_FromString(x) PyUnicode_FromString(x)
34 #define PyRRD_String_AS_STRING(x) PyBytes_AsString(PyUnicode_AsUTF8String(o))
35 #define PyRRD_String_FromStringAndSize(x, y) PyBytes_FromStringAndSize(x, y)
36 #define PyRRD_Int_FromLong(x) PyLong_FromLong(x)
38 #define PyRRD_String_Check(x) PyString_Check(x)
39 #define PyRRD_String_FromString(x) PyString_FromString(x)
40 #define PyRRD_String_AS_STRING(x) PyString_AS_STRING(x)
41 #define PyRRD_String_FromStringAndSize(x, y) PyString_FromStringAndSize(x, y)
42 #define PyRRD_Int_FromLong(x) PyInt_FromLong(x)
45 /** Binding version. */
46 static const char *_version
= "0.1.2";
48 /** Exception types. */
49 static PyObject
*rrdtool_OperationalError
;
50 static PyObject
*rrdtool_ProgrammingError
;
52 static char **rrdtool_argv
= NULL
;
53 static int rrdtool_argc
= 0;
55 /* extern getopt state */
56 extern int optind
, opterr
;
60 * Helper function to convert Python objects into a representation that the
61 * rrdtool functions can work with.
63 * @param command RRDtool command name
64 * @param args Command arguments
65 * @return Zero if the function succeeds, otherwise -1
68 convert_args(char *command
, PyObject
*args
)
71 int i
, j
, args_count
, argv_count
= 0, element_count
= 0;
73 args_count
= PyTuple_Size(args
);
75 for (i
= 0; i
< args_count
; i
++)
77 o
= PyTuple_GET_ITEM(args
, i
);
79 if (PyRRD_String_Check(o
))
81 else if (PyList_CheckExact(o
))
82 element_count
+= PyList_Size(o
);
84 PyErr_Format(rrdtool_ProgrammingError
,
85 "Argument %d must be str or a list of str", i
);
90 rrdtool_argv
= PyMem_New(char *, element_count
+ 1);
92 if (rrdtool_argv
== NULL
)
95 for (i
= 0, args_count
= 0; i
< args_count
; i
++) {
96 o
= PyTuple_GET_ITEM(args
, i
);
98 if (PyRRD_String_Check(o
))
99 rrdtool_argv
[++argv_count
] = PyRRD_String_AS_STRING(o
);
100 else if (PyList_CheckExact(o
)) {
101 for (j
= 0; j
< PyList_Size(o
); j
++) {
102 lo
= PyList_GetItem(o
, j
);
104 if (PyRRD_String_Check(o
))
105 rrdtool_argv
[++argv_count
] = PyRRD_String_AS_STRING(o
);
107 PyMem_Del(rrdtool_argv
);
108 PyErr_Format(rrdtool_ProgrammingError
,
109 "Element %d in argument %d must be str", j
, i
);
114 PyMem_Del(rrdtool_argv
);
115 PyErr_Format(rrdtool_ProgrammingError
,
116 "Argument %d must be str or list of str", i
);
121 rrdtool_argv
[0] = command
;
122 rrdtool_argc
= element_count
+ 1;
124 for (i
= 0; i
< rrdtool_argc
; i
++) {
125 fprintf(stderr
, "argv[%d] = '%s'\n", i
, rrdtool_argv
[i
]);
128 /* reset getopt state */
135 * Destroy argument vector.
140 PyMem_Del(rrdtool_argv
);
145 * Convert RRDtool info to dict.
147 * @param data RRDtool info object
148 * @return Python dict object
151 _rrdtool_util_info2dict(const rrd_info_t
*data
)
153 PyObject
*dict
, *val
;
160 switch (data
->type
) {
162 if (isnan(data
->value
.u_val
)) {
166 PyFloat_FromDouble(data
->value
.u_val
);
170 val
= PyLong_FromUnsignedLong(data
->value
.u_cnt
);
174 val
= PyLong_FromLong(data
->value
.u_int
);
178 val
= PyRRD_String_FromString(data
->value
.u_str
);
182 val
= PyRRD_String_FromStringAndSize(
183 (char *)data
->value
.u_blo
.ptr
,
184 data
->value
.u_blo
.size
);
191 PyDict_SetItemString(dict
, data
->key
, val
);
201 static char _rrdtool_create__doc__
[] = "Create a new Round Robin Database.\n\n\
202 Usage: create(args...)\n\
205 [-b|--start start time]\n\
207 [-t|--template temolate-file]\n\
208 [-r|--source source-file]\n\
209 [-O|--no-overwrite]\n\
210 [-d|--daemon address]\n\
211 [DS:ds-name[=mapped-ds-name[source-index]]:DST:heartbeat:min:max]\n\
212 [RRA:CF:xff:steps:rows]\n\n\
213 Full documentation can be found at:\n\
214 http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html";
217 _rrdtool_create(PyObject
*self
, PyObject
*args
)
221 if (convert_args("create", args
) == -1)
224 if (rrd_create(rrdtool_argc
, rrdtool_argv
) == -1) {
225 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
237 static char _rrdtool_dump__doc__
[] = "Dump an RRD to XML.\n\n\
238 Usage: dump(args..)\n\
240 [-h|--header {none,xsd,dtd}\n\
242 [-d|--daemon address]\n\
245 Full documentation can be found at:\n\
246 http://oss.oetiker.ch/rrdtool/doc/rrddump.en.html";
249 _rrdtool_dump(PyObject
*self
, PyObject
*args
)
253 if (convert_args("dump", args
) == -1)
256 if (rrd_dump(rrdtool_argc
, rrdtool_argv
) != 0) {
257 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
269 static char _rrdtool_update__doc__
[] = "Store a new set of values into\
271 Usage: update(args..)\n\
274 [--template|-t ds-name[:ds-name]...]\n\
275 N|timestamp:value[:value...]\n\
276 [timestamp:value[:value...] ...]\n\n\
277 Full documentation can be found at:\n\
278 http://oss.oetiker.ch/rrdtool/doc/rrdupdate.en.html";
281 _rrdtool_update(PyObject
*self
, PyObject
*args
)
285 if (convert_args("update", args
) == -1)
288 if (rrd_update(rrdtool_argc
, rrdtool_argv
) == -1) {
289 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
301 static char _rrdtool_updatev__doc__
[] = "Store a new set of values into "\
302 "the Round Robin Database and return an info dictionary.\n\n\
303 This function works in the same manner as 'update', but will return an\n\
304 info dictionary instead of None.";
307 _rrdtool_updatev(PyObject
*self
, PyObject
*args
)
312 if (convert_args("updatev", args
) == -1)
315 if ((data
= rrd_update_v(rrdtool_argc
, rrdtool_argv
)) == NULL
) {
316 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
320 ret
= _rrdtool_util_info2dict(data
);
328 static char _rrdtool_fetch__doc__
[] = "Fetch data from an RRD.\n\n\
329 Usage: fetch(args..)\n\
333 [-r|--resolution resolution]\n\
334 [-s|--start start]\n\
336 [-a|--align-start]\n\
337 [-d|--daemon address]\n\n\
338 Full documentation can be found at:\n\
339 http://oss.oetiker.ch/rrdtool/doc/rrdfetch.en.html";
342 _rrdtool_fetch(PyObject
*self
, PyObject
*args
)
344 PyObject
*ret
, *range_tup
, *dsnam_tup
, *data_list
, *t
;
345 rrd_value_t
*data
, *datai
, dv
;
346 unsigned long step
, ds_cnt
, i
, j
, row
;
350 if (convert_args("fetch", args
) == -1)
353 if (rrd_fetch(rrdtool_argc
, rrdtool_argv
, &start
, &end
, &step
, &ds_cnt
,
354 &ds_namv
, &data
) == -1) {
355 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
359 row
= (end
- start
) / step
;
360 ret
= PyTuple_New(3);
361 range_tup
= PyTuple_New(3);
362 dsnam_tup
= PyTuple_New(ds_cnt
);
363 data_list
= PyList_New(row
);
365 PyTuple_SET_ITEM(ret
, 0, range_tup
);
366 PyTuple_SET_ITEM(ret
, 1, dsnam_tup
);
367 PyTuple_SET_ITEM(ret
, 2, data_list
);
371 PyTuple_SET_ITEM(range_tup
, 0, PyRRD_Int_FromLong((long) start
));
372 PyTuple_SET_ITEM(range_tup
, 1, PyRRD_Int_FromLong((long) end
));
373 PyTuple_SET_ITEM(range_tup
, 2, PyRRD_Int_FromLong((long) step
));
375 for (i
= 0; i
< ds_cnt
; i
++)
376 PyTuple_SET_ITEM(dsnam_tup
, i
, PyRRD_String_FromString(ds_namv
[i
]));
378 for (i
= 0; i
< row
; i
++) {
379 t
= PyTuple_New(ds_cnt
);
380 PyList_SET_ITEM(data_list
, i
, t
);
382 for (j
= 0; j
< ds_cnt
; j
++) {
385 PyTuple_SET_ITEM(t
, j
, Py_None
);
388 PyTuple_SET_ITEM(t
, j
, PyFloat_FromDouble((double) dv
));
392 for (i
= 0; i
< ds_cnt
; i
++)
393 rrd_freemem(ds_namv
[i
]);
395 rrd_freemem(ds_namv
);
403 static char _rrdtool_flushcached__doc__
[] = "Flush RRD files from memory.\n\n\
404 Usage: flushcached(args..)\n\
406 [-d|--daemon address]\n\
409 Full documentation can be found at:\n\
410 http://oss.oetiker.ch/rrdtool/doc/rrdflushcached.en.html";
413 _rrdtool_flushcached(PyObject
*self
, PyObject
*args
)
417 if (convert_args("flushcached", args
) == -1)
420 if (rrd_flushcached(rrdtool_argc
, rrdtool_argv
) != 0) {
421 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
433 #ifdef HAVE_RRD_GRAPH
434 static char _rrdtool_graph__doc__
[] = "Create a graph based on one or more " \
436 Usage: graph(args..)\n\
439 [-s|--start start]\n\
442 [-t|--title string]\n\
443 [-v|--vertical-label string]\n\
444 [-w|--width pixels]\n\
445 [-h|--height pixels]\n\
447 [-D|--full-size-mode]\n\
448 [-u|--upper-limit value]\n\
449 [-l|--lower-limit value]\n\
451 [-A|--alt-autoscale]\n\
452 [-J|--alt-autoscale-min]\n\
453 [-M|--alt-autoscale-max]\n\
455 [-x|--x-grid (GTM:GST:MTM:MST:LTM:LST:LPR:LFM|none)]\n\
456 [-y|--y-grid (grid step:label factor|none)]\n\
457 [--week-fmt strftime format string]\n\
458 [--left-axis-formatter formatter-name]\n\
459 [--left-axis-format format-string]\n\
461 [-o|--logarithmic]\n\
462 [-X|--units-exponent value]\n\
463 [-L|--units-length value]\n\
465 [--right-axis scale:shift]\n\
466 [--right-axis-label label]\n\
467 [--right-axis-format format-string]\n\
469 [-F|--force-rules-legend]\n\
470 [--legend-position=(north|south|west|east)]\n\
471 [--legend-direction=(topdown|bottomup)]\n\
473 [-d|--daemon address]\n\
474 [-f|--imginfo printfstr]\n\
475 [-c|--color COLORTAG#rrggbb[aa]]\n\
476 [--grid-dash on:off]\n\
478 [--dynamic-labels]\n\
479 [-m|--zoom factor]\n\
480 [-n|--font FONTTAG:size:[font]]\n\
481 [-R|--font-render-mode {normal,light,mono}]\n\
482 [-B|--font-smoothing-threshold size]\n\
483 [-P|--pango-markup]\n\
484 [-G|--graph-render-mode {normal,mono}]\n\
486 [-a|--imgformat {PNG,SVG,EPS,PDF,XML,XMLENUM,JSON,JSONTIME,CSV,TSV,SSV}]\n\
488 [-T|--tabwidth value]\n\
490 [-W|--watermark string]\n\
491 [-Z|--use-nan-for-all-missing-data]\n\
492 DEF:vname=rrdfile:ds-name:CF[:step=step][:start=time][:end=time]\n\
493 CDEF:vname=RPN expression\n\
494 VDEF=vname:RPN expression\n\n\
495 Full documentation can be found at:\n\
496 http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html";
499 _rrdtool_graph(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
506 if (convert_args("graph", args
) == -1)
509 if (rrd_graph(rrdtool_argc
, rrdtool_argv
, &calcpr
, &xsize
, &ysize
, NULL
,
510 &ymin
, &ymax
) == -1) {
511 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
515 ret
= PyTuple_New(3);
517 PyTuple_SET_ITEM(ret
, 0, PyRRD_Int_FromLong((long) xsize
));
518 PyTuple_SET_ITEM(ret
, 1, PyRRD_Int_FromLong((long) ysize
));
524 PyTuple_SET_ITEM(ret
, 2, e
);
526 for (i
= 0; calcpr
[i
]; i
++) {
527 t
= PyRRD_String_FromString(calcpr
[i
]);
530 rrd_freemem(calcpr
[i
]);
534 PyTuple_SET_ITEM(ret
, 2, Py_None
);
542 static char _rrdtool_graphv__doc__
[] = "Create a graph based on one or more " \
543 "RRDs and return data in RRDtool info format.\n\n\
544 This function works the same way as 'graph', but will return a info\n\
545 dictionary instead of None.\n\n\
546 Full documentation can be found at (graphv section):\n\
547 http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html";
550 _rrdtool_graphv(PyObject
*self
, PyObject
*args
)
555 if (convert_args("graphv", args
) == -1)
558 if ((data
= rrd_graph_v(rrdtool_argc
, rrdtool_argv
)) == NULL
) {
559 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
563 ret
= _rrdtool_util_info2dict(data
);
571 static char _rrdtool_xport__doc__
[] = "Dictionary representation of data " \
572 "stored in RRDs.\n\n\
573 Usage: xport(args..)\n\
575 [-s[--start seconds]\n\
576 [-e|--end seconds]\n\
577 [-m|--maxrows rows]\n\
581 [--daemon address]\n\
582 [DEF:vname=rrd:ds-name:CF]\n\
583 [CDEF:vname=rpn-expression]\n\
584 [XPORT:vname[:legend]]\n\n\
585 Full documentation can be found at:\n\
586 http://oss.oetiker.ch/rrdtool/doc/rrdxport.en.html";
589 _rrdtool_xport(PyObject
*self
, PyObject
*args
)
595 unsigned long step
, col_cnt
;
596 rrd_value_t
*data
, *datai
;
598 if (convert_args("xport", args
) == -1)
601 if (rrd_xport(rrdtool_argc
, rrdtool_argv
, &xsize
, &start
, &end
, &step
,
602 &col_cnt
, &legend_v
, &data
) == -1) {
603 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
607 PyObject
*meta_dict
, *data_list
, *legend_list
, *t
;
609 unsigned long i
, j
, row_cnt
= (end
- start
) / step
;
612 meta_dict
= PyDict_New();
613 legend_list
= PyList_New(col_cnt
);
614 data_list
= PyList_New(row_cnt
);
616 PyDict_SetItem(ret
, PyRRD_String_FromString("meta"), meta_dict
);
617 PyDict_SetItem(ret
, PyRRD_String_FromString("data"), data_list
);
621 PyDict_SetItem(meta_dict
,
622 PyRRD_String_FromString("start"),
623 PyRRD_Int_FromLong((long) start
));
624 PyDict_SetItem(meta_dict
,
625 PyRRD_String_FromString("end"),
626 PyRRD_Int_FromLong((long) end
));
627 PyDict_SetItem(meta_dict
,
628 PyRRD_String_FromString("step"),
629 PyRRD_Int_FromLong((long) step
));
630 PyDict_SetItem(meta_dict
,
631 PyRRD_String_FromString("rows"),
632 PyRRD_Int_FromLong((long) row_cnt
));
633 PyDict_SetItem(meta_dict
,
634 PyRRD_String_FromString("columns"),
635 PyRRD_Int_FromLong((long) col_cnt
));
636 PyDict_SetItem(meta_dict
,
637 PyRRD_String_FromString("legend"),
640 for (i
= 0; i
< col_cnt
; i
++)
641 PyList_SET_ITEM(legend_list
, i
, PyRRD_String_FromString(legend_v
[i
]));
643 for (i
= 0; i
< row_cnt
; i
++) {
644 t
= PyTuple_New(col_cnt
);
645 PyList_SET_ITEM(data_list
, i
, t
);
647 for (j
= 0; j
< col_cnt
; j
++) {
651 PyTuple_SET_ITEM(t
, j
, Py_None
);
654 PyTuple_SET_ITEM(t
, j
, PyFloat_FromDouble((double) dv
));
659 for (i
= 0; i
< col_cnt
; i
++)
660 rrd_freemem(legend_v
[i
]);
662 rrd_freemem(legend_v
);
670 #endif /* HAVE_RRD_GRAPH */
672 static char _rrdtool_tune__doc__
[] = "Modify some basic properties of a " \
673 "Round Robin Database.\n\n\
674 Usage: tune(args..)\n\
677 [-h|--heartbeat ds-name:heartbeat]\n\
678 [-i|--minimum ds-name:min]\n\
679 [-a|--maximum ds-name:max]\n\
680 [-d|--data-source-type ds-name:DST]\n\
681 [-r|--data-source-rename old-name:new-name]\n\n\
682 Full documentation can be found at:\n\
683 http://oss.oetiker.ch/rrdtool/doc/rrdtune.en.html";
686 _rrdtool_tune(PyObject
*self
, PyObject
*args
)
690 if (convert_args("tune", args
) == -1)
693 if (rrd_tune(rrdtool_argc
, rrdtool_argv
) == -1) {
694 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
706 static char _rrdtool_first__doc__
[] = "Get the first UNIX timestamp of the "\
707 "first data sample in an Round Robin Database.\n\n\
708 Usage: first(args..)\n\
711 [--rraindex number]\n\
712 [-d|--daemon address]\n\n\
713 Full documentation can be found at:\n\
714 http://oss.oetiker.ch/rrdtool/doc/rrdfirst.en.html";
717 _rrdtool_first(PyObject
*self
, PyObject
*args
)
722 if (convert_args("first", args
) == -1)
725 if ((ts
= rrd_first(rrdtool_argc
, rrdtool_argv
)) == -1) {
726 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
730 ret
= PyRRD_Int_FromLong((long) ts
);
736 static char _rrdtool_last__doc__
[] = "Get the UNIX timestamp of the most "\
737 "recent data sample in an Round Robin Database.\n\n\
738 Usage: last(args..)\n\
741 [-d|--daemon address]\n\n\
742 Full documentation can be found at:\n\
743 http://oss.oetiker.ch/rrdtool/doc/rrdlast.en.html";
746 _rrdtool_last(PyObject
*self
, PyObject
*args
)
751 if (convert_args("last", args
) == -1)
754 if ((ts
= rrd_last(rrdtool_argc
, rrdtool_argv
)) == -1) {
755 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
759 ret
= PyRRD_Int_FromLong((long) ts
);
765 static char _rrdtool_resize__doc__
[] = "Modify the number of rows in a "\
766 "Round Robin Database.\n\n\
767 Usage: resize(args..)\n\
773 Full documentation can be found at:\n\
774 http://oss.oetiker.ch/rrdtool/doc/rrdlast.en.html";
777 _rrdtool_resize(PyObject
*self
, PyObject
*args
)
782 if (convert_args("resize", args
) == -1)
785 if ((ts
= rrd_resize(rrdtool_argc
, rrdtool_argv
)) == -1) {
786 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
798 static char _rrdtool_info__doc__
[] = "Extract header information from an "\
799 "Round Robin Database.\n\n\
800 Usage: info(filename, ...)\n\
803 [-d|--daemon address]\n\
805 Full documentation can be found at:\n\
806 http://oss.oetiker.ch/rrdtool/doc/rrdinfo.en.html";
809 _rrdtool_info(PyObject
*self
, PyObject
*args
)
814 if (convert_args("info", args
) == -1)
817 if ((data
= rrd_info(rrdtool_argc
, rrdtool_argv
)) == NULL
) {
818 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
822 ret
= _rrdtool_util_info2dict(data
);
830 static char _rrdtool_lastupdate__doc__
[] = "Returns datetime and value stored "\
831 "for each datum in the most recent update of an RRD.\n\n\
832 Usage: lastupdate(filename, ...)\n\
835 [-d|--daemon address]\n\n\
836 Full documentation can be found at:\n\
837 http://oss.oetiker.ch/rrdtool/doc/rrdlastupdate.en.html";
840 _rrdtool_lastupdate(PyObject
*self
, PyObject
*args
)
842 PyObject
*ret
, *ds_dict
;
846 char **ds_names
, **last_ds
;
847 unsigned long ds_cnt
, i
;
849 if (convert_args("lastupdate", args
) == -1)
851 else if (rrdtool_argc
< 2) {
852 PyErr_SetString(rrdtool_ProgrammingError
, "Required arguments missing");
856 printf("Using '%s'\n", rrdtool_argv
[1]);
858 status
= rrd_lastupdate_r(rrdtool_argv
[1],
865 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
869 /* convert last_update to Python datetime object */
870 struct tm
*ts
= localtime(&last_update
);
872 ds_dict
= PyDict_New();
874 PyDict_SetItemString(ret
,
875 PyRRD_String_FromString("date"),
876 PyDateTime_FromDateAndTime(
884 PyDict_SetItemString(ret
,
885 PyRRD_String_FromString("ds"),
888 for (i
= 0; i
< ds_cnt
; i
++) {
889 PyDict_SetItemString(ds_dict
,
890 PyRRD_String_FromString(ds_names
[i
]),
891 PyLong_FromString(last_ds
[i
], NULL
, 10));
906 static char _rrdtool_lib_version__doc__
[] = "Get the version this binding "\
907 "was compiled against.";
910 * Returns a str object that contains the librrd version.
912 * @return librrd version (Python str object)
915 _rrdtool_lib_version(PyObject
*self
, PyObject
*args
)
917 return PyRRD_String_FromString(rrd_strversion());
921 static PyMethodDef rrdtool_methods
[] = {
922 {"create", (PyCFunction
)_rrdtool_create
,
923 METH_VARARGS
, _rrdtool_create__doc__
},
924 {"dump", (PyCFunction
)_rrdtool_dump
,
925 METH_VARARGS
, _rrdtool_dump__doc__
},
926 {"update", (PyCFunction
)_rrdtool_update
,
927 METH_VARARGS
, _rrdtool_update__doc__
},
928 {"updatev", (PyCFunction
)_rrdtool_updatev
,
929 METH_VARARGS
, _rrdtool_updatev__doc__
},
930 {"fetch", (PyCFunction
)_rrdtool_fetch
,
931 METH_VARARGS
, _rrdtool_fetch__doc__
},
932 {"flushcached", (PyCFunction
)_rrdtool_flushcached
,
933 METH_VARARGS
, _rrdtool_flushcached__doc__
},
934 #ifdef HAVE_RRD_GRAPH
935 {"graph", (PyCFunction
)_rrdtool_graph
,
936 METH_VARARGS
, _rrdtool_graph__doc__
},
937 {"graphv", (PyCFunction
)_rrdtool_graphv
,
938 METH_VARARGS
, _rrdtool_graphv__doc__
},
939 {"xport", (PyCFunction
)_rrdtool_xport
,
940 METH_VARARGS
, _rrdtool_xport__doc__
},
942 {"tune", (PyCFunction
)_rrdtool_tune
,
943 METH_VARARGS
, _rrdtool_tune__doc__
},
944 {"first", (PyCFunction
)_rrdtool_first
,
945 METH_VARARGS
, _rrdtool_first__doc__
},
946 {"last", (PyCFunction
)_rrdtool_last
,
947 METH_VARARGS
, _rrdtool_last__doc__
},
948 {"resize", (PyCFunction
)_rrdtool_resize
,
949 METH_VARARGS
, _rrdtool_resize__doc__
},
950 {"info", (PyCFunction
)_rrdtool_info
,
951 METH_VARARGS
, _rrdtool_info__doc__
},
952 {"lastupdate", (PyCFunction
)_rrdtool_lastupdate
,
953 METH_VARARGS
, _rrdtool_lastupdate__doc__
},
954 {"lib_version", (PyCFunction
)_rrdtool_lib_version
,
955 METH_VARARGS
, _rrdtool_lib_version__doc__
},
956 {NULL
, NULL
, 0, NULL
}
959 /** Library init function. */
961 static struct PyModuleDef rrdtoolmodule
= {
962 PyModuleDef_HEAD_INIT
,
964 "rrdtool bindings for Python",
981 PyDateTime_IMPORT
; /* initialize PyDateTime_ functions */
984 m
= PyModule_Create(&rrdtoolmodule
);
986 m
= Py_InitModule3("rrdtool",
988 "rrdtool bindings for Python");
998 rrdtool_ProgrammingError
= PyErr_NewException("rrdtool.ProgrammingError",
1000 Py_INCREF(rrdtool_ProgrammingError
);
1001 PyModule_AddObject(m
, "ProgrammingError", rrdtool_ProgrammingError
);
1003 rrdtool_OperationalError
= PyErr_NewException("rrdtool.OperationalError",
1005 Py_INCREF(rrdtool_OperationalError
);
1006 PyModule_AddObject(m
, "OperationalError", rrdtool_OperationalError
);
1007 PyModule_AddObject(m
, "__version__", PyRRD_String_FromString(_version
));