Skip to content
This repository was archived by the owner on Oct 29, 2024. It is now read-only.

Fix failing tags match in get_points() on a ResultSet #511

Merged
merged 7 commits into from
Nov 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/source/resultset.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Using ``rs.get_points()`` will return a generator for all the points in the Resu
Filtering by measurement
------------------------

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.
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.
::

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

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.
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.
::

rs = cli.query("SELECT * from cpu")
Expand Down
2 changes: 1 addition & 1 deletion influxdb/influxdb08/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ def _query(self, query, time_precision='s', chunked=False):
else:
chunked_param = 'false'

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

params = {
Expand Down
67 changes: 35 additions & 32 deletions influxdb/resultset.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ def error(self):
def __getitem__(self, key):
"""Retrieve the series name or specific set based on key.

:param key: Either a serie name, or a tags_dict, or
a 2-tuple(serie_name, tags_dict).
If the serie name is None (or not given) then any serie
:param key: Either a series name, or a tags_dict, or
a 2-tuple(series_name, tags_dict).
If the series name is None (or not given) then any serie
matching the eventual given tags will be given its points
one after the other.
To get the points of every serie in this resultset then
To get the points of every series in this resultset then
you have to provide None as key.
:return: A generator yielding `Point`s matching the given key.
NB:
Expand Down Expand Up @@ -93,22 +93,25 @@ def get_points(self, measurement=None, tags=None):
(bytes, type(b''.decode()), type(None))):
raise TypeError('measurement must be an str or None')

for serie in self._get_series():
serie_name = serie.get('measurement', serie.get('name', 'results'))
if serie_name is None:
for series in self._get_series():
series_name = series.get('measurement',
series.get('name', 'results'))
if series_name is None:
# this is a "system" query or a query which
# doesn't return a name attribute.
# like 'show retention policies' ..
if tags is None:
for item in self._get_points_for_serie(serie):
for item in self._get_points_for_series(series):
yield item

elif measurement in (None, serie_name):
elif measurement in (None, series_name):
# by default if no tags was provided then
# we will matches every returned serie
serie_tags = serie.get('tags', {})
if tags is None or self._tag_matches(serie_tags, tags):
for item in self._get_points_for_serie(serie):
# we will matches every returned series
series_tags = series.get('tags', {})
for item in self._get_points_for_series(series):
if tags is None or \
self._tag_matches(item, tags) or \
self._tag_matches(series_tags, tags):
yield item

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

def __iter__(self):
"""Yield one dict instance per serie result."""
"""Yield one dict instance per series result."""
for key in self.keys():
yield list(self.__getitem__(key))

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

return True
Expand All @@ -150,14 +153,14 @@ def __len__(self):
def keys(self):
"""Return the list of keys in the ResultSet.

:return: List of keys. Keys are tuples (serie_name, tags)
:return: List of keys. Keys are tuples (series_name, tags)
"""
keys = []
for serie in self._get_series():
for series in self._get_series():
keys.append(
(serie.get('measurement',
serie.get('name', 'results')),
serie.get('tags', None))
(series.get('measurement',
series.get('name', 'results')),
series.get('tags', None))
)
return keys

Expand All @@ -167,24 +170,24 @@ def items(self):
:return: List of tuples, (key, generator)
"""
items = []
for serie in self._get_series():
serie_key = (serie.get('measurement',
serie.get('name', 'results')),
serie.get('tags', None))
for series in self._get_series():
series_key = (series.get('measurement',
series.get('name', 'results')),
series.get('tags', None))
items.append(
(serie_key, self._get_points_for_serie(serie))
(series_key, self._get_points_for_series(series))
)
return items

def _get_points_for_serie(self, serie):
"""Return generator of dict from columns and values of a serie.
def _get_points_for_series(self, series):
"""Return generator of dict from columns and values of a series.

:param serie: One serie
:param series: One series
:return: Generator of dicts
"""
for point in serie.get('values', []):
for point in series.get('values', []):
yield self.point_from_cols_vals(
serie['columns'],
series['columns'],
point
)

Expand Down
105 changes: 63 additions & 42 deletions influxdb/tests/resultset_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,25 @@ def setUp(self):
"""Set up an instance of TestResultSet."""
self.query_response = {
"results": [
{"series": [{"measurement": "cpu_load_short",
"tags": {"host": "server01",
"region": "us-west"},
"columns": ["time", "value"],
{"series": [{"name": "cpu_load_short",
"columns": ["time", "value", "host", "region"],
"values": [
["2015-01-29T21:51:28.968422294Z", 0.64]
["2015-01-29T21:51:28.968422294Z",
0.64,
"server01",
"us-west"],
["2015-01-29T21:51:28.968422294Z",
0.65,
"server02",
"us-west"],
]},
{"measurement": "cpu_load_short",
"tags": {"host": "server02",
"region": "us-west"},
"columns": ["time", "value"],
{"name": "other_series",
"columns": ["time", "value", "host", "region"],
"values": [
["2015-01-29T21:51:28.968422294Z", 0.65]
]},
{"measurement": "other_serie",
"tags": {"host": "server01",
"region": "us-west"},
"columns": ["time", "value"],
"values": [
["2015-01-29T21:51:28.968422294Z", 0.66]
["2015-01-29T21:51:28.968422294Z",
0.66,
"server01",
"us-west"],
]}]}
]
}
Expand All @@ -48,8 +47,14 @@ def setUp(self):
def test_filter_by_name(self):
"""Test filtering by name in TestResultSet object."""
expected = [
{'value': 0.64, 'time': '2015-01-29T21:51:28.968422294Z'},
{'value': 0.65, 'time': '2015-01-29T21:51:28.968422294Z'}
{'value': 0.64,
'time': '2015-01-29T21:51:28.968422294Z',
'host': 'server01',
'region': 'us-west'},
{'value': 0.65,
'time': '2015-01-29T21:51:28.968422294Z',
'host': 'server02',
'region': 'us-west'},
]

self.assertEqual(expected, list(self.rs['cpu_load_short']))
Expand All @@ -60,8 +65,14 @@ def test_filter_by_name(self):
def test_filter_by_tags(self):
"""Test filter by tags in TestResultSet object."""
expected = [
{'time': '2015-01-29T21:51:28.968422294Z', 'value': 0.64},
{'time': '2015-01-29T21:51:28.968422294Z', 'value': 0.66}
{'value': 0.64,
'time': '2015-01-29T21:51:28.968422294Z',
'host': 'server01',
'region': 'us-west'},
{'value': 0.66,
'time': '2015-01-29T21:51:28.968422294Z',
'host': 'server01',
'region': 'us-west'},
]

self.assertEqual(
Expand All @@ -78,14 +89,23 @@ def test_filter_by_name_and_tags(self):
"""Test filter by name and tags in TestResultSet object."""
self.assertEqual(
list(self.rs[('cpu_load_short', {"host": "server01"})]),
[{'time': '2015-01-29T21:51:28.968422294Z', 'value': 0.64}]
[{'value': 0.64,
'time': '2015-01-29T21:51:28.968422294Z',
'host': 'server01',
'region': 'us-west'}]
)

self.assertEqual(
list(self.rs[('cpu_load_short', {"region": "us-west"})]),
[
{'value': 0.64, 'time': '2015-01-29T21:51:28.968422294Z'},
{'value': 0.65, 'time': '2015-01-29T21:51:28.968422294Z'}
{'value': 0.64,
'time': '2015-01-29T21:51:28.968422294Z',
'host': 'server01',
'region': 'us-west'},
{'value': 0.65,
'time': '2015-01-29T21:51:28.968422294Z',
'host': 'server02',
'region': 'us-west'},
]
)

Expand All @@ -94,17 +114,16 @@ def test_keys(self):
self.assertEqual(
self.rs.keys(),
[
('cpu_load_short', {'host': 'server01', 'region': 'us-west'}),
('cpu_load_short', {'host': 'server02', 'region': 'us-west'}),
('other_serie', {'host': 'server01', 'region': 'us-west'})
('cpu_load_short', None),
('other_series', None),
]
)

def test_len(self):
"""Test length in TestResultSet object."""
self.assertEqual(
len(self.rs),
3
2
)

def test_items(self):
Expand All @@ -116,21 +135,23 @@ def test_items(self):
items_lists,
[
(
('cpu_load_short',
{'host': 'server01', 'region': 'us-west'}),
[{'value': 0.64, 'time': '2015-01-29T21:51:28.968422294Z'}]
),
('cpu_load_short', None),
[
{'time': '2015-01-29T21:51:28.968422294Z',
'value': 0.64,
'host': 'server01',
'region': 'us-west'},
{'time': '2015-01-29T21:51:28.968422294Z',
'value': 0.65,
'host': 'server02',
'region': 'us-west'}]),
(
('cpu_load_short',
{'host': 'server02', 'region': 'us-west'}),
[{'value': 0.65, 'time': '2015-01-29T21:51:28.968422294Z'}]
),
(
('other_serie',
{'host': 'server01', 'region': 'us-west'}),
[{'value': 0.66, 'time': '2015-01-29T21:51:28.968422294Z'}]
)
]
('other_series', None),
[
{'time': '2015-01-29T21:51:28.968422294Z',
'value': 0.66,
'host': 'server01',
'region': 'us-west'}])]
)

def test_point_from_cols_vals(self):
Expand Down
Loading