Skip to content

Commit 89961cf

Browse files
xginn8aviau
authored andcommitted
Fix failing tags match in get_points() on a ResultSet (influxdata#511)
* rename serie to series * pass in tags variable to perform match fix the format of the object in the ResultSet test to match what's returned from a query fix other flake8 formatting issues * meh * more serie -> series * fixing broken tags filtering * readding missing parameter that i somehow dropped
1 parent 530b4c5 commit 89961cf

File tree

5 files changed

+118
-93
lines changed

5 files changed

+118
-93
lines changed

docs/source/resultset.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Using ``rs.get_points()`` will return a generator for all the points in the Resu
1818
Filtering by measurement
1919
------------------------
2020

21-
Using ``rs.get_points('cpu')`` will return a generator for all the points that are in a serie with measurement name ``cpu``, no matter the tags.
21+
Using ``rs.get_points('cpu')`` will return a generator for all the points that are in a series with measurement name ``cpu``, no matter the tags.
2222
::
2323

2424
rs = cli.query("SELECT * from cpu")
@@ -36,7 +36,7 @@ Using ``rs.get_points(tags={'host_name': 'influxdb.com'})`` will return a genera
3636
Filtering by measurement and tags
3737
---------------------------------
3838

39-
Using measurement name and tags will return a generator for all the points that are in a serie with the specified measurement name AND whose tags match the given tags.
39+
Using measurement name and tags will return a generator for all the points that are in a series with the specified measurement name AND whose tags match the given tags.
4040
::
4141

4242
rs = cli.query("SELECT * from cpu")

influxdb/influxdb08/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ def _query(self, query, time_precision='s', chunked=False):
435435
else:
436436
chunked_param = 'false'
437437

438-
# Build the URL of the serie to query
438+
# Build the URL of the series to query
439439
url = "db/{0}/series".format(self._database)
440440

441441
params = {

influxdb/resultset.py

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ def error(self):
4141
def __getitem__(self, key):
4242
"""Retrieve the series name or specific set based on key.
4343
44-
:param key: Either a serie name, or a tags_dict, or
45-
a 2-tuple(serie_name, tags_dict).
46-
If the serie name is None (or not given) then any serie
44+
:param key: Either a series name, or a tags_dict, or
45+
a 2-tuple(series_name, tags_dict).
46+
If the series name is None (or not given) then any serie
4747
matching the eventual given tags will be given its points
4848
one after the other.
49-
To get the points of every serie in this resultset then
49+
To get the points of every series in this resultset then
5050
you have to provide None as key.
5151
:return: A generator yielding `Point`s matching the given key.
5252
NB:
@@ -93,22 +93,25 @@ def get_points(self, measurement=None, tags=None):
9393
(bytes, type(b''.decode()), type(None))):
9494
raise TypeError('measurement must be an str or None')
9595

96-
for serie in self._get_series():
97-
serie_name = serie.get('measurement', serie.get('name', 'results'))
98-
if serie_name is None:
96+
for series in self._get_series():
97+
series_name = series.get('measurement',
98+
series.get('name', 'results'))
99+
if series_name is None:
99100
# this is a "system" query or a query which
100101
# doesn't return a name attribute.
101102
# like 'show retention policies' ..
102103
if tags is None:
103-
for item in self._get_points_for_serie(serie):
104+
for item in self._get_points_for_series(series):
104105
yield item
105106

106-
elif measurement in (None, serie_name):
107+
elif measurement in (None, series_name):
107108
# by default if no tags was provided then
108-
# we will matches every returned serie
109-
serie_tags = serie.get('tags', {})
110-
if tags is None or self._tag_matches(serie_tags, tags):
111-
for item in self._get_points_for_serie(serie):
109+
# we will matches every returned series
110+
series_tags = series.get('tags', {})
111+
for item in self._get_points_for_series(series):
112+
if tags is None or \
113+
self._tag_matches(item, tags) or \
114+
self._tag_matches(series_tags, tags):
112115
yield item
113116

114117
def __repr__(self):
@@ -121,7 +124,7 @@ def __repr__(self):
121124
return "ResultSet({%s})" % ", ".join(items)
122125

123126
def __iter__(self):
124-
"""Yield one dict instance per serie result."""
127+
"""Yield one dict instance per series result."""
125128
for key in self.keys():
126129
yield list(self.__getitem__(key))
127130

@@ -131,10 +134,10 @@ def _tag_matches(tags, filter):
131134
for tag_name, tag_value in filter.items():
132135
# using _sentinel as I'm not sure that "None"
133136
# could be used, because it could be a valid
134-
# serie_tags value : when a serie has no such tag
137+
# series_tags value : when a series has no such tag
135138
# then I think it's set to /null/None/.. TBC..
136-
serie_tag_value = tags.get(tag_name, _sentinel)
137-
if serie_tag_value != tag_value:
139+
series_tag_value = tags.get(tag_name, _sentinel)
140+
if series_tag_value != tag_value:
138141
return False
139142

140143
return True
@@ -150,14 +153,14 @@ def __len__(self):
150153
def keys(self):
151154
"""Return the list of keys in the ResultSet.
152155
153-
:return: List of keys. Keys are tuples (serie_name, tags)
156+
:return: List of keys. Keys are tuples (series_name, tags)
154157
"""
155158
keys = []
156-
for serie in self._get_series():
159+
for series in self._get_series():
157160
keys.append(
158-
(serie.get('measurement',
159-
serie.get('name', 'results')),
160-
serie.get('tags', None))
161+
(series.get('measurement',
162+
series.get('name', 'results')),
163+
series.get('tags', None))
161164
)
162165
return keys
163166

@@ -167,24 +170,24 @@ def items(self):
167170
:return: List of tuples, (key, generator)
168171
"""
169172
items = []
170-
for serie in self._get_series():
171-
serie_key = (serie.get('measurement',
172-
serie.get('name', 'results')),
173-
serie.get('tags', None))
173+
for series in self._get_series():
174+
series_key = (series.get('measurement',
175+
series.get('name', 'results')),
176+
series.get('tags', None))
174177
items.append(
175-
(serie_key, self._get_points_for_serie(serie))
178+
(series_key, self._get_points_for_series(series))
176179
)
177180
return items
178181

179-
def _get_points_for_serie(self, serie):
180-
"""Return generator of dict from columns and values of a serie.
182+
def _get_points_for_series(self, series):
183+
"""Return generator of dict from columns and values of a series.
181184
182-
:param serie: One serie
185+
:param series: One series
183186
:return: Generator of dicts
184187
"""
185-
for point in serie.get('values', []):
188+
for point in series.get('values', []):
186189
yield self.point_from_cols_vals(
187-
serie['columns'],
190+
series['columns'],
188191
point
189192
)
190193

influxdb/tests/resultset_test.py

Lines changed: 63 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,25 @@ def setUp(self):
1919
"""Set up an instance of TestResultSet."""
2020
self.query_response = {
2121
"results": [
22-
{"series": [{"measurement": "cpu_load_short",
23-
"tags": {"host": "server01",
24-
"region": "us-west"},
25-
"columns": ["time", "value"],
22+
{"series": [{"name": "cpu_load_short",
23+
"columns": ["time", "value", "host", "region"],
2624
"values": [
27-
["2015-01-29T21:51:28.968422294Z", 0.64]
25+
["2015-01-29T21:51:28.968422294Z",
26+
0.64,
27+
"server01",
28+
"us-west"],
29+
["2015-01-29T21:51:28.968422294Z",
30+
0.65,
31+
"server02",
32+
"us-west"],
2833
]},
29-
{"measurement": "cpu_load_short",
30-
"tags": {"host": "server02",
31-
"region": "us-west"},
32-
"columns": ["time", "value"],
34+
{"name": "other_series",
35+
"columns": ["time", "value", "host", "region"],
3336
"values": [
34-
["2015-01-29T21:51:28.968422294Z", 0.65]
35-
]},
36-
{"measurement": "other_serie",
37-
"tags": {"host": "server01",
38-
"region": "us-west"},
39-
"columns": ["time", "value"],
40-
"values": [
41-
["2015-01-29T21:51:28.968422294Z", 0.66]
37+
["2015-01-29T21:51:28.968422294Z",
38+
0.66,
39+
"server01",
40+
"us-west"],
4241
]}]}
4342
]
4443
}
@@ -48,8 +47,14 @@ def setUp(self):
4847
def test_filter_by_name(self):
4948
"""Test filtering by name in TestResultSet object."""
5049
expected = [
51-
{'value': 0.64, 'time': '2015-01-29T21:51:28.968422294Z'},
52-
{'value': 0.65, 'time': '2015-01-29T21:51:28.968422294Z'}
50+
{'value': 0.64,
51+
'time': '2015-01-29T21:51:28.968422294Z',
52+
'host': 'server01',
53+
'region': 'us-west'},
54+
{'value': 0.65,
55+
'time': '2015-01-29T21:51:28.968422294Z',
56+
'host': 'server02',
57+
'region': 'us-west'},
5358
]
5459

5560
self.assertEqual(expected, list(self.rs['cpu_load_short']))
@@ -60,8 +65,14 @@ def test_filter_by_name(self):
6065
def test_filter_by_tags(self):
6166
"""Test filter by tags in TestResultSet object."""
6267
expected = [
63-
{'time': '2015-01-29T21:51:28.968422294Z', 'value': 0.64},
64-
{'time': '2015-01-29T21:51:28.968422294Z', 'value': 0.66}
68+
{'value': 0.64,
69+
'time': '2015-01-29T21:51:28.968422294Z',
70+
'host': 'server01',
71+
'region': 'us-west'},
72+
{'value': 0.66,
73+
'time': '2015-01-29T21:51:28.968422294Z',
74+
'host': 'server01',
75+
'region': 'us-west'},
6576
]
6677

6778
self.assertEqual(
@@ -78,14 +89,23 @@ def test_filter_by_name_and_tags(self):
7889
"""Test filter by name and tags in TestResultSet object."""
7990
self.assertEqual(
8091
list(self.rs[('cpu_load_short', {"host": "server01"})]),
81-
[{'time': '2015-01-29T21:51:28.968422294Z', 'value': 0.64}]
92+
[{'value': 0.64,
93+
'time': '2015-01-29T21:51:28.968422294Z',
94+
'host': 'server01',
95+
'region': 'us-west'}]
8296
)
8397

8498
self.assertEqual(
8599
list(self.rs[('cpu_load_short', {"region": "us-west"})]),
86100
[
87-
{'value': 0.64, 'time': '2015-01-29T21:51:28.968422294Z'},
88-
{'value': 0.65, 'time': '2015-01-29T21:51:28.968422294Z'}
101+
{'value': 0.64,
102+
'time': '2015-01-29T21:51:28.968422294Z',
103+
'host': 'server01',
104+
'region': 'us-west'},
105+
{'value': 0.65,
106+
'time': '2015-01-29T21:51:28.968422294Z',
107+
'host': 'server02',
108+
'region': 'us-west'},
89109
]
90110
)
91111

@@ -94,17 +114,16 @@ def test_keys(self):
94114
self.assertEqual(
95115
self.rs.keys(),
96116
[
97-
('cpu_load_short', {'host': 'server01', 'region': 'us-west'}),
98-
('cpu_load_short', {'host': 'server02', 'region': 'us-west'}),
99-
('other_serie', {'host': 'server01', 'region': 'us-west'})
117+
('cpu_load_short', None),
118+
('other_series', None),
100119
]
101120
)
102121

103122
def test_len(self):
104123
"""Test length in TestResultSet object."""
105124
self.assertEqual(
106125
len(self.rs),
107-
3
126+
2
108127
)
109128

110129
def test_items(self):
@@ -116,21 +135,23 @@ def test_items(self):
116135
items_lists,
117136
[
118137
(
119-
('cpu_load_short',
120-
{'host': 'server01', 'region': 'us-west'}),
121-
[{'value': 0.64, 'time': '2015-01-29T21:51:28.968422294Z'}]
122-
),
138+
('cpu_load_short', None),
139+
[
140+
{'time': '2015-01-29T21:51:28.968422294Z',
141+
'value': 0.64,
142+
'host': 'server01',
143+
'region': 'us-west'},
144+
{'time': '2015-01-29T21:51:28.968422294Z',
145+
'value': 0.65,
146+
'host': 'server02',
147+
'region': 'us-west'}]),
123148
(
124-
('cpu_load_short',
125-
{'host': 'server02', 'region': 'us-west'}),
126-
[{'value': 0.65, 'time': '2015-01-29T21:51:28.968422294Z'}]
127-
),
128-
(
129-
('other_serie',
130-
{'host': 'server01', 'region': 'us-west'}),
131-
[{'value': 0.66, 'time': '2015-01-29T21:51:28.968422294Z'}]
132-
)
133-
]
149+
('other_series', None),
150+
[
151+
{'time': '2015-01-29T21:51:28.968422294Z',
152+
'value': 0.66,
153+
'host': 'server01',
154+
'region': 'us-west'}])]
134155
)
135156

136157
def test_point_from_cols_vals(self):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy