diff --git a/.gitignore b/.gitignore index 72364f9..2b3e5fa 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ htmlcov/ .tox/ .coverage .coverage.* +.coveragerc .cache nosetests.xml coverage.xml diff --git a/.travis.yml b/.travis.yml index 519e476..c1ab5fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,12 +2,9 @@ language: python cache: pip python: - '2.7' -- '3.3' -- '3.4' -- '3.5' install: pip install . codecov mock nose pylint script: -- nosetests --with-coverage +- nosetests --with-coverage --cover-package influxalchemy - pylint influxalchemy after_success: codecov deploy: diff --git a/influxalchemy/measurement.py b/influxalchemy/measurement.py index 4fd3fbe..232217c 100644 --- a/influxalchemy/measurement.py +++ b/influxalchemy/measurement.py @@ -12,10 +12,13 @@ def __getattr__(cls, name): return Tag(name, cls) def __str__(cls): - try: - return cls.__measurement__ - except AttributeError: - return cls.__name__ + return cls.__measurement__ + + def __eq__(cls, other): + return str(cls) == str(other) + + def __ne__(cls, other): + return str(cls) != str(other) def __or__(cls, other): left = str(cls).strip("/") @@ -51,12 +54,12 @@ def __init__(self, name, measurement): self._name = name self.measurement = measurement - def __repr__(self): - return "<%s.%s>" % (self.measurement.__measurement__, self._name) - def __str__(self): return self._name + def __repr__(self): + return "<%s.%s>" % (self.measurement.__measurement__, self._name) + def __eq__(self, other): return TagExp.equals(self, other) @@ -120,11 +123,17 @@ def __init__(self, left, op, right): else: self._right = repr(right) + def __str__(self): + return "%s%s%s" % (self._left, self._op, self._right) + def __repr__(self): return "[ %s ]" % self - def __str__(self): - return "%s%s%s" % (self._left, self._op, self._right) + def __eq__(self, other): + return str(self) == str(other) + + def __ne__(self, other): + return str(self) != str(other) def __and__(self, other): return TagExp(str(self), " AND ", str(other)) @@ -138,39 +147,39 @@ def __invert__(self): @classmethod def equals(cls, self, other): """ left = right """ - return TagExp(self, operations.EQ, other) + return cls(self, operations.EQ, other) @classmethod def notequals(cls, self, other): """ left != right """ - return TagExp(self, operations.NE, other) + return cls(self, operations.NE, other) @classmethod def greater_than(cls, self, other): """ left > right """ - return TagExp(self, operations.GT, other) + return cls(self, operations.GT, other) @classmethod def less_than(cls, self, other): """ left < right """ - return TagExp(self, operations.LT, other) + return cls(self, operations.LT, other) @classmethod def greater_equal(cls, self, other): """ left >= right """ - return TagExp(self, operations.GE, other) + return cls(self, operations.GE, other) @classmethod def less_equal(cls, self, other): """ left <= right """ - return TagExp(self, operations.LE, other) + return cls(self, operations.LE, other) @classmethod def like(cls, self, other): """ left =~ right """ - return TagExp(self, operations.LK, other) + return cls(self, operations.LK, other) @classmethod def notlike(cls, self, other): """ left !~ right """ - return TagExp(self, operations.NK, other) + return cls(self, operations.NK, other) diff --git a/influxalchemy/query.py b/influxalchemy/query.py index 47a8519..b4d1c65 100644 --- a/influxalchemy/query.py +++ b/influxalchemy/query.py @@ -49,7 +49,7 @@ def filter_by(self, **kwargs): expressions = self._expressions for key, val in kwargs.items(): expressions += measurement.TagExp.equals(key, val), - return InfluxDBQuery(self._entities, self._client, *expressions) + return InfluxDBQuery(self._entities, self._client, expressions) def group_by(self, groupby): """ Group query. """ diff --git a/setup.py b/setup.py index 39c1968..4e9a567 100644 --- a/setup.py +++ b/setup.py @@ -16,9 +16,6 @@ "Topic :: Utilities", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", "Programming Language :: Python"] diff --git a/tests/client_tests.py b/tests/client_tests.py new file mode 100644 index 0000000..8ff9b2a --- /dev/null +++ b/tests/client_tests.py @@ -0,0 +1,28 @@ +""" InfluxAlchemy client tests. """ + +import mock +import influxdb +from influxalchemy.client import InfluxAlchemy +from influxalchemy.measurement import Measurement +from influxalchemy.query import InfluxDBQuery +from nose import tools + + +@mock.patch("influxdb.InfluxDBClient") +def test_query(mock_flux): + db = influxdb.InfluxDBClient(database="fizz") + db.query.side_effect = influxdb.exceptions.InfluxDBClientError(None) + client = InfluxAlchemy(db) + query = client.query(Measurement.new("buzz")) + tools.assert_equal(str(query), "SELECT * FROM buzz;") + + +@mock.patch("influxdb.InfluxDBClient.query") +def test_measurements(mock_flux): + mock_res = mock.MagicMock() + mock_res.get_points.return_value = [{"name": "fizz"}] + mock_flux.return_value = mock_res + db = influxdb.InfluxDBClient(database="fizz") + client = InfluxAlchemy(db) + measurements = list(client.measurements()) + mock_flux.assert_called_once_with("SHOW MEASUREMENTS;") diff --git a/tests/measurement_tests.py b/tests/measurement_tests.py new file mode 100644 index 0000000..b563e42 --- /dev/null +++ b/tests/measurement_tests.py @@ -0,0 +1,215 @@ +""" InfluxAlchemy Measurements. """ + +from influxalchemy.measurement import Measurement +from influxalchemy.measurement import Tag +from influxalchemy.measurement import TagExp +from influxalchemy.operations import * +from nose import tools + + +def test_meta_getattr(): + meas = Measurement.new("fizz") + yield tools.assert_equal, meas.buzz, Tag("buzz", meas) + + +def test_meta_str(): + meas = Measurement.new("fizz") + yield tools.assert_equal, str(meas), "fizz" + + +def test_meta_or(): + meas0 = Measurement.new("fizz") + meas1 = Measurement.new("buzz") + yield tools.assert_equal, (meas0 | meas1), Measurement.new("/fizz|buzz/") + + +def test_meta_measurement(): + meas = Measurement.new("fizz") + yield tools.assert_equal, meas, meas.measurement + + +class Fizz(Measurement): + __measurement__ = "fizz" + + +def test_new(): + yield tools.assert_equal, Measurement.new("fizz"), Fizz + + +def test_tag_init(): + meas = Measurement.new("fizz") + tag = Tag("buzz", meas) + yield tools.assert_equal, tag, meas.buzz + + +def test_tag_str(): + meas = Measurement.new("fizz") + tag = Tag("buzz", meas) + yield tools.assert_equal, str(tag), "buzz" + + +def test_tag_repr(): + meas = Measurement.new("fizz") + tag = Tag("buzz", meas) + yield tools.assert_equal, repr(tag), "" + + +def test_tag_eq(): + meas = Measurement.new("fizz") + tag = Tag("buzz", meas) + exp = tag == "foo" + yield tools.assert_equal, exp, TagExp("buzz", EQ, "foo") + + +def test_tag_ne(): + meas = Measurement.new("fizz") + tag = Tag("buzz", meas) + exp = tag != "foo" + yield tools.assert_equal, exp, TagExp("buzz", NE, "foo") + + +def test_tag_gt(): + meas = Measurement.new("fizz") + tag = Tag("buzz", meas) + exp = tag > "foo" + yield tools.assert_equal, exp, TagExp("buzz", GT, "foo") + + +def test_tag_lt(): + meas = Measurement.new("fizz") + tag = Tag("buzz", meas) + exp = tag < "foo" + yield tools.assert_equal, exp, TagExp("buzz", LT, "foo") + + +def test_tag_ge(): + meas = Measurement.new("fizz") + tag = Tag("buzz", meas) + exp = tag >= "foo" + yield tools.assert_equal, exp, TagExp("buzz", GE, "foo") + + +def test_tag_le(): + meas = Measurement.new("fizz") + tag = Tag("buzz", meas) + exp = tag <= "foo" + yield tools.assert_equal, exp, TagExp("buzz", LE, "foo") + + +def test_tag_like(): + meas = Measurement.new("fizz") + tag = Tag("buzz", meas) + exp = tag.like("foo") + yield tools.assert_equal, exp, TagExp("buzz", LK, "foo") + + +def test_tag_notlike(): + meas = Measurement.new("fizz") + tag = Tag("buzz", meas) + exp = tag.notlike("foo") + yield tools.assert_equal, exp, TagExp("buzz", NK, "foo") + + +def test_time_between(): + meas = Measurement.new("fizz") + exp = meas.time.between("'2016-01-01'", "now() - 7d") + yield tools.assert_equal, exp, \ + TagExp(meas.time, " >= ", "'2016-01-01'") & \ + TagExp(meas.time, " <= ", "now() - 7d") + + +def test_exp_init(): + meas = Measurement.new("fizz") + exp = TagExp(meas.buzz, " = ", "goo") + yield tools.assert_equal, exp._left, meas.buzz + yield tools.assert_equal, exp._op, " = " + yield tools.assert_equal, exp._right, "'goo'" + + +def test_exp_str(): + meas = Measurement.new("fizz") + exp = TagExp(meas.buzz, " = ", "goo") + yield tools.assert_equal, str(exp), "buzz = 'goo'" + + +def test_exp_repr(): + meas = Measurement.new("fizz") + exp = TagExp(meas.buzz, " = ", "goo") + yield tools.assert_equal, repr(exp), "[ buzz = 'goo' ]" + + +def test_exp_ne(): + meas = Measurement.new("fizz") + exp0 = TagExp(meas.buzz, " = ", "goo") + exp1 = TagExp(meas.guzz, " = ", "zoo") + yield tools.assert_true, exp0 != exp1 + + +def test_exp_and(): + meas = Measurement.new("fizz") + exp0 = TagExp(meas.buzz, " = ", "goo") + exp1 = TagExp(meas.guzz, " = ", "zoo") + yield tools.assert_equal, (exp0 & exp1), \ + TagExp("buzz = 'goo'", " AND ", "guzz = 'zoo'") + + +def test_exp_or(): + meas = Measurement.new("fizz") + exp0 = TagExp(meas.buzz, " = ", "goo") + exp1 = TagExp(meas.guzz, " = ", "zoo") + yield tools.assert_equal, (exp0 | exp1), \ + TagExp("buzz = 'goo'", " OR ", "guzz = 'zoo'") + + +def test_exp_inv(): + meas = Measurement.new("fizz") + exp = TagExp(meas.buzz, EQ, "goo") + yield tools.assert_equal, ~exp, TagExp(meas.buzz, NE, "'goo'") + + +def test_equals(): + meas = Measurement.new("fizz") + exp = TagExp.equals(meas.buzz, "goo") + yield tools.assert_equal, exp, TagExp(meas.buzz, EQ, "goo") + + +def test_notequals(): + meas = Measurement.new("fizz") + exp = TagExp.notequals(meas.buzz, "goo") + yield tools.assert_equal, exp, TagExp(meas.buzz, NE, "goo") + + +def test_greater_than(): + meas = Measurement.new("fizz") + exp = TagExp.greater_than(meas.buzz, "goo") + yield tools.assert_equal, exp, TagExp(meas.buzz, GT, "goo") + + +def test_less_than(): + meas = Measurement.new("fizz") + exp = TagExp.less_than(meas.buzz, "goo") + yield tools.assert_equal, exp, TagExp(meas.buzz, LT, "goo") + + +def test_greater_equal(): + meas = Measurement.new("fizz") + exp = TagExp.greater_equal(meas.buzz, "goo") + yield tools.assert_equal, exp, TagExp(meas.buzz, GE, "goo") + + +def test_less_equal(): + meas = Measurement.new("fizz") + exp = TagExp.less_equal(meas.buzz, "goo") + yield tools.assert_equal, exp, TagExp(meas.buzz, LE, "goo") + + +def test_like(): + meas = Measurement.new("fizz") + exp = TagExp.like(meas.buzz, "goo") + yield tools.assert_equal, exp, TagExp(meas.buzz, LK, "goo") + + +def test_notlike(): + meas = Measurement.new("fizz") + exp = TagExp.notlike(meas.buzz, "goo") + yield tools.assert_equal, exp, TagExp(meas.buzz, NK, "goo") diff --git a/tests/operations_tests.py b/tests/operations_tests.py index 253d5ff..a50ac79 100644 --- a/tests/operations_tests.py +++ b/tests/operations_tests.py @@ -1,4 +1,4 @@ -""" Test Operations. """ +""" InfluxAlchemy Operations. """ from nose import tools from influxalchemy.operations import Operation diff --git a/tests/query_tests.py b/tests/query_tests.py new file mode 100644 index 0000000..6ab5674 --- /dev/null +++ b/tests/query_tests.py @@ -0,0 +1,41 @@ +""" InfluxAlchemy Query Tests. """ + +import influxdb +import mock +from influxalchemy.client import InfluxAlchemy +from influxalchemy.measurement import Measurement +from nose import tools + + +def test_group_by(): + db = influxdb.InfluxDBClient(database="example") + client = InfluxAlchemy(db) + query = client.query(Measurement.new("fizz")).group_by("buzz") + tools.assert_equal(str(query), "SELECT * FROM fizz GROUP BY buzz;") + + +def test_filter_by(): + db = influxdb.InfluxDBClient(database="example") + client = InfluxAlchemy(db) + query = client.query(Measurement.new("fizz")).filter_by(buzz="goo") + tools.assert_equal(str(query), "SELECT * FROM fizz WHERE (buzz = 'goo');") + + +def test_tags(): + db = influxdb.InfluxDBClient(database="example") + client = InfluxAlchemy(db) + fizz = Measurement.new("fizz") + query = client.query(fizz.buzz, fizz.bug) + tools.assert_equal(str(query), "SELECT buzz, bug FROM fizz;") + + +@mock.patch("influxalchemy.InfluxAlchemy.tags") +@mock.patch("influxalchemy.InfluxAlchemy.fields") +def test_get_tags_fields(mock_fields, mock_tags): + mock_tags.return_value = ["fizz", "buzz"] + mock_fields.return_value = ["foo", "goo"] + db = influxdb.InfluxDBClient(database="example") + client = InfluxAlchemy(db) + fizz = Measurement.new("fuzz") + query = client.query(fizz) + tools.assert_equal(str(query), "SELECT fizz, buzz, foo, goo FROM fuzz;") diff --git a/tox.ini b/tox.ini index 40c37eb..45d6b21 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27, py35 +envlist = py27 [testenv] deps=