Skip to content

Commit 50ac36a

Browse files
author
Christopher Rabotin
committed
Completed helper code and tests (which succeed).
1 parent c2f2967 commit 50ac36a

File tree

4 files changed

+91
-37
lines changed

4 files changed

+91
-37
lines changed

influxdb/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22
from .client import InfluxDBClient
33
from .dataframe_client import DataFrameClient
4+
from .helper import SeriesHelper
45

56

67
__all__ = [

influxdb/helper.py

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,67 @@
33
Helper class for InfluxDB
44
"""
55
from collections import namedtuple, defaultdict
6+
import six
67

7-
8-
class InfluxDBSeriesHelper(object):
8+
class SeriesHelper(object):
9+
__initialized__ = False
910

1011
def __new__(cls, *args, **kwargs):
11-
# Introspect series representation.
12-
try:
13-
_meta = getattr(cls, 'Meta')
14-
except AttributeError:
15-
raise AttributeError('SeriesHelper {} does not contain a Meta class.'.format(cls.__name__))
16-
17-
for attribute in ['series_name', 'fields', 'client']:
12+
if not SeriesHelper.__initialized__:
13+
SeriesHelper.__initialized__ = True
14+
# Introspect series representation.
1815
try:
19-
setattr(cls, '_' + attribute, getattr(_meta, attribute))
16+
_meta = getattr(cls, 'Meta')
2017
except AttributeError:
21-
raise AttributeError('SeriesHelper\' {0} Meta class does not define {1}.'.format(cls.__name__, attribute))
22-
23-
cls._bulk_size = getattr(_meta, 'bulk_size', 1)
18+
raise AttributeError('SeriesHelper {} does not contain a Meta class.'.format(cls.__name__))
19+
20+
for attribute in ['series_name', 'fields', 'client']:
21+
try:
22+
setattr(cls, '_' + attribute, getattr(_meta, attribute))
23+
except AttributeError:
24+
raise AttributeError('SeriesHelper\' {0} Meta class does not define {1}.'.format(cls.__name__, attribute))
25+
26+
cls._bulk_size = getattr(_meta, 'bulk_size', 1)
27+
28+
# Class attribute definitions
29+
cls._datapoints = defaultdict(list) # keys are the series name for ease of commit.
30+
cls._type = namedtuple(cls.__name__, cls._fields)
2431

25-
# Class attribute definitions
26-
cls._datapoints = defaultdict(list) # keys are the series name for ease of commit.
27-
cls._type = namedtuple(cls.__name__, cls._fields)
28-
29-
return super(InfluxDBSeriesHelper, cls).__new__(cls, *args, **kwargs)
32+
return super(SeriesHelper, cls).__new__(cls, *args, **kwargs)
3033

3134
def __init__(self, **kwargs): # Does not support positional arguments.
3235
cls = self.__class__
3336

3437
if sorted(cls._fields) != sorted(kwargs.keys()):
35-
raise KeyError('[Fields enforced] Expected fields {0} and got {1}.'.format(sorted(cls._fields), sorted(kwargs.keys())))
38+
raise NameError('Expected fields {0} and got {1}.'.format(', '.join(sorted(cls._fields)), ', '.join(sorted(kwargs.keys()))))
3639

37-
cls._datapoints[cls._series_name.format(**kwargs)] = cls._type(**kwargs)
40+
cls._datapoints[cls._series_name.format(**kwargs)].append(cls._type(**kwargs))
3841

3942
if len(cls._datapoints) > cls._bulk_size:
4043
cls.commit()
4144

42-
@staticmethod
43-
def _json_body():
45+
@classmethod
46+
def commit(cls):
4447
'''
45-
:return: JSON body of these datapoints.
48+
Commit everything from datapoints via the client.
4649
'''
47-
pass
50+
rtn = cls._client.write_points(cls._json_body_())
51+
cls._reset_()
52+
return rtn
4853

49-
@staticmethod
50-
def commit():
54+
@classmethod
55+
def _json_body_(cls):
5156
'''
52-
Commit everything from datapoints via the client.
57+
:return: JSON body of these datapoints.
5358
'''
54-
pass
59+
json_datapoints = []
60+
for series_name, data in six.iteritems(cls._datapoints):
61+
json_datapoints.append({'name': series_name,
62+
'columns': cls._fields,
63+
'points': [[point.__dict__[k] for k in cls._fields] for point in data]
64+
})
65+
return json_datapoints
66+
67+
@classmethod
68+
def _reset_(cls):
69+
cls._datapoints = defaultdict(list)

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
requests>=1.0.3
2+
six==1.9.0

tests/influxdb/helper_test.py

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,63 @@
22

33
import unittest
44

5-
from influxdb.helper import InfluxDBSeriesHelper
5+
from influxdb import SeriesHelper, InfluxDBClient
66

77

88
class TestSeriesHelper(unittest.TestCase):
99
@classmethod
1010
def setUpClass(cls):
1111
super(TestSeriesHelper, cls).setUpClass()
12-
13-
class MySeriesHelper(InfluxDBSeriesHelper):
12+
13+
TestSeriesHelper.client = InfluxDBClient('host', 8086, 'username', 'password', 'database')
14+
15+
class MySeriesHelper(SeriesHelper):
1416
class Meta:
17+
client = TestSeriesHelper.client
1518
series_name = 'events.stats.{server_name}'
1619
fields = ['time', 'server_name']
1720
bulk_size = 5
18-
21+
1922
TestSeriesHelper.MySeriesHelper = MySeriesHelper
2023

21-
def testFeatures(self):
24+
def testSingleSeriesName(self):
25+
'''
26+
Tests JSON conversion when there is only one series name.
27+
'''
28+
TestSeriesHelper.MySeriesHelper(server_name='us.east-1', time=159)
29+
TestSeriesHelper.MySeriesHelper(server_name='us.east-1', time=158)
30+
TestSeriesHelper.MySeriesHelper(server_name='us.east-1', time=157)
31+
TestSeriesHelper.MySeriesHelper(server_name='us.east-1', time=156)
32+
expectation = [{'points': [[159, 'us.east-1'],
33+
[158, 'us.east-1'],
34+
[157, 'us.east-1'],
35+
[156, 'us.east-1']],
36+
'name': 'events.stats.us.east-1',
37+
'columns': ['time', 'server_name']}]
38+
self.assertListEqual(TestSeriesHelper.MySeriesHelper._json_body_(), expectation, 'Invalid JSON body of time series returned from _json_body_ for one series name.')
39+
TestSeriesHelper.MySeriesHelper._reset_()
40+
self.assertEqual(TestSeriesHelper.MySeriesHelper._json_body_(), [], 'Resetting helper did not empty datapoints.')
41+
42+
def testSeveralSeriesNames(self):
2243
'''
23-
+ Create event
24-
+ JSON
25-
+ Commit ? May be tough to test.
44+
Tests JSON conversion when there is only one series name.
2645
'''
27-
TestSeriesHelper.MySeriesHelper(server_name='us.east-1', time=159)
46+
TestSeriesHelper.MySeriesHelper(server_name='us.east-1', time=159)
47+
TestSeriesHelper.MySeriesHelper(server_name='fr.paris-10', time=158)
48+
TestSeriesHelper.MySeriesHelper(server_name='lu.lux', time=157)
49+
TestSeriesHelper.MySeriesHelper(server_name='uk.london', time=156)
50+
expectation = [{'points': [[157, 'lu.lux']],
51+
'name': 'events.stats.lu.lux',
52+
'columns': ['time', 'server_name']},
53+
{'points': [[156, 'uk.london']],
54+
'name': 'events.stats.uk.london',
55+
'columns': ['time', 'server_name']},
56+
{'points': [[158, 'fr.paris-10']],
57+
'name': 'events.stats.fr.paris-10',
58+
'columns': ['time', 'server_name']},
59+
{'points': [[159, 'us.east-1']],
60+
'name': 'events.stats.us.east-1',
61+
'columns': ['time', 'server_name']}]
62+
self.assertListEqual(TestSeriesHelper.MySeriesHelper._json_body_(), expectation, 'Invalid JSON body of time series returned from _json_body_ for several series names.')
63+
TestSeriesHelper.MySeriesHelper._reset_()
64+
self.assertEqual(TestSeriesHelper.MySeriesHelper._json_body_(), [], 'Resetting helper did not empty datapoints.')

0 commit comments

Comments
 (0)