]>
Commit | Line | Data |
---|---|---|
225c0910 | 1 | #!/usr/bin/env python |
b4570f2a CJ |
2 | # -*- coding: utf-8 -*- |
3 | # | |
225c0910 | 4 | # python-rrdtool, rrdtool bindings for Python. |
b4570f2a CJ |
5 | # Based on the rrdtool Python bindings for Python 2 from |
6 | # Hye-Shik Chang <perky@fallin.lv>. | |
7 | # | |
8 | # Copyright 2012 Christian Jurk <commx@commx.ws> | |
9 | # | |
10 | # This program is free software; you can redistribute it and/or modify | |
275aa95d CJ |
11 | # it under the terms of the GNU Lesser General Public License as |
12 | # published by the Free Software Foundation; either version 3 of the | |
13 | # License, or (at your option) any later version. | |
b4570f2a CJ |
14 | # |
15 | # This program is distributed in the hope that it will be useful, | |
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | # GNU General Public License for more details. | |
19 | # | |
275aa95d | 20 | # You should have received a copy of the GNU Lesser General Public License |
b4570f2a CJ |
21 | # along with this program; if not, write to the Free Software |
22 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
23 | # MA 02110-1301, USA. | |
24 | # | |
25 | # | |
26 | ||
b4570f2a CJ |
27 | import os |
28 | import rrdtool | |
225c0910 CJ |
29 | |
30 | from datetime import datetime | |
31 | from io import BytesIO | |
b4570f2a CJ |
32 | from time import mktime |
33 | ||
34 | def create(filename, *args): | |
35 | "Create a Round Robin Database and return a RRD object on success." | |
36 | rrdtool.create(filename, *args) | |
37 | ||
38 | if not os.access(filename, os.F_OK): | |
39 | raise rrdtool.OperationalError('RRD file was not created') | |
40 | ||
41 | return RRD(filename) | |
42 | ||
43 | class RRD: | |
44 | """An object-based interface to the rrdtool module.""" | |
45 | ||
46 | def __init__(self, filename, check_type=True): | |
47 | "Initialize the class instance with a filename." | |
48 | ||
49 | if not os.access(filename, os.F_OK | os.R_OK): | |
50 | raise rrdtool.OperationalError('RRD {!s} cannot be opened.' \ | |
51 | .format(filename)) | |
52 | ||
53 | # Use rrdinfo to test whether the file is a valid RRD file | |
54 | if check_type is True: | |
55 | rrdtool.info(filename) | |
56 | ||
57 | self.readonly = not os.access(filename, os.W_OK) | |
58 | self.filename = filename | |
59 | ||
60 | def graph(self, output_file, *args): | |
225c0910 CJ |
61 | """ |
62 | Generate a graph based on the arguments passed to this function. | |
63 | ||
64 | If output_file is None, "-" will be used as the output filename. | |
65 | In that case, rrdtool returns the image bytes within its info dict. | |
66 | """ | |
67 | outfile = '-' if output_file is None else output_file | |
b4570f2a | 68 | |
225c0910 CJ |
69 | # when writing to a file-like object, use output buffering |
70 | if isinstance(output_file, os.IOBase): | |
71 | outfile = '-' | |
b4570f2a | 72 | |
225c0910 | 73 | info = rrdtool.graphv(outfile, *args) |
b4570f2a | 74 | |
225c0910 CJ |
75 | if isinstance(info, dict) and 'image' in info: |
76 | if isinstance(output_file, os.IOBase): | |
77 | output_file.write(info['image']) | |
78 | elif output_file is None: | |
79 | return info['image'] | |
b4570f2a | 80 | |
225c0910 | 81 | return info |
b4570f2a CJ |
82 | |
83 | def info(self): | |
84 | return rrdtool.info(self.filename) | |
85 | ||
86 | def update(self, values, *args): | |
87 | vl = [] | |
88 | ||
89 | if self.readonly: | |
90 | raise rrdtool.OperationalError('RRD file is read-only: {!s}' \ | |
91 | .format(self.filename)) | |
92 | elif not isinstance(values, (list, tuple)): | |
93 | raise rrdtool.ProgrammingError('The values parameter must be a ' \ | |
94 | 'list or tuple') | |
95 | else: | |
96 | for row in values: | |
97 | if isinstance(row, str): | |
98 | vl.append(row) | |
99 | elif isinstance(row, (list, tuple)): | |
100 | if len(row) < 2: | |
101 | raise rrdtool.ProgrammingError('Value {!r} has too ' \ | |
102 | 'few elements in sequence object'.format(row)) | |
103 | else: | |
104 | ts = row[0] | |
105 | if ts is None: | |
106 | ts = 'N' | |
107 | elif isinstance(ts, datetime): | |
108 | ts = int(mktime(ts.timetuple())) | |
109 | elif isinstance(ts, str): | |
110 | ts = int(ts) | |
111 | elif not isinstance(ts, int): | |
112 | raise ValueError('Unsupported type') | |
113 | ||
114 | v = '{}:{}'.format(ts, ':'.join([str(x) for x in row[1:]])) | |
115 | vl.append(v) | |
116 | ||
117 | arglist = tuple(vl + list(args)) | |
118 | return rrdtool.update(self.filename, *arglist) | |
119 | ||
120 | def __repr__(self): | |
121 | return '<RRD {!r}>'.format(self.filename) |