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)
37 #define PyRRD_Int_FromString(x, y, z) PyLong_FromString(x,y,z)
39 #define PyRRD_String_Check(x) PyString_Check(x)
40 #define PyRRD_String_FromString(x) PyString_FromString(x)
41 #define PyRRD_String_AS_STRING(x) PyString_AS_STRING(x)
42 #define PyRRD_String_FromStringAndSize(x, y) PyString_FromStringAndSize(x, y)
43 #define PyRRD_Int_FromLong(x) PyInt_FromLong(x)
44 #define PyRRD_Int_FromString(x, y, z) PyInt_FromString(x,y,z)
47 /** Binding version. */
48 static const char *_version
= "0.1.2";
50 /** Exception types. */
51 static PyObject
*rrdtool_OperationalError
;
52 static PyObject
*rrdtool_ProgrammingError
;
54 static char **rrdtool_argv
= NULL
;
55 static int rrdtool_argc
= 0;
57 /* extern getopt state */
58 extern int optind
, opterr
;
62 * Helper function to convert Python objects into a representation that the
63 * rrdtool functions can work with.
65 * @param command RRDtool command name
66 * @param args Command arguments
67 * @return Zero if the function succeeds, otherwise -1
70 convert_args(char *command
, PyObject
*args
)
73 int i
, j
, args_count
, argv_count
, element_count
;
75 argv_count
= element_count
= 0;
76 args_count
= PyTuple_Size(args
);
78 for (i
= 0; i
< args_count
; i
++) {
79 o
= PyTuple_GET_ITEM(args
, i
);
81 if (PyRRD_String_Check(o
))
83 else if (PyList_CheckExact(o
))
84 element_count
+= PyList_Size(o
);
86 PyErr_Format(PyExc_TypeError
,
87 "Argument %d must be str or a list of str", i
);
92 rrdtool_argv
= PyMem_New(char *, element_count
+ 1);
94 if (rrdtool_argv
== NULL
)
97 for (i
= 0; i
< args_count
; i
++) {
98 o
= PyTuple_GET_ITEM(args
, i
);
100 if (PyRRD_String_Check(o
))
101 rrdtool_argv
[++argv_count
] = PyRRD_String_AS_STRING(o
);
102 else if (PyList_CheckExact(o
)) {
103 for (j
= 0; j
< PyList_Size(o
); j
++) {
104 lo
= PyList_GetItem(o
, j
);
106 if (PyRRD_String_Check(lo
))
107 rrdtool_argv
[++argv_count
] = PyRRD_String_AS_STRING(lo
);
109 PyMem_Del(rrdtool_argv
);
110 PyErr_Format(PyExc_TypeError
,
111 "Element %d in argument %d must be str", j
, i
);
116 PyMem_Del(rrdtool_argv
);
117 PyErr_Format(rrdtool_ProgrammingError
,
118 "Argument %d must be str or list of str", i
);
123 rrdtool_argv
[0] = command
;
124 rrdtool_argc
= element_count
+ 1;
126 /* reset getopt state */
133 * Destroy argument vector.
138 PyMem_Del(rrdtool_argv
);
143 * Convert RRDtool info to dict.
145 * @param data RRDtool info object
146 * @return Python dict object
149 _rrdtool_util_info2dict(const rrd_info_t
*data
)
151 PyObject
*dict
, *val
;
158 switch (data
->type
) {
160 if (isnan(data
->value
.u_val
)) {
164 PyFloat_FromDouble(data
->value
.u_val
);
168 val
= PyLong_FromUnsignedLong(data
->value
.u_cnt
);
172 val
= PyLong_FromLong(data
->value
.u_int
);
176 val
= PyRRD_String_FromString(data
->value
.u_str
);
180 val
= PyRRD_String_FromStringAndSize(
181 (char *)data
->value
.u_blo
.ptr
,
182 data
->value
.u_blo
.size
);
189 PyDict_SetItemString(dict
, data
->key
, val
);
199 static char _rrdtool_create__doc__
[] = "Create a new Round Robin Database.\n\n\
200 Usage: create(args...)\n\
203 [-b|--start start time]\n\
205 [-t|--template temolate-file]\n\
206 [-r|--source source-file]\n\
207 [-O|--no-overwrite]\n\
208 [-d|--daemon address]\n\
209 [DS:ds-name[=mapped-ds-name[source-index]]:DST:heartbeat:min:max]\n\
210 [RRA:CF:xff:steps:rows]\n\n\
211 Full documentation can be found at:\n\
212 http://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html";
215 _rrdtool_create(PyObject
*self
, PyObject
*args
)
219 if (convert_args("create", args
) == -1)
222 if (rrd_create(rrdtool_argc
, rrdtool_argv
) == -1) {
223 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
235 static char _rrdtool_dump__doc__
[] = "Dump an RRD to XML.\n\n\
236 Usage: dump(args..)\n\
238 [-h|--header {none,xsd,dtd}\n\
240 [-d|--daemon address]\n\
243 Full documentation can be found at:\n\
244 http://oss.oetiker.ch/rrdtool/doc/rrddump.en.html";
247 _rrdtool_dump(PyObject
*self
, PyObject
*args
)
251 if (convert_args("dump", args
) == -1)
254 if (rrd_dump(rrdtool_argc
, rrdtool_argv
) != 0) {
255 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
267 static char _rrdtool_update__doc__
[] = "Store a new set of values into\
269 Usage: update(args..)\n\
272 [--template|-t ds-name[:ds-name]...]\n\
273 N|timestamp:value[:value...]\n\
274 [timestamp:value[:value...] ...]\n\n\
275 Full documentation can be found at:\n\
276 http://oss.oetiker.ch/rrdtool/doc/rrdupdate.en.html";
279 _rrdtool_update(PyObject
*self
, PyObject
*args
)
283 if (convert_args("update", args
) == -1)
286 if (rrd_update(rrdtool_argc
, rrdtool_argv
) == -1) {
287 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
299 static char _rrdtool_updatev__doc__
[] = "Store a new set of values into "\
300 "the Round Robin Database and return an info dictionary.\n\n\
301 This function works in the same manner as 'update', but will return an\n\
302 info dictionary instead of None.";
305 _rrdtool_updatev(PyObject
*self
, PyObject
*args
)
310 if (convert_args("updatev", args
) == -1)
313 if ((data
= rrd_update_v(rrdtool_argc
, rrdtool_argv
)) == NULL
) {
314 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
318 ret
= _rrdtool_util_info2dict(data
);
326 static char _rrdtool_fetch__doc__
[] = "Fetch data from an RRD.\n\n\
327 Usage: fetch(args..)\n\
331 [-r|--resolution resolution]\n\
332 [-s|--start start]\n\
334 [-a|--align-start]\n\
335 [-d|--daemon address]\n\n\
336 Full documentation can be found at:\n\
337 http://oss.oetiker.ch/rrdtool/doc/rrdfetch.en.html";
340 _rrdtool_fetch(PyObject
*self
, PyObject
*args
)
342 PyObject
*ret
, *range_tup
, *dsnam_tup
, *data_list
, *t
;
343 rrd_value_t
*data
, *datai
, dv
;
344 unsigned long step
, ds_cnt
, i
, j
, row
;
348 if (convert_args("fetch", args
) == -1)
351 if (rrd_fetch(rrdtool_argc
, rrdtool_argv
, &start
, &end
, &step
, &ds_cnt
,
352 &ds_namv
, &data
) == -1) {
353 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
357 row
= (end
- start
) / step
;
358 ret
= PyTuple_New(3);
359 range_tup
= PyTuple_New(3);
360 dsnam_tup
= PyTuple_New(ds_cnt
);
361 data_list
= PyList_New(row
);
363 PyTuple_SET_ITEM(ret
, 0, range_tup
);
364 PyTuple_SET_ITEM(ret
, 1, dsnam_tup
);
365 PyTuple_SET_ITEM(ret
, 2, data_list
);
369 PyTuple_SET_ITEM(range_tup
, 0, PyRRD_Int_FromLong((long) start
));
370 PyTuple_SET_ITEM(range_tup
, 1, PyRRD_Int_FromLong((long) end
));
371 PyTuple_SET_ITEM(range_tup
, 2, PyRRD_Int_FromLong((long) step
));
373 for (i
= 0; i
< ds_cnt
; i
++)
374 PyTuple_SET_ITEM(dsnam_tup
, i
, PyRRD_String_FromString(ds_namv
[i
]));
376 for (i
= 0; i
< row
; i
++) {
377 t
= PyTuple_New(ds_cnt
);
378 PyList_SET_ITEM(data_list
, i
, t
);
380 for (j
= 0; j
< ds_cnt
; j
++) {
383 PyTuple_SET_ITEM(t
, j
, Py_None
);
386 PyTuple_SET_ITEM(t
, j
, PyFloat_FromDouble((double) dv
));
390 for (i
= 0; i
< ds_cnt
; i
++)
391 rrd_freemem(ds_namv
[i
]);
393 rrd_freemem(ds_namv
);
401 static char _rrdtool_flushcached__doc__
[] = "Flush RRD files from memory.\n\n\
402 Usage: flushcached(args..)\n\
404 [-d|--daemon address]\n\
407 Full documentation can be found at:\n\
408 http://oss.oetiker.ch/rrdtool/doc/rrdflushcached.en.html";
411 _rrdtool_flushcached(PyObject
*self
, PyObject
*args
)
415 if (convert_args("flushcached", args
) == -1)
418 if (rrd_flushcached(rrdtool_argc
, rrdtool_argv
) != 0) {
419 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
431 #ifdef HAVE_RRD_GRAPH
432 static char _rrdtool_graph__doc__
[] = "Create a graph based on one or more " \
434 Usage: graph(args..)\n\
437 [-s|--start start]\n\
440 [-t|--title string]\n\
441 [-v|--vertical-label string]\n\
442 [-w|--width pixels]\n\
443 [-h|--height pixels]\n\
445 [-D|--full-size-mode]\n\
446 [-u|--upper-limit value]\n\
447 [-l|--lower-limit value]\n\
449 [-A|--alt-autoscale]\n\
450 [-J|--alt-autoscale-min]\n\
451 [-M|--alt-autoscale-max]\n\
453 [-x|--x-grid (GTM:GST:MTM:MST:LTM:LST:LPR:LFM|none)]\n\
454 [-y|--y-grid (grid step:label factor|none)]\n\
455 [--week-fmt strftime format string]\n\
456 [--left-axis-formatter formatter-name]\n\
457 [--left-axis-format format-string]\n\
459 [-o|--logarithmic]\n\
460 [-X|--units-exponent value]\n\
461 [-L|--units-length value]\n\
463 [--right-axis scale:shift]\n\
464 [--right-axis-label label]\n\
465 [--right-axis-format format-string]\n\
467 [-F|--force-rules-legend]\n\
468 [--legend-position=(north|south|west|east)]\n\
469 [--legend-direction=(topdown|bottomup)]\n\
471 [-d|--daemon address]\n\
472 [-f|--imginfo printfstr]\n\
473 [-c|--color COLORTAG#rrggbb[aa]]\n\
474 [--grid-dash on:off]\n\
476 [--dynamic-labels]\n\
477 [-m|--zoom factor]\n\
478 [-n|--font FONTTAG:size:[font]]\n\
479 [-R|--font-render-mode {normal,light,mono}]\n\
480 [-B|--font-smoothing-threshold size]\n\
481 [-P|--pango-markup]\n\
482 [-G|--graph-render-mode {normal,mono}]\n\
484 [-a|--imgformat {PNG,SVG,EPS,PDF,XML,XMLENUM,JSON,JSONTIME,CSV,TSV,SSV}]\n\
486 [-T|--tabwidth value]\n\
488 [-W|--watermark string]\n\
489 [-Z|--use-nan-for-all-missing-data]\n\
490 DEF:vname=rrdfile:ds-name:CF[:step=step][:start=time][:end=time]\n\
491 CDEF:vname=RPN expression\n\
492 VDEF=vname:RPN expression\n\n\
493 Full documentation can be found at:\n\
494 http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html";
497 _rrdtool_graph(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
504 if (convert_args("graph", args
) == -1)
507 if (rrd_graph(rrdtool_argc
, rrdtool_argv
, &calcpr
, &xsize
, &ysize
, NULL
,
508 &ymin
, &ymax
) == -1) {
509 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
513 ret
= PyTuple_New(3);
515 PyTuple_SET_ITEM(ret
, 0, PyRRD_Int_FromLong((long) xsize
));
516 PyTuple_SET_ITEM(ret
, 1, PyRRD_Int_FromLong((long) ysize
));
522 PyTuple_SET_ITEM(ret
, 2, e
);
524 for (i
= 0; calcpr
[i
]; i
++) {
525 t
= PyRRD_String_FromString(calcpr
[i
]);
528 rrd_freemem(calcpr
[i
]);
532 PyTuple_SET_ITEM(ret
, 2, Py_None
);
540 static char _rrdtool_graphv__doc__
[] = "Create a graph based on one or more " \
541 "RRDs and return data in RRDtool info format.\n\n\
542 This function works the same way as 'graph', but will return a info\n\
543 dictionary instead of None.\n\n\
544 Full documentation can be found at (graphv section):\n\
545 http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html";
548 _rrdtool_graphv(PyObject
*self
, PyObject
*args
)
553 if (convert_args("graphv", args
) == -1)
556 if ((data
= rrd_graph_v(rrdtool_argc
, rrdtool_argv
)) == NULL
) {
557 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
561 ret
= _rrdtool_util_info2dict(data
);
569 static char _rrdtool_xport__doc__
[] = "Dictionary representation of data " \
570 "stored in RRDs.\n\n\
571 Usage: xport(args..)\n\
573 [-s[--start seconds]\n\
574 [-e|--end seconds]\n\
575 [-m|--maxrows rows]\n\
579 [--daemon address]\n\
580 [DEF:vname=rrd:ds-name:CF]\n\
581 [CDEF:vname=rpn-expression]\n\
582 [XPORT:vname[:legend]]\n\n\
583 Full documentation can be found at:\n\
584 http://oss.oetiker.ch/rrdtool/doc/rrdxport.en.html";
587 _rrdtool_xport(PyObject
*self
, PyObject
*args
)
593 unsigned long step
, col_cnt
;
594 rrd_value_t
*data
, *datai
;
596 if (convert_args("xport", args
) == -1)
599 if (rrd_xport(rrdtool_argc
, rrdtool_argv
, &xsize
, &start
, &end
, &step
,
600 &col_cnt
, &legend_v
, &data
) == -1) {
601 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
605 PyObject
*meta_dict
, *data_list
, *legend_list
, *t
;
607 unsigned long i
, j
, row_cnt
= (end
- start
) / step
;
610 meta_dict
= PyDict_New();
611 legend_list
= PyList_New(col_cnt
);
612 data_list
= PyList_New(row_cnt
);
614 PyDict_SetItem(ret
, PyRRD_String_FromString("meta"), meta_dict
);
615 PyDict_SetItem(ret
, PyRRD_String_FromString("data"), data_list
);
619 PyDict_SetItem(meta_dict
,
620 PyRRD_String_FromString("start"),
621 PyRRD_Int_FromLong((long) start
));
622 PyDict_SetItem(meta_dict
,
623 PyRRD_String_FromString("end"),
624 PyRRD_Int_FromLong((long) end
));
625 PyDict_SetItem(meta_dict
,
626 PyRRD_String_FromString("step"),
627 PyRRD_Int_FromLong((long) step
));
628 PyDict_SetItem(meta_dict
,
629 PyRRD_String_FromString("rows"),
630 PyRRD_Int_FromLong((long) row_cnt
));
631 PyDict_SetItem(meta_dict
,
632 PyRRD_String_FromString("columns"),
633 PyRRD_Int_FromLong((long) col_cnt
));
634 PyDict_SetItem(meta_dict
,
635 PyRRD_String_FromString("legend"),
638 for (i
= 0; i
< col_cnt
; i
++)
639 PyList_SET_ITEM(legend_list
, i
, PyRRD_String_FromString(legend_v
[i
]));
641 for (i
= 0; i
< row_cnt
; i
++) {
642 t
= PyTuple_New(col_cnt
);
643 PyList_SET_ITEM(data_list
, i
, t
);
645 for (j
= 0; j
< col_cnt
; j
++) {
649 PyTuple_SET_ITEM(t
, j
, Py_None
);
652 PyTuple_SET_ITEM(t
, j
, PyFloat_FromDouble((double) dv
));
657 for (i
= 0; i
< col_cnt
; i
++)
658 rrd_freemem(legend_v
[i
]);
660 rrd_freemem(legend_v
);
668 #endif /* HAVE_RRD_GRAPH */
670 static char _rrdtool_tune__doc__
[] = "Modify some basic properties of a " \
671 "Round Robin Database.\n\n\
672 Usage: tune(args..)\n\
675 [-h|--heartbeat ds-name:heartbeat]\n\
676 [-i|--minimum ds-name:min]\n\
677 [-a|--maximum ds-name:max]\n\
678 [-d|--data-source-type ds-name:DST]\n\
679 [-r|--data-source-rename old-name:new-name]\n\n\
680 Full documentation can be found at:\n\
681 http://oss.oetiker.ch/rrdtool/doc/rrdtune.en.html";
684 _rrdtool_tune(PyObject
*self
, PyObject
*args
)
688 if (convert_args("tune", args
) == -1)
691 if (rrd_tune(rrdtool_argc
, rrdtool_argv
) == -1) {
692 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
704 static char _rrdtool_first__doc__
[] = "Get the first UNIX timestamp of the "\
705 "first data sample in an Round Robin Database.\n\n\
706 Usage: first(args..)\n\
709 [--rraindex number]\n\
710 [-d|--daemon address]\n\n\
711 Full documentation can be found at:\n\
712 http://oss.oetiker.ch/rrdtool/doc/rrdfirst.en.html";
715 _rrdtool_first(PyObject
*self
, PyObject
*args
)
720 if (convert_args("first", args
) == -1)
723 if ((ts
= rrd_first(rrdtool_argc
, rrdtool_argv
)) == -1) {
724 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
728 ret
= PyRRD_Int_FromLong((long) ts
);
734 static char _rrdtool_last__doc__
[] = "Get the UNIX timestamp of the most "\
735 "recent data sample in an Round Robin Database.\n\n\
736 Usage: last(args..)\n\
739 [-d|--daemon address]\n\n\
740 Full documentation can be found at:\n\
741 http://oss.oetiker.ch/rrdtool/doc/rrdlast.en.html";
744 _rrdtool_last(PyObject
*self
, PyObject
*args
)
749 if (convert_args("last", args
) == -1)
752 if ((ts
= rrd_last(rrdtool_argc
, rrdtool_argv
)) == -1) {
753 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
757 ret
= PyRRD_Int_FromLong((long) ts
);
763 static char _rrdtool_resize__doc__
[] = "Modify the number of rows in a "\
764 "Round Robin Database.\n\n\
765 Usage: resize(args..)\n\
771 Full documentation can be found at:\n\
772 http://oss.oetiker.ch/rrdtool/doc/rrdlast.en.html";
775 _rrdtool_resize(PyObject
*self
, PyObject
*args
)
780 if (convert_args("resize", args
) == -1)
783 if ((ts
= rrd_resize(rrdtool_argc
, rrdtool_argv
)) == -1) {
784 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
796 static char _rrdtool_info__doc__
[] = "Extract header information from an "\
797 "Round Robin Database.\n\n\
798 Usage: info(filename, ...)\n\
801 [-d|--daemon address]\n\
803 Full documentation can be found at:\n\
804 http://oss.oetiker.ch/rrdtool/doc/rrdinfo.en.html";
807 _rrdtool_info(PyObject
*self
, PyObject
*args
)
812 if (convert_args("info", args
) == -1)
815 if ((data
= rrd_info(rrdtool_argc
, rrdtool_argv
)) == NULL
) {
816 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
820 ret
= _rrdtool_util_info2dict(data
);
828 static char _rrdtool_lastupdate__doc__
[] = "Returns datetime and value stored "\
829 "for each datum in the most recent update of an RRD.\n\n\
830 Usage: lastupdate(filename, ...)\n\
833 [-d|--daemon address]\n\n\
834 Full documentation can be found at:\n\
835 http://oss.oetiker.ch/rrdtool/doc/rrdlastupdate.en.html";
838 _rrdtool_lastupdate(PyObject
*self
, PyObject
*args
)
840 PyObject
*ret
, *ds_dict
;
844 char **ds_names
, **last_ds
;
845 unsigned long ds_cnt
, i
;
847 if (convert_args("lastupdate", args
) == -1)
849 else if (rrdtool_argc
< 2) {
850 PyErr_SetString(rrdtool_ProgrammingError
, "Missing filename argument");
854 status
= rrd_lastupdate_r(rrdtool_argv
[1],
861 PyErr_SetString(rrdtool_OperationalError
, rrd_get_error());
865 /* convert last_update to Python datetime object */
866 struct tm
*ts
= localtime(&last_update
);
868 ds_dict
= PyDict_New();
870 PyDict_SetItemString(ret
,
872 PyDateTime_FromDateAndTime(
880 PyDict_SetItemString(ret
, "ds", ds_dict
);
882 for (i
= 0; i
< ds_cnt
; i
++) {
883 PyDict_SetItemString(ds_dict
,
885 PyRRD_Int_FromString(last_ds
[i
], NULL
, 10));
900 static char _rrdtool_lib_version__doc__
[] = "Get the version this binding "\
901 "was compiled against.";
904 * Returns a str object that contains the librrd version.
906 * @return librrd version (Python str object)
909 _rrdtool_lib_version(PyObject
*self
, PyObject
*args
)
911 return PyRRD_String_FromString(rrd_strversion());
915 static PyMethodDef rrdtool_methods
[] = {
916 {"create", (PyCFunction
)_rrdtool_create
,
917 METH_VARARGS
, _rrdtool_create__doc__
},
918 {"dump", (PyCFunction
)_rrdtool_dump
,
919 METH_VARARGS
, _rrdtool_dump__doc__
},
920 {"update", (PyCFunction
)_rrdtool_update
,
921 METH_VARARGS
, _rrdtool_update__doc__
},
922 {"updatev", (PyCFunction
)_rrdtool_updatev
,
923 METH_VARARGS
, _rrdtool_updatev__doc__
},
924 {"fetch", (PyCFunction
)_rrdtool_fetch
,
925 METH_VARARGS
, _rrdtool_fetch__doc__
},
926 {"flushcached", (PyCFunction
)_rrdtool_flushcached
,
927 METH_VARARGS
, _rrdtool_flushcached__doc__
},
928 #ifdef HAVE_RRD_GRAPH
929 {"graph", (PyCFunction
)_rrdtool_graph
,
930 METH_VARARGS
, _rrdtool_graph__doc__
},
931 {"graphv", (PyCFunction
)_rrdtool_graphv
,
932 METH_VARARGS
, _rrdtool_graphv__doc__
},
933 {"xport", (PyCFunction
)_rrdtool_xport
,
934 METH_VARARGS
, _rrdtool_xport__doc__
},
936 {"tune", (PyCFunction
)_rrdtool_tune
,
937 METH_VARARGS
, _rrdtool_tune__doc__
},
938 {"first", (PyCFunction
)_rrdtool_first
,
939 METH_VARARGS
, _rrdtool_first__doc__
},
940 {"last", (PyCFunction
)_rrdtool_last
,
941 METH_VARARGS
, _rrdtool_last__doc__
},
942 {"resize", (PyCFunction
)_rrdtool_resize
,
943 METH_VARARGS
, _rrdtool_resize__doc__
},
944 {"info", (PyCFunction
)_rrdtool_info
,
945 METH_VARARGS
, _rrdtool_info__doc__
},
946 {"lastupdate", (PyCFunction
)_rrdtool_lastupdate
,
947 METH_VARARGS
, _rrdtool_lastupdate__doc__
},
948 {"lib_version", (PyCFunction
)_rrdtool_lib_version
,
949 METH_VARARGS
, _rrdtool_lib_version__doc__
},
950 {NULL
, NULL
, 0, NULL
}
953 /** Library init function. */
955 static struct PyModuleDef rrdtoolmodule
= {
956 PyModuleDef_HEAD_INIT
,
958 "rrdtool bindings for Python",
975 PyDateTime_IMPORT
; /* initialize PyDateTime_ functions */
978 m
= PyModule_Create(&rrdtoolmodule
);
980 m
= Py_InitModule3("rrdtool",
982 "rrdtool bindings for Python");
992 rrdtool_ProgrammingError
= PyErr_NewException("rrdtool.ProgrammingError",
994 Py_INCREF(rrdtool_ProgrammingError
);
995 PyModule_AddObject(m
, "ProgrammingError", rrdtool_ProgrammingError
);
997 rrdtool_OperationalError
= PyErr_NewException("rrdtool.OperationalError",
999 Py_INCREF(rrdtool_OperationalError
);
1000 PyModule_AddObject(m
, "OperationalError", rrdtool_OperationalError
);
1001 PyModule_AddObject(m
, "__version__", PyRRD_String_FromString(_version
));