From 4c4c8f76776860fe9f264b999955ec32b47fad5d Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 03:10:50 +0900 Subject: [PATCH 01/20] Initial import --- .gitignore | 3 + .travis.yml | 10 ++ MANIFEST.in | 2 + influxdb/__init__.py | 7 ++ influxdb/client.py | 228 ++++++++++++++++++++++++++++++++++ requirements.txt | 1 + setup.py | 38 ++++++ test-requirements.txt | 2 + tests/__init__.py | 1 + tests/influxdb/__init__.py | 1 + tests/influxdb/client_test.py | 26 ++++ tox.ini | 14 +++ 12 files changed, 333 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 MANIFEST.in create mode 100644 influxdb/__init__.py create mode 100644 influxdb/client.py create mode 100644 requirements.txt create mode 100755 setup.py create mode 100644 test-requirements.txt create mode 100644 tests/__init__.py create mode 100644 tests/influxdb/__init__.py create mode 100644 tests/influxdb/client_test.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f5cb22f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +*.py.swp +.tox diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..a055493e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: python +python: + - "3.3" + - "3.2" + - "2.7" +install: + - "pip install -r requirements.txt --use-mirrors" + - "pip install -r test-requirements.txt --use-mirrors" + - "pip install --use-mirrors flake8 pep8-naming" +script: nosetests && flake8 influxdb diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..44ebdabd --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include requirements.txt +include test-requirements.txt diff --git a/influxdb/__init__.py b/influxdb/__init__.py new file mode 100644 index 00000000..40478066 --- /dev/null +++ b/influxdb/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +from influxdb.client import InfluxDBClient + + +__all__ = ['InfluxDBClient'] + +__version__ = '0.1.0' diff --git a/influxdb/client.py b/influxdb/client.py new file mode 100644 index 00000000..686d4838 --- /dev/null +++ b/influxdb/client.py @@ -0,0 +1,228 @@ +# -*- coding: utf-8 -*- +""" +python client for influxdb +""" +import requests +import json + + +class InfluxDBClient(object): + """ + InfluxDB Client + """ + def __init__(self, host, port, username, password, database): + self._host = host + self._port = port + self._username = username + self._password = password + self._database = database + self._baseurl = "http://{0}:{1}".format(self._host, self._port) + + self._headers = json.dumps({ + 'Content-type': 'application/json', + 'Accept': 'text/plain'}) + + # Change member variables + + def switch_database(self, database): + """ + Change client database + + Parameters + ---------- + database : string + """ + self._database = database + + def switch_username(self, username, password): + """ + Change client username + + Parameters + ---------- + username : string + password : string + """ + self._username = username + self._password = password + + ### + # Administration & Security + + ### + # Creating and Dropping Databases + + def create_database(self, database): + """ + Create a database + + Parameters + ---------- + database: string + database name + """ + response = requests.post("{0}/db?u={1}&p={2}".format( + self._baseurl, + self._username, + self._password), + data=json.dumps({'name': database}), + headers=self._headers) + + if response.status_code == 200: + return True + else: + raise Exception(response.content) + + def delete_database(self, database): + """ + Drop a database + + Parameters + ---------- + database: string + database name + """ + response = requests.delete("{0}/db/{1}?u={2}&p={3}".format( + self._baseurl, + database, + self._username, + self._password)) + + if response.status_code == 200: + return True + else: + raise Exception(response.content) + + ### + # Security + + ### + # Limiting User Access + + def get_database_users(self): + """ + Get list of database users + """ + response = requests.get( + "{0}/db/{1}/users?u={2}&p={3}".format( + self._baseurl, + self._database, + self._username, + self._password)) + + if response.status_code == 200: + return True + else: + raise Exception(response.content) + + def add_database_user(self, new_username, new_password): + """ + Add database user + """ + response = requests.post( + "{0}/db/{1}/users?u={2}&p={3}".format( + self._baseurl, + self._database, + self._username, + self._password), + data=json.dumps({ + 'username': new_username, + 'password': new_password}), + headers=self._headers) + + if response.status_code == 200: + return True + else: + raise Exception(response.content) + + def update_database_password(self, username, new_password): + """ + Update password + """ + response = requests.post( + "{0}/db/{1}/users/{2}?u={3}&p={4}".format( + self._baseurl, + self._database, + username, + self._username, + self._password), + data=json.dumps({ + 'password': new_password}), + headers=self._headers) + + if response.status_code == 200: + if username == self._username: + self._password = new_password + return True + else: + raise Exception(response.content) + + def delete_database_user(self, username): + """ + Delete database user + """ + response = requests.delete( + "{0}/db/{1}/users/{2}?u={3}&p={4}".format( + self._baseurl, + self._database, + username, + self._username, + self._password)) + + if response.status_code == 200: + return True + else: + raise Exception(response.content) + + ### + # Writing Data + + def write_points(self, data): + """ + Write to multiple time series names + """ + response = requests.post( + "{0}/db/{1}/series?u={2}&p={3}".format( + self._baseurl, + self._database, + self._username, + self._password), + data=json.dumps(data), + headers=self._headers) + + if response.status_code == 200: + return True + else: + raise Exception(response.content) + + def write_points_with_time_precision(self, data, time_precision='s'): + """ + Write to multiple time series names + """ + if time_precision not in ['s', 'm', 'u']: + raise Exception("Invalid time precision is given.") + + response = requests.post( + "{0}/db/{1}/series?u={2}&p={3}&time_precision={4}".format( + self._baseurl, + self._database, + self._username, + self._password, + time_precision), + data=json.dumps(data), + headers=self._headers) + + if response.status_code == 200: + return True + else: + raise Exception(response.content) + + def delete_points(self, name, + regex=None, start_epoch=None, end_epoch=None): + pass + + ### + # Regularly Scheduled Deletes + + ### + # Querying Data diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..f2293605 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +requests diff --git a/setup.py b/setup.py new file mode 100755 index 00000000..8bff30ad --- /dev/null +++ b/setup.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +try: + import distribute_setup + distribute_setup.use_setuptools() +except: + pass + +try: + from setuptools import setup, find_packages +except ImportError: + from distutils.core import setup + +import os +import re + + +with open(os.path.join(os.path.dirname(__file__), + 'influxdb', '__init__.py')) as f: + version = re.search("__version__ = '([^']+)'", f.read()).group(1) + +with open('requirements.txt', 'r') as f: + requires = [x.strip() for x in f if x.strip()] + +with open('test-requirements.txt', 'r') as f: + test_requires = [x.strip() for x in f if x.strip()] + +setup( + name='influxdb', + version=version, + description="influxdb client", + packages=find_packages(exclude=['tests']), + test_suite='tests', + tests_require=test_requires, + install_requires=requires, + extras_require={'test': test_requires}, +) diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 00000000..a6786964 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,2 @@ +nose +mock diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..40a96afc --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/tests/influxdb/__init__.py b/tests/influxdb/__init__.py new file mode 100644 index 00000000..40a96afc --- /dev/null +++ b/tests/influxdb/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/tests/influxdb/client_test.py b/tests/influxdb/client_test.py new file mode 100644 index 00000000..d61e6bce --- /dev/null +++ b/tests/influxdb/client_test.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +import requests +import nose.tools +from mock import patch + +from influxdb import InfluxDBClient + + +def _build_response_object(status_code=200, content=""): + resp = requests.Response() + resp.status_code = 200 + resp.content = content + return resp + + +class TestInfluxDBClient(object): + def test_switch_database(self): + cli = InfluxDBClient('host', 8086, 'username', 'password', 'database') + cli.switch_database('another_database') + assert cli._database == 'another_database' + + def test_switch_username(self): + cli = InfluxDBClient('host', 8086, 'username', 'password', 'database') + cli.switch_username('another_username', 'another_password') + assert cli._username == 'another_username' + assert cli._password == 'another_password' diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..f5128281 --- /dev/null +++ b/tox.ini @@ -0,0 +1,14 @@ +[tox] +envlist = py33, py27, flake8 + +[testenv] +commands = + pip install -r test-requirements.txt + nosetests + +[testenv:flake8] +deps = + flake8 + pep8-naming + +commands = flake8 influxdb From 58e749572b8e284dc382ad19ab7214a2e33f10cb Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 03:44:47 +0900 Subject: [PATCH 02/20] Update tests to check Exception --- test-requirements.txt | 1 + tests/influxdb/client_test.py | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/test-requirements.txt b/test-requirements.txt index a6786964..fac3bb36 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,2 +1,3 @@ +requests nose mock diff --git a/tests/influxdb/client_test.py b/tests/influxdb/client_test.py index d61e6bce..c32bfebc 100644 --- a/tests/influxdb/client_test.py +++ b/tests/influxdb/client_test.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- import requests -import nose.tools +from nose.tools import raises from mock import patch from influxdb import InfluxDBClient @@ -8,8 +8,8 @@ def _build_response_object(status_code=200, content=""): resp = requests.Response() - resp.status_code = 200 - resp.content = content + resp.status_code = status_code + resp._content = content return resp @@ -24,3 +24,31 @@ def test_switch_username(self): cli.switch_username('another_username', 'another_password') assert cli._username == 'another_username' assert cli._password == 'another_password' + + def test_create_database(self): + with patch.object(requests, 'post') as mocked_post: + mocked_post.return_value = _build_response_object() + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + assert cli.create_database('new_db') is True + + @raises(Exception) + def test_creata_database_fails(self): + with patch.object(requests, 'post') as mocked_post: + mocked_post.return_value = _build_response_object(status_code=401) + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.create_database('new_db') + + def test_delete_database(self): + with patch.object(requests, 'delete') as mocked_post: + mocked_post.return_value = _build_response_object() + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + assert cli.delete_database('old_db') is True + + @raises(Exception) + def test_delete_database_fails(self): + with patch.object(requests, 'delete') as mocked_post: + mocked_post.return_value = _build_response_object(status_code=401) + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.delete_database('old_db') + + From 97082cae60f878390b18a5f77bd7b84a4d1b27b2 Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 03:56:01 +0900 Subject: [PATCH 03/20] Fix bug. No need to dump headers in python-requests --- influxdb/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index 686d4838..4cbefd2b 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -18,9 +18,9 @@ def __init__(self, host, port, username, password, database): self._database = database self._baseurl = "http://{0}:{1}".format(self._host, self._port) - self._headers = json.dumps({ + self._headers = { 'Content-type': 'application/json', - 'Accept': 'text/plain'}) + 'Accept': 'text/plain'} # Change member variables From 03d39ecb425bbaf26d860c86561776d8fcc89a5d Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 03:59:06 +0900 Subject: [PATCH 04/20] Fix bug. create_database returns 201. --- influxdb/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/influxdb/client.py b/influxdb/client.py index 4cbefd2b..5729580a 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -68,7 +68,7 @@ def create_database(self, database): data=json.dumps({'name': database}), headers=self._headers) - if response.status_code == 200: + if response.status_code == 201: return True else: raise Exception(response.content) From 7a2d440ce1d8a76527cc1d5838b7ec83103c128b Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 04:02:38 +0900 Subject: [PATCH 05/20] Fix bug. delete_database returns 201. --- influxdb/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/influxdb/client.py b/influxdb/client.py index 5729580a..9683117d 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -88,7 +88,7 @@ def delete_database(self, database): self._username, self._password)) - if response.status_code == 200: + if response.status_code == 201: return True else: raise Exception(response.content) From 4463d00058e957aafb3f097f77c0ff6b4e6e7031 Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 04:06:42 +0900 Subject: [PATCH 06/20] Fix bug. delete_database returns 204 not 201 --- influxdb/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/influxdb/client.py b/influxdb/client.py index 9683117d..6e1ec264 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -88,7 +88,7 @@ def delete_database(self, database): self._username, self._password)) - if response.status_code == 201: + if response.status_code == 204: return True else: raise Exception(response.content) From 89039129f164b54170999c3b1d15ac39290da69e Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 04:21:44 +0900 Subject: [PATCH 07/20] Chanage return value of get_database_users --- influxdb/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/influxdb/client.py b/influxdb/client.py index 6e1ec264..62ce435d 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -111,7 +111,7 @@ def get_database_users(self): self._password)) if response.status_code == 200: - return True + return json.loads(response.content) else: raise Exception(response.content) From 580fc2e994603949cec19644af59310ab3ae149a Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 09:33:18 +0900 Subject: [PATCH 08/20] Udpate to handle administering requests --- influxdb/client.py | 290 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 244 insertions(+), 46 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index 62ce435d..79c300ba 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -46,11 +46,78 @@ def switch_username(self, username, password): self._username = username self._password = password - ### - # Administration & Security + # Writing Data + # + # Assuming you have a database named foo_production you can write data + # by doing a POST to /db/foo_production/series?u=some_user&p=some_password + # with a JSON body of points. + + def write_points(self, data): + """ + Write to multiple time series names + """ + response = requests.post( + "{0}/db/{1}/series?u={2}&p={3}".format( + self._baseurl, + self._database, + self._username, + self._password), + data=json.dumps(data), + headers=self._headers) + + if response.status_code == 200: + return True + else: + raise Exception(response.content) + + def write_points_with_time_precision(self, data, time_precision='s'): + """ + Write to multiple time series names + """ + if time_precision not in ['s', 'm', 'u']: + raise Exception("Invalid time precision is given.") + + response = requests.post( + "{0}/db/{1}/series?u={2}&p={3}&time_precision={4}".format( + self._baseurl, + self._database, + self._username, + self._password, + time_precision), + data=json.dumps(data), + headers=self._headers) + + if response.status_code == 200: + return True + else: + raise Exception(response.content) + + # TODO: + # One Time Deletes + + def delete_points(self, name, + regex=None, start_epoch=None, end_epoch=None): + pass + + # TODO: + # Regularly Scheduled Deletes + # get list of deletes + # curl http://localhost:8086/db/site_dev/scheduled_deletes + # + # remove a regularly scheduled delete + # curl -X DELETE http://localhost:8086/db/site_dev/scheduled_deletes/:id + + # TODO: + # Querying Data + # GET db/:name/series. It takes five parameters - ### # Creating and Dropping Databases + # + # ### create a database + # curl -X POST http://localhost:8086/db -d '{"name": "site_development"}' + # + # ### drop a database + # curl -X DELETE http://localhost:8086/db/site_development def create_database(self, database): """ @@ -93,20 +160,43 @@ def delete_database(self, database): else: raise Exception(response.content) - ### # Security + # get list of cluster admins + # curl http://localhost:8086/cluster_admins?u=root&p=root - ### - # Limiting User Access + # add cluster admin + # curl -X POST http://localhost:8086/cluster_admins?u=root&p=root \ + # -d '{"username": "paul", "password": "i write teh docz"}' - def get_database_users(self): + # update cluster admin password + # curl -X POST http://localhost:8086/cluster_admins/paul?u=root&p=root \ + # -d '{"password": "new pass"}' + + # delete cluster admin + # curl -X DELETE http://localhost:8086/cluster_admins/paul?u=root&p=root + + # Database admins, with a database name of site_dev + # get list of database admins + # curl http://localhost:8086/db/site_dev/admins?u=root&p=root + + # add database admin + # curl -X POST http://localhost:8086/db/site_dev/admins?u=root&p=root \ + # -d '{"username": "paul", "password": "i write teh docz"}' + + # update database admin password + # curl -X POST http://localhost:8086/db/site_dev/admins/paul?u=root&p=root \ + # -d '{"password": "new pass"}' + + # delete database admin + # curl -X DELETE http://localhost:8086/db/site_dev/admins/paul?u=root&p=root + + def get_list_cluster_admins(self, database): """ - Get list of database users + Get list of cluster admins """ response = requests.get( - "{0}/db/{1}/users?u={2}&p={3}".format( + "{0}/cluster_admins?u={1}&p={2}".format( self._baseurl, - self._database, self._username, self._password)) @@ -115,14 +205,13 @@ def get_database_users(self): else: raise Exception(response.content) - def add_database_user(self, new_username, new_password): + def add_cluster_admin(self, new_username, new_password): """ - Add database user + Add cluster admin """ response = requests.post( - "{0}/db/{1}/users?u={2}&p={3}".format( + "{0}/cluster_admins?u={1}&p={2}".format( self._baseurl, - self._database, self._username, self._password), data=json.dumps({ @@ -135,14 +224,13 @@ def add_database_user(self, new_username, new_password): else: raise Exception(response.content) - def update_database_password(self, username, new_password): + def update_cluster_admin_password(self, username, new_password): """ - Update password + Update cluster admin password """ response = requests.post( - "{0}/db/{1}/users/{2}?u={3}&p={4}".format( + "{0}/cluster_admins/{1}?u={2}&p={3}".format( self._baseurl, - self._database, username, self._username, self._password), @@ -151,43 +239,144 @@ def update_database_password(self, username, new_password): headers=self._headers) if response.status_code == 200: - if username == self._username: - self._password = new_password return True else: raise Exception(response.content) - def delete_database_user(self, username): + def delete_cluster_admin(self, username): """ - Delete database user + Delete cluster admin """ - response = requests.delete( - "{0}/db/{1}/users/{2}?u={3}&p={4}".format( + response = requests.delete("{0}/cluster_admin/{1}?u={2}&p={3}".format( + self._baseurl, + username, + self._username, + self._password)) + + if response.status_code == 204: + return True + else: + raise Exception(response.content) + + def get_list_database_admins(self): + """ + Get list of database admins + """ + response = requests.get( + "{0}/db/{1}/admins?u={2}&p={3}".format( self._baseurl, self._database, - username, self._username, self._password)) if response.status_code == 200: + return json.loads(response.content) + else: + raise Exception(response.content) + + def add_database_admin(self, new_username, new_password): + """ + Add cluster admin + """ + response = requests.post( + "{0}/db/{1}/admins?u={2}&p={3}".format( + self._baseurl, + self._database, + self._username, + self._password), + data=json.dumps({ + 'username': new_username, + 'password': new_password}), + headers=self._headers) + + if response.status_code == 200: + return True + else: + raise Exception(response.content) + + def update_database_admin_password(self, username, new_password): + """ + Update database admin password + """ + response = requests.post( + "{0}/db/{1}/admins/{2}?u={3}&p={4}".format( + self._baseurl, + self._database, + username, + self._username, + self._password), + data=json.dumps({ + 'password': new_password}), + headers=self._headers) + + if response.status_code == 200: + return True + else: + raise Exception(response.content) + + def delete_database_admin(self, username): + """ + Delete database admin + """ + response = requests.delete("{0}/db/{1}/admins/{2}?u={3}&p={4}".format( + self._baseurl, + self._database, + username, + self._username, + self._password)) + + if response.status_code == 204: return True else: raise Exception(response.content) ### - # Writing Data + # Limiting User Access - def write_points(self, data): + # Database users + # get list of database users + # curl http://localhost:8086/db/site_dev/users?u=root&p=root + + # add database user + # curl -X POST http://localhost:8086/db/site_dev/users?u=root&p=root \ + # -d '{"username": "paul", "password": "i write teh docz"}' + + # update database user password + # curl -X POST http://localhost:8086/db/site_dev/users/paul?u=root&p=root \ + # -d '{"password": "new pass"}' + + # delete database user + # curl -X DELETE http://localhost:8086/db/site_dev/users/paul?u=root&p=root + + def get_database_users(self): """ - Write to multiple time series names + Get list of database users + """ + response = requests.get( + "{0}/db/{1}/users?u={2}&p={3}".format( + self._baseurl, + self._database, + self._username, + self._password)) + + if response.status_code == 200: + return json.loads(response.content) + else: + raise Exception(response.content) + + def add_database_user(self, new_username, new_password): + """ + Add database user """ response = requests.post( - "{0}/db/{1}/series?u={2}&p={3}".format( + "{0}/db/{1}/users?u={2}&p={3}".format( self._baseurl, self._database, self._username, self._password), - data=json.dumps(data), + data=json.dumps({ + 'username': new_username, + 'password': new_password}), headers=self._headers) if response.status_code == 200: @@ -195,34 +384,43 @@ def write_points(self, data): else: raise Exception(response.content) - def write_points_with_time_precision(self, data, time_precision='s'): + def update_database_password(self, username, new_password): """ - Write to multiple time series names + Update password """ - if time_precision not in ['s', 'm', 'u']: - raise Exception("Invalid time precision is given.") - response = requests.post( - "{0}/db/{1}/series?u={2}&p={3}&time_precision={4}".format( + "{0}/db/{1}/users/{2}?u={3}&p={4}".format( self._baseurl, self._database, + username, self._username, - self._password, - time_precision), - data=json.dumps(data), + self._password), + data=json.dumps({ + 'password': new_password}), headers=self._headers) if response.status_code == 200: + if username == self._username: + self._password = new_password return True else: raise Exception(response.content) - def delete_points(self, name, - regex=None, start_epoch=None, end_epoch=None): - pass + def delete_database_user(self, username): + """ + Delete database user + """ + response = requests.delete( + "{0}/db/{1}/users/{2}?u={3}&p={4}".format( + self._baseurl, + self._database, + username, + self._username, + self._password)) - ### - # Regularly Scheduled Deletes + if response.status_code == 200: + return True + else: + raise Exception(response.content) - ### - # Querying Data + # TODO: Change read/write permission From 0265440d8fc5584a4a9876bdfddf73680de74e83 Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 09:54:36 +0900 Subject: [PATCH 09/20] Update testcases (use 201 or 204) --- influxdb/client.py | 42 +++++++++++++++++++---------------- tests/influxdb/client_test.py | 4 ++-- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index 79c300ba..41daaf49 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -68,7 +68,7 @@ def write_points(self, data): if response.status_code == 200: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) def write_points_with_time_precision(self, data, time_precision='s'): """ @@ -90,7 +90,7 @@ def write_points_with_time_precision(self, data, time_precision='s'): if response.status_code == 200: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) # TODO: # One Time Deletes @@ -138,7 +138,7 @@ def create_database(self, database): if response.status_code == 201: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) def delete_database(self, database): """ @@ -158,7 +158,7 @@ def delete_database(self, database): if response.status_code == 204: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) # Security # get list of cluster admins @@ -190,7 +190,7 @@ def delete_database(self, database): # delete database admin # curl -X DELETE http://localhost:8086/db/site_dev/admins/paul?u=root&p=root - def get_list_cluster_admins(self, database): + def get_list_cluster_admins(self): """ Get list of cluster admins """ @@ -203,7 +203,7 @@ def get_list_cluster_admins(self, database): if response.status_code == 200: return json.loads(response.content) else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) def add_cluster_admin(self, new_username, new_password): """ @@ -222,7 +222,7 @@ def add_cluster_admin(self, new_username, new_password): if response.status_code == 200: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) def update_cluster_admin_password(self, username, new_password): """ @@ -241,13 +241,13 @@ def update_cluster_admin_password(self, username, new_password): if response.status_code == 200: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) def delete_cluster_admin(self, username): """ Delete cluster admin """ - response = requests.delete("{0}/cluster_admin/{1}?u={2}&p={3}".format( + response = requests.delete("{0}/cluster_admins/{1}?u={2}&p={3}".format( self._baseurl, username, self._username, @@ -256,8 +256,9 @@ def delete_cluster_admin(self, username): if response.status_code == 204: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) + # TODO: Not working def get_list_database_admins(self): """ Get list of database admins @@ -272,8 +273,9 @@ def get_list_database_admins(self): if response.status_code == 200: return json.loads(response.content) else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) + # TODO: Not working def add_database_admin(self, new_username, new_password): """ Add cluster admin @@ -292,8 +294,9 @@ def add_database_admin(self, new_username, new_password): if response.status_code == 200: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) + # TODO: Not working def update_database_admin_password(self, username, new_password): """ Update database admin password @@ -312,8 +315,9 @@ def update_database_admin_password(self, username, new_password): if response.status_code == 200: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) + # TODO: Not working def delete_database_admin(self, username): """ Delete database admin @@ -328,7 +332,7 @@ def delete_database_admin(self, username): if response.status_code == 204: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) ### # Limiting User Access @@ -362,7 +366,7 @@ def get_database_users(self): if response.status_code == 200: return json.loads(response.content) else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) def add_database_user(self, new_username, new_password): """ @@ -382,9 +386,9 @@ def add_database_user(self, new_username, new_password): if response.status_code == 200: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) - def update_database_password(self, username, new_password): + def update_database_user_password(self, username, new_password): """ Update password """ @@ -404,7 +408,7 @@ def update_database_password(self, username, new_password): self._password = new_password return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) def delete_database_user(self, username): """ @@ -421,6 +425,6 @@ def delete_database_user(self, username): if response.status_code == 200: return True else: - raise Exception(response.content) + raise Exception("{0}: {1}".format(response.status_code, response.content)) # TODO: Change read/write permission diff --git a/tests/influxdb/client_test.py b/tests/influxdb/client_test.py index c32bfebc..250658ea 100644 --- a/tests/influxdb/client_test.py +++ b/tests/influxdb/client_test.py @@ -27,7 +27,7 @@ def test_switch_username(self): def test_create_database(self): with patch.object(requests, 'post') as mocked_post: - mocked_post.return_value = _build_response_object() + mocked_post.return_value = _build_response_object(status_code=201) cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') assert cli.create_database('new_db') is True @@ -40,7 +40,7 @@ def test_creata_database_fails(self): def test_delete_database(self): with patch.object(requests, 'delete') as mocked_post: - mocked_post.return_value = _build_response_object() + mocked_post.return_value = _build_response_object(status_code=204) cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') assert cli.delete_database('old_db') is True From c10a7a9bee71c825a4bd81781bb64461e8e34ae6 Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 10:47:16 +0900 Subject: [PATCH 10/20] Declare methods (not implemented). --- influxdb/client.py | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index 41daaf49..60ca8fa4 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -92,24 +92,49 @@ def write_points_with_time_precision(self, data, time_precision='s'): else: raise Exception("{0}: {1}".format(response.status_code, response.content)) - # TODO: # One Time Deletes def delete_points(self, name, regex=None, start_epoch=None, end_epoch=None): - pass + """ + TODO: One Time Deletes + """ + raise NotImplemented() - # TODO: # Regularly Scheduled Deletes + + def create_scheduled_delete(self, json_body): + """ + TODO: Create scheduled delete + """ + raise NotImplemented() + # get list of deletes # curl http://localhost:8086/db/site_dev/scheduled_deletes # # remove a regularly scheduled delete # curl -X DELETE http://localhost:8086/db/site_dev/scheduled_deletes/:id - # TODO: + def get_list_scheduled_delete(self): + """ + TODO: Get list of scheduled deletes + """ + raise NotImplemented() + + def remove_scheduled_delete(self, delete_id): + """ + TODO: Remove scheduled delete + """ + raise NotImplemented() + # Querying Data + # # GET db/:name/series. It takes five parameters + def query(self, query, time_precision, chunked=False): + """ + TODO: Quering data + """ + raise NotImplemented() # Creating and Dropping Databases # @@ -427,4 +452,10 @@ def delete_database_user(self, username): else: raise Exception("{0}: {1}".format(response.status_code, response.content)) - # TODO: Change read/write permission + # update the user by POSTing to db/site_dev/users/paul + + def update_permission(self, json_body): + """ + TODO: Update read/write permission + """ + raise NotImplemented() From 46818fb8e954127c37e9626fb8f756f19ee2c175 Mon Sep 17 00:00:00 2001 From: smly Date: Thu, 7 Nov 2013 11:53:12 +0900 Subject: [PATCH 11/20] Implement query method --- .gitignore | 1 + .travis.yml | 3 +-- README.md | 15 ++++++++++++ influxdb/client.py | 43 ++++++++++++++++++++++++++++------- tests/influxdb/client_test.py | 8 +++---- tox.ini | 2 +- 6 files changed, 57 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index f5cb22f3..a90b1009 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +influxdb.egg-info/ *.pyc *.py.swp .tox diff --git a/.travis.yml b/.travis.yml index a055493e..bb686f7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,5 +6,4 @@ python: install: - "pip install -r requirements.txt --use-mirrors" - "pip install -r test-requirements.txt --use-mirrors" - - "pip install --use-mirrors flake8 pep8-naming" -script: nosetests && flake8 influxdb +script: nosetests diff --git a/README.md b/README.md index 9976fe41..feeff885 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,18 @@ influxdb-python =============== Python client for InfluxDB + +For developers +-------------- + +To test influxdb-python with multiple version of Python, you can use tox: + +```` +$ tox +```` + +If you don't have all Python version listed in tox.ini, then + +```` +$ tox -e py27 +```` diff --git a/influxdb/client.py b/influxdb/client.py index 60ca8fa4..15c5dce6 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -4,6 +4,7 @@ """ import requests import json +import urllib class InfluxDBClient(object): @@ -24,7 +25,7 @@ def __init__(self, host, port, username, password, database): # Change member variables - def switch_database(self, database): + def switch_db(self, database): """ Change client database @@ -34,7 +35,7 @@ def switch_database(self, database): """ self._database = database - def switch_username(self, username, password): + def switch_user(self, username, password): """ Change client username @@ -75,10 +76,11 @@ def write_points_with_time_precision(self, data, time_precision='s'): Write to multiple time series names """ if time_precision not in ['s', 'm', 'u']: - raise Exception("Invalid time precision is given.") + raise Exception("Invalid time precision is given. (use 's','m' or 'u')") - response = requests.post( - "{0}/db/{1}/series?u={2}&p={3}&time_precision={4}".format( + url_format = "{0}/db/{1}/series?u={2}&p={3}&time_precision={4}" + + response = requests.post(url_format.format( self._baseurl, self._database, self._username, @@ -130,11 +132,36 @@ def remove_scheduled_delete(self, delete_id): # Querying Data # # GET db/:name/series. It takes five parameters - def query(self, query, time_precision, chunked=False): + def query(self, query, time_precision='s', chunked=False): """ - TODO: Quering data + Quering data """ - raise NotImplemented() + if time_precision not in ['s', 'm', 'u']: + raise Exception("Invalid time precision is given. (use 's','m' or 'u')") + + if chunked is True: + chunked_param = 'true' + else: + chunked_param = 'false' + + encoded_query = urllib.urlencode(query) + + url_format = "{0}/db/{1}/series?q={2}&u={3}&p={4}" + url_format += "&time_precision={5}&chunked={6}" + + response = requests.get(url_format.format( + self._baseurl, + self._database, + encoded_query, + self._username, + self._password, + time_precision, + chunked_param)) + + if response.status_code == 200: + return response.content + else: + raise Exception("{0}: {1}".format(response.status_code, response.content)) # Creating and Dropping Databases # diff --git a/tests/influxdb/client_test.py b/tests/influxdb/client_test.py index 250658ea..63ad28c6 100644 --- a/tests/influxdb/client_test.py +++ b/tests/influxdb/client_test.py @@ -14,14 +14,14 @@ def _build_response_object(status_code=200, content=""): class TestInfluxDBClient(object): - def test_switch_database(self): + def test_switch_db(self): cli = InfluxDBClient('host', 8086, 'username', 'password', 'database') - cli.switch_database('another_database') + cli.switch_db('another_database') assert cli._database == 'another_database' - def test_switch_username(self): + def test_switch_user(self): cli = InfluxDBClient('host', 8086, 'username', 'password', 'database') - cli.switch_username('another_username', 'another_password') + cli.switch_user('another_username', 'another_password') assert cli._username == 'another_username' assert cli._password == 'another_password' diff --git a/tox.ini b/tox.ini index f5128281..237ffa90 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py33, py27, flake8 +envlist = py32, py27, flake8 [testenv] commands = From 494e654903c09c2916ea62622631796a426bf9c7 Mon Sep 17 00:00:00 2001 From: smly Date: Thu, 7 Nov 2013 13:49:10 +0900 Subject: [PATCH 12/20] Fix bug in query parameter --- influxdb/client.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index 15c5dce6..5a020682 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -144,9 +144,10 @@ def query(self, query, time_precision='s', chunked=False): else: chunked_param = 'false' - encoded_query = urllib.urlencode(query) + encoded_query = urllib.urlencode({ + 'q': query}) - url_format = "{0}/db/{1}/series?q={2}&u={3}&p={4}" + url_format = "{0}/db/{1}/series?{2}&u={3}&p={4}" url_format += "&time_precision={5}&chunked={6}" response = requests.get(url_format.format( From 8afb8e2a474b3cfb4d4f3e9a1defcaab6e37d986 Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 22:35:35 +0900 Subject: [PATCH 13/20] Fix indent. Impl delete method --- influxdb/client.py | 57 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index 5a020682..fd6ca45d 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -69,39 +69,61 @@ def write_points(self, data): if response.status_code == 200: return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) def write_points_with_time_precision(self, data, time_precision='s'): """ Write to multiple time series names """ if time_precision not in ['s', 'm', 'u']: - raise Exception("Invalid time precision is given. (use 's','m' or 'u')") + raise Exception( + "Invalid time precision is given. (use 's','m' or 'u')") url_format = "{0}/db/{1}/series?u={2}&p={3}&time_precision={4}" response = requests.post(url_format.format( - self._baseurl, - self._database, - self._username, - self._password, - time_precision), + self._baseurl, + self._database, + self._username, + self._password, + time_precision), data=json.dumps(data), headers=self._headers) if response.status_code == 200: return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) # One Time Deletes def delete_points(self, name, regex=None, start_epoch=None, end_epoch=None): """ - TODO: One Time Deletes + Delete a range of data """ - raise NotImplemented() + url_format = "{0}/db/{1}/series?u={2}&p={3}" + url_format += "&name={4}" + if regex is not None: + url_format += "®ex=" + regex + if start_epoch is not None: + url_format += "&start=" + start_epoch + if end_epoch is not None: + url_format += "&end=" + end_epoch + + response = requests.delete(url_format.format( + self._baseurl, + self._database, + self._username, + self._password, + name)) + if response.status_code == 200: + return True + else: + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) # Regularly Scheduled Deletes @@ -137,7 +159,8 @@ def query(self, query, time_precision='s', chunked=False): Quering data """ if time_precision not in ['s', 'm', 'u']: - raise Exception("Invalid time precision is given. (use 's','m' or 'u')") + raise Exception( + "Invalid time precision is given. (use 's','m' or 'u')") if chunked is True: chunked_param = 'true' @@ -162,7 +185,8 @@ def query(self, query, time_precision='s', chunked=False): if response.status_code == 200: return response.content else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) # Creating and Dropping Databases # @@ -211,7 +235,8 @@ def delete_database(self, database): if response.status_code == 204: return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) # Security # get list of cluster admins @@ -256,7 +281,8 @@ def get_list_cluster_admins(self): if response.status_code == 200: return json.loads(response.content) else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) def add_cluster_admin(self, new_username, new_password): """ @@ -275,7 +301,8 @@ def add_cluster_admin(self, new_username, new_password): if response.status_code == 200: return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) def update_cluster_admin_password(self, username, new_password): """ From e6c454c03f6cc143e394d5e8fd594a23a3fea082 Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 23:29:14 +0900 Subject: [PATCH 14/20] Scheduled deletions are not implemented. Comment out them --- influxdb/client.py | 277 +++++++++++++++++++++++++-------------------- 1 file changed, 155 insertions(+), 122 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index fd6ca45d..aff3ea48 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -97,59 +97,42 @@ def write_points_with_time_precision(self, data, time_precision='s'): raise Exception( "{0}: {1}".format(response.status_code, response.content)) - # One Time Deletes - - def delete_points(self, name, - regex=None, start_epoch=None, end_epoch=None): - """ - Delete a range of data - """ - url_format = "{0}/db/{1}/series?u={2}&p={3}" - url_format += "&name={4}" - if regex is not None: - url_format += "®ex=" + regex - if start_epoch is not None: - url_format += "&start=" + start_epoch - if end_epoch is not None: - url_format += "&end=" + end_epoch - - response = requests.delete(url_format.format( - self._baseurl, - self._database, - self._username, - self._password, - name)) - if response.status_code == 200: - return True - else: - raise Exception( - "{0}: {1}".format(response.status_code, response.content)) - - # Regularly Scheduled Deletes - - def create_scheduled_delete(self, json_body): - """ - TODO: Create scheduled delete - """ - raise NotImplemented() - - # get list of deletes - # curl http://localhost:8086/db/site_dev/scheduled_deletes - # - # remove a regularly scheduled delete - # curl -X DELETE http://localhost:8086/db/site_dev/scheduled_deletes/:id - - def get_list_scheduled_delete(self): - """ - TODO: Get list of scheduled deletes - """ - raise NotImplemented() - - def remove_scheduled_delete(self, delete_id): - """ - TODO: Remove scheduled delete - """ - raise NotImplemented() +# # One Time Deletes +# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 +# # see also: src/api/http/api.go:l57) +# def delete_points(self, name, +# regex=None, start_epoch=None, end_epoch=None): +# """ +# TODO: Delete a range of data +# """ +# raise NotImplemented() +# +# # Regularly Scheduled Deletes +# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 +# # see also: src/api/http/api.go:l57) +# def create_scheduled_delete(self, json_body): +# """ +# TODO: Create scheduled delete +# """ +# raise NotImplemented() +# +# # get list of deletes +# # curl http://localhost:8086/db/site_dev/scheduled_deletes +# # +# # remove a regularly scheduled delete +# # curl -X DELETE http://localhost:8086/db/site_dev/scheduled_deletes/:id +# +# def get_list_scheduled_delete(self): +# """ +# TODO: Get list of scheduled deletes +# """ +# raise NotImplemented() +# +# def remove_scheduled_delete(self, delete_id): +# """ +# TODO: Remove scheduled delete +# """ +# raise NotImplemented() # Querying Data # @@ -215,7 +198,8 @@ def create_database(self, database): if response.status_code == 201: return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) def delete_database(self, database): """ @@ -321,7 +305,8 @@ def update_cluster_admin_password(self, username, new_password): if response.status_code == 200: return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) def delete_cluster_admin(self, username): """ @@ -336,83 +321,127 @@ def delete_cluster_admin(self, username): if response.status_code == 204: return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) - - # TODO: Not working - def get_list_database_admins(self): - """ - Get list of database admins - """ - response = requests.get( - "{0}/db/{1}/admins?u={2}&p={3}".format( - self._baseurl, - self._database, - self._username, - self._password)) - - if response.status_code == 200: - return json.loads(response.content) - else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) - # TODO: Not working - def add_database_admin(self, new_username, new_password): + def set_database_admin(self, username): """ - Add cluster admin + Set user as database admin """ response = requests.post( - "{0}/db/{1}/admins?u={2}&p={3}".format( + "{0}/db/{1}/admins/{2}?u={3}&p={4}".format( self._baseurl, self._database, + username, self._username, - self._password), - data=json.dumps({ - 'username': new_username, - 'password': new_password}), - headers=self._headers) - - if response.status_code == 200: + self._password)) + if response.status_code == 204: return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) - # TODO: Not working - def update_database_admin_password(self, username, new_password): + def unset_database_admin(self, username): """ - Update database admin password + Unset user as database admin """ - response = requests.post( + response = requests.delete( "{0}/db/{1}/admins/{2}?u={3}&p={4}".format( self._baseurl, self._database, username, self._username, - self._password), - data=json.dumps({ - 'password': new_password}), - headers=self._headers) - - if response.status_code == 200: + self._password)) + if response.status_code == 204: return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) - # TODO: Not working - def delete_database_admin(self, username): - """ - Delete database admin - """ - response = requests.delete("{0}/db/{1}/admins/{2}?u={3}&p={4}".format( - self._baseurl, - self._database, - username, - self._username, - self._password)) - if response.status_code == 204: - return True - else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) +# # TODO: Not working +# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 +# # see also: src/api/http/api.go:l57) +# def get_list_database_admins(self): +# """ +# Get list of database admins +# """ +# response = requests.get( +# "{0}/db/{1}/admins?u={2}&p={3}".format( +# self._baseurl, +# self._database, +# self._username, +# self._password)) +# +# if response.status_code == 200: +# return json.loads(response.content) +# else: +# raise Exception("{0}: {1}".format(response.status_code, response.content)) +# +# # TODO: Not working +# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 +# # see also: src/api/http/api.go:l57) +# def add_database_admin(self, new_username, new_password): +# """ +# Add cluster admin +# """ +# response = requests.post( +# "{0}/db/{1}/admins?u={2}&p={3}".format( +# self._baseurl, +# self._database, +# self._username, +# self._password), +# data=json.dumps({ +# 'username': new_username, +# 'password': new_password}), +# headers=self._headers) +# +# if response.status_code == 200: +# return True +# else: +# raise Exception("{0}: {1}".format(response.status_code, response.content)) +# +# # TODO: Not working +# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 +# # see also: src/api/http/api.go:l57) +# def update_database_admin_password(self, username, new_password): +# """ +# Update database admin password +# """ +# response = requests.post( +# "{0}/db/{1}/admins/{2}?u={3}&p={4}".format( +# self._baseurl, +# self._database, +# username, +# self._username, +# self._password), +# data=json.dumps({ +# 'password': new_password}), +# headers=self._headers) +# +# if response.status_code == 200: +# return True +# else: +# raise Exception("{0}: {1}".format(response.status_code, response.content)) +# +# # TODO: Not working +# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 +# # see also: src/api/http/api.go:l57) +# def delete_database_admin(self, username): +# """ +# Delete database admin +# """ +# response = requests.delete("{0}/db/{1}/admins/{2}?u={3}&p={4}".format( +# self._baseurl, +# self._database, +# username, +# self._username, +# self._password)) +# +# if response.status_code == 204: +# return True +# else: +# raise Exception("{0}: {1}".format(response.status_code, response.content)) ### # Limiting User Access @@ -446,7 +475,8 @@ def get_database_users(self): if response.status_code == 200: return json.loads(response.content) else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) def add_database_user(self, new_username, new_password): """ @@ -466,7 +496,8 @@ def add_database_user(self, new_username, new_password): if response.status_code == 200: return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) def update_database_user_password(self, username, new_password): """ @@ -488,7 +519,8 @@ def update_database_user_password(self, username, new_password): self._password = new_password return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) def delete_database_user(self, username): """ @@ -505,12 +537,13 @@ def delete_database_user(self, username): if response.status_code == 200: return True else: - raise Exception("{0}: {1}".format(response.status_code, response.content)) - - # update the user by POSTing to db/site_dev/users/paul + raise Exception( + "{0}: {1}".format(response.status_code, response.content)) - def update_permission(self, json_body): - """ - TODO: Update read/write permission - """ - raise NotImplemented() +# # update the user by POSTing to db/site_dev/users/paul +# +# def update_permission(self, json_body): +# """ +# TODO: Update read/write permission +# """ +# raise NotImplemented() From 3a24c5281865b219d45b455d847c24cef0103e19 Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 23:39:57 +0900 Subject: [PATCH 15/20] unset/setDbAdmin returns 200, not 204 --- influxdb/client.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index aff3ea48..cf86a6b6 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -335,7 +335,7 @@ def set_database_admin(self, username): username, self._username, self._password)) - if response.status_code == 204: + if response.status_code == 200: return True else: raise Exception( @@ -352,7 +352,7 @@ def unset_database_admin(self, username): username, self._username, self._password)) - if response.status_code == 204: + if response.status_code == 200: return True else: raise Exception( @@ -541,6 +541,8 @@ def delete_database_user(self, username): "{0}: {1}".format(response.status_code, response.content)) # # update the user by POSTing to db/site_dev/users/paul +# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 +# # see also: src/api/http/api.go:l57) # # def update_permission(self, json_body): # """ From acc27c3637af3ddee5565c2cefb0cb858ffc2be8 Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Thu, 7 Nov 2013 23:59:44 +0900 Subject: [PATCH 16/20] Use NotImplementedError exceptions --- influxdb/client.py | 238 ++++++++++++++++++++------------------------- 1 file changed, 106 insertions(+), 132 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index cf86a6b6..7a788ad3 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -2,16 +2,21 @@ """ python client for influxdb """ -import requests import json import urllib +import requests + class InfluxDBClient(object): """ InfluxDB Client """ + def __init__(self, host, port, username, password, database): + """ + Initialize client + """ self._host = host self._port = port self._username = username @@ -72,7 +77,7 @@ def write_points(self, data): raise Exception( "{0}: {1}".format(response.status_code, response.content)) - def write_points_with_time_precision(self, data, time_precision='s'): + def write_points_with_precision(self, data, time_precision='s'): """ Write to multiple time series names """ @@ -97,42 +102,56 @@ def write_points_with_time_precision(self, data, time_precision='s'): raise Exception( "{0}: {1}".format(response.status_code, response.content)) -# # One Time Deletes -# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 -# # see also: src/api/http/api.go:l57) -# def delete_points(self, name, -# regex=None, start_epoch=None, end_epoch=None): -# """ -# TODO: Delete a range of data -# """ -# raise NotImplemented() -# -# # Regularly Scheduled Deletes -# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 -# # see also: src/api/http/api.go:l57) -# def create_scheduled_delete(self, json_body): -# """ -# TODO: Create scheduled delete -# """ -# raise NotImplemented() -# -# # get list of deletes -# # curl http://localhost:8086/db/site_dev/scheduled_deletes -# # -# # remove a regularly scheduled delete -# # curl -X DELETE http://localhost:8086/db/site_dev/scheduled_deletes/:id -# -# def get_list_scheduled_delete(self): -# """ -# TODO: Get list of scheduled deletes -# """ -# raise NotImplemented() -# -# def remove_scheduled_delete(self, delete_id): -# """ -# TODO: Remove scheduled delete -# """ -# raise NotImplemented() + # One Time Deletes + + # todo + def delete_points(self, name, + regex=None, start_epoch=None, end_epoch=None): + """ + Delete a range of data + + This endpoint has been not implemented yet in InfluxDB ver0.0.8 + See also: src/api/http/api.go:l57 + """ + raise NotImplementedError() + + # Regularly Scheduled Deletes + + # todo + def create_scheduled_delete(self, json_body): + """ + Create scheduled delete + + This endpoint has been not implemented yet in InfluxDB ver0.0.8 + See also: src/api/http/api.go:l57 + """ + raise NotImplementedError() + + # get list of deletes + # curl http://localhost:8086/db/site_dev/scheduled_deletes + # + # remove a regularly scheduled delete + # curl -X DELETE http://localhost:8086/db/site_dev/scheduled_deletes/:id + + # todo + def get_list_scheduled_delete(self): + """ + Get list of scheduled deletes + + This endpoint has been not implemented yet in InfluxDB ver0.0.8 + See also: src/api/http/api.go:l57 + """ + raise NotImplementedError() + + # todo + def remove_scheduled_delete(self, delete_id): + """ + Remove scheduled delete + + This endpoint has been not implemented yet in InfluxDB ver0.0.8 + See also: src/api/http/api.go:l57 + """ + raise NotImplementedError() # Querying Data # @@ -246,11 +265,12 @@ def delete_database(self, database): # -d '{"username": "paul", "password": "i write teh docz"}' # update database admin password - # curl -X POST http://localhost:8086/db/site_dev/admins/paul?u=root&p=root \ + # curl -X POST http://localhost:8086/db/site_dev/admins/paul?u=root&p=root\ # -d '{"password": "new pass"}' # delete database admin - # curl -X DELETE http://localhost:8086/db/site_dev/admins/paul?u=root&p=root + # curl -X DELETE \ + # http://localhost:8086/db/site_dev/admins/paul?u=root&p=root def get_list_cluster_admins(self): """ @@ -358,90 +378,45 @@ def unset_database_admin(self, username): raise Exception( "{0}: {1}".format(response.status_code, response.content)) + # todo + def get_list_database_admins(self): + """ + Get list of database admins -# # TODO: Not working -# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 -# # see also: src/api/http/api.go:l57) -# def get_list_database_admins(self): -# """ -# Get list of database admins -# """ -# response = requests.get( -# "{0}/db/{1}/admins?u={2}&p={3}".format( -# self._baseurl, -# self._database, -# self._username, -# self._password)) -# -# if response.status_code == 200: -# return json.loads(response.content) -# else: -# raise Exception("{0}: {1}".format(response.status_code, response.content)) -# -# # TODO: Not working -# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 -# # see also: src/api/http/api.go:l57) -# def add_database_admin(self, new_username, new_password): -# """ -# Add cluster admin -# """ -# response = requests.post( -# "{0}/db/{1}/admins?u={2}&p={3}".format( -# self._baseurl, -# self._database, -# self._username, -# self._password), -# data=json.dumps({ -# 'username': new_username, -# 'password': new_password}), -# headers=self._headers) -# -# if response.status_code == 200: -# return True -# else: -# raise Exception("{0}: {1}".format(response.status_code, response.content)) -# -# # TODO: Not working -# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 -# # see also: src/api/http/api.go:l57) -# def update_database_admin_password(self, username, new_password): -# """ -# Update database admin password -# """ -# response = requests.post( -# "{0}/db/{1}/admins/{2}?u={3}&p={4}".format( -# self._baseurl, -# self._database, -# username, -# self._username, -# self._password), -# data=json.dumps({ -# 'password': new_password}), -# headers=self._headers) -# -# if response.status_code == 200: -# return True -# else: -# raise Exception("{0}: {1}".format(response.status_code, response.content)) -# -# # TODO: Not working -# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 -# # see also: src/api/http/api.go:l57) -# def delete_database_admin(self, username): -# """ -# Delete database admin -# """ -# response = requests.delete("{0}/db/{1}/admins/{2}?u={3}&p={4}".format( -# self._baseurl, -# self._database, -# username, -# self._username, -# self._password)) -# -# if response.status_code == 204: -# return True -# else: -# raise Exception("{0}: {1}".format(response.status_code, response.content)) + This endpoint has been not implemented yet in InfluxDB ver0.0.8 + See also: src/api/http/api.go:l57 + """ + raise NotImplementedError() + + # todo + def add_database_admin(self, new_username, new_password): + """ + Add cluster admin + + This endpoint has been not implemented yet in InfluxDB ver0.0.8 + See also: src/api/http/api.go:l57 + """ + raise NotImplementedError() + + # todo + def update_database_admin_password(self, username, new_password): + """ + Update database admin password + + This endpoint has been not implemented yet in InfluxDB ver0.0.8 + See also: src/api/http/api.go:l57 + """ + raise NotImplementedError() + + # todo + def delete_database_admin(self, username): + """ + Delete database admin + + This endpoint has been not implemented yet in InfluxDB ver0.0.8 + See also: src/api/http/api.go:l57 + """ + raise NotImplementedError() ### # Limiting User Access @@ -540,12 +515,11 @@ def delete_database_user(self, username): raise Exception( "{0}: {1}".format(response.status_code, response.content)) -# # update the user by POSTing to db/site_dev/users/paul -# # (I guess this endpoint is not implemented in InfluxDB v0.0.7 -# # see also: src/api/http/api.go:l57) -# -# def update_permission(self, json_body): -# """ -# TODO: Update read/write permission -# """ -# raise NotImplemented() + # update the user by POSTing to db/site_dev/users/paul + + # todo + def update_permission(self, json_body): + """ + Update read/write permission + """ + raise NotImplementedError() From 5ead1d8c4583ef2acf90334c1f1319ee0c4d6931 Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Fri, 8 Nov 2013 10:50:08 +0900 Subject: [PATCH 17/20] Update unit tests --- influxdb/client.py | 2 +- tests/influxdb/client_test.py | 127 ++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 1 deletion(-) diff --git a/influxdb/client.py b/influxdb/client.py index 7a788ad3..cc262e15 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -518,7 +518,7 @@ def delete_database_user(self, username): # update the user by POSTing to db/site_dev/users/paul # todo - def update_permission(self, json_body): + def update_permission(self, username, json_body): """ Update read/write permission """ diff --git a/tests/influxdb/client_test.py b/tests/influxdb/client_test.py index 63ad28c6..987a0605 100644 --- a/tests/influxdb/client_test.py +++ b/tests/influxdb/client_test.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +""" +unit tests +""" import requests from nose.tools import raises from mock import patch @@ -25,6 +28,77 @@ def test_switch_user(self): assert cli._username == 'another_username' assert cli._password == 'another_password' + def test_write_points(self): + data = [ + { + "points": [ + ["1", 1, 1.0], + ["2", 2, 2.0] + ], + "name": "foo", + "columns": ["column_one", "column_two", "column_three"] + } + ] + + with patch.object(requests, 'post') as mocked_post: + mocked_post.return_value = _build_response_object(status_code=200) + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + assert cli.write_points(data) is True + + @raises(Exception) + def test_write_points_fails(self): + with patch.object(requests, 'post') as mocked_post: + mocked_post.return_value = _build_response_object(status_code=500) + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.write_points([]) + + def test_write_points_with_precision(self): + data = [ + { + "points": [ + ["1", 1, 1.0], + ["2", 2, 2.0] + ], + "name": "foo", + "columns": ["column_one", "column_two", "column_three"] + } + ] + + with patch.object(requests, 'post') as mocked_post: + mocked_post.return_value = _build_response_object(status_code=200) + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + assert cli.write_points_with_precision(data) is True + + @raises(Exception) + def test_write_points_with_precision_fails(self): + with patch.object(requests, 'post') as mocked_post: + mocked_post.return_value = _build_response_object(status_code=500) + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.write_points_with_precision([]) + + @raises(NotImplementedError) + def test_delete_points(self): + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.delete_points([]) + + @raises(NotImplementedError) + def test_create_scheduled_delete(self): + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.create_scheduled_delete([]) + + @raises(NotImplementedError) + def test_get_list_scheduled_delete(self): + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.get_list_scheduled_delete() + + @raises(NotImplementedError) + def test_remove_scheduled_delete(self): + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.remove_scheduled_delete(1) + + def test_query(self): + pass + def test_create_database(self): with patch.object(requests, 'post') as mocked_post: mocked_post.return_value = _build_response_object(status_code=201) @@ -51,4 +125,57 @@ def test_delete_database_fails(self): cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') cli.delete_database('old_db') + def test_get_list_cluster_admins(self): + pass + + def test_add_cluster_admin(self): + pass + + def test_update_cluster_admin_password(self): + pass + + def test_delete_cluster_admin(self): + pass + + def test_set_database_admin(self): + pass + + def test_unset_database_admin(self): + pass + + @raises(NotImplementedError) + def test_get_list_database_admins(self): + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.get_list_database_admins() + + @raises(NotImplementedError) + def test_add_database_admin(self): + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.add_database_admin('admin', 'admin_secret_password') + + @raises(NotImplementedError) + def test_update_database_admin_password(self): + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.update_database_admin_password('admin', 'admin_secret_password') + + @raises(NotImplementedError) + def test_delete_database_admin(self): + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.delete_database_admin('admin') + + def test_get_database_user(self): + pass + + def test_add_database_user(self): + pass + + def test_update_database_user_password(self): + pass + + def test_delete_database_user(self): + pass + @raises(NotImplementedError) + def test_update_permission(self): + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.update_permission('admin', []) From 56cab640303a018189dbde70b117078bc860f8ac Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Fri, 8 Nov 2013 10:58:58 +0900 Subject: [PATCH 18/20] Update docstring of unimplemented API --- influxdb/client.py | 55 ++++++++++++++++++++++++---------------------- tox.ini | 2 +- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index cc262e15..edaf4c1f 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -104,25 +104,25 @@ def write_points_with_precision(self, data, time_precision='s'): # One Time Deletes - # todo def delete_points(self, name, regex=None, start_epoch=None, end_epoch=None): """ - Delete a range of data + TODO: Delete a range of data - This endpoint has been not implemented yet in InfluxDB ver0.0.8 + 2013-11-08: This endpoint has not been implemented yet in ver0.0.8, + but it is documented in http://influxdb.org/docs/api/http.html. See also: src/api/http/api.go:l57 """ raise NotImplementedError() # Regularly Scheduled Deletes - # todo def create_scheduled_delete(self, json_body): """ - Create scheduled delete + TODO: Create scheduled delete - This endpoint has been not implemented yet in InfluxDB ver0.0.8 + 2013-11-08: This endpoint has not been implemented yet in ver0.0.8, + but it is documented in http://influxdb.org/docs/api/http.html. See also: src/api/http/api.go:l57 """ raise NotImplementedError() @@ -133,22 +133,22 @@ def create_scheduled_delete(self, json_body): # remove a regularly scheduled delete # curl -X DELETE http://localhost:8086/db/site_dev/scheduled_deletes/:id - # todo def get_list_scheduled_delete(self): """ - Get list of scheduled deletes + TODO: Get list of scheduled deletes - This endpoint has been not implemented yet in InfluxDB ver0.0.8 + 2013-11-08: This endpoint has not been implemented yet in ver0.0.8, + but it is documented in http://influxdb.org/docs/api/http.html. See also: src/api/http/api.go:l57 """ raise NotImplementedError() - # todo def remove_scheduled_delete(self, delete_id): """ - Remove scheduled delete + TODO: Remove scheduled delete - This endpoint has been not implemented yet in InfluxDB ver0.0.8 + 2013-11-08: This endpoint has not been implemented yet in ver0.0.8, + but it is documented in http://influxdb.org/docs/api/http.html. See also: src/api/http/api.go:l57 """ raise NotImplementedError() @@ -378,42 +378,42 @@ def unset_database_admin(self, username): raise Exception( "{0}: {1}".format(response.status_code, response.content)) - # todo def get_list_database_admins(self): """ - Get list of database admins + TODO: Get list of database admins - This endpoint has been not implemented yet in InfluxDB ver0.0.8 + 2013-11-08: This endpoint has not been implemented yet in ver0.0.8, + but it is documented in http://influxdb.org/docs/api/http.html. See also: src/api/http/api.go:l57 """ raise NotImplementedError() - # todo def add_database_admin(self, new_username, new_password): """ - Add cluster admin + TODO: Add cluster admin - This endpoint has been not implemented yet in InfluxDB ver0.0.8 + 2013-11-08: This endpoint has not been implemented yet in ver0.0.8, + but it is documented in http://influxdb.org/docs/api/http.html. See also: src/api/http/api.go:l57 """ raise NotImplementedError() - # todo def update_database_admin_password(self, username, new_password): """ - Update database admin password + TODO: Update database admin password - This endpoint has been not implemented yet in InfluxDB ver0.0.8 + 2013-11-08: This endpoint has not been implemented yet in ver0.0.8, + but it is documented in http://influxdb.org/docs/api/http.html. See also: src/api/http/api.go:l57 """ raise NotImplementedError() - # todo def delete_database_admin(self, username): """ - Delete database admin + TODO: Delete database admin - This endpoint has been not implemented yet in InfluxDB ver0.0.8 + 2013-11-08: This endpoint has not been implemented yet in ver0.0.8, + but it is documented in http://influxdb.org/docs/api/http.html. See also: src/api/http/api.go:l57 """ raise NotImplementedError() @@ -517,9 +517,12 @@ def delete_database_user(self, username): # update the user by POSTing to db/site_dev/users/paul - # todo def update_permission(self, username, json_body): """ - Update read/write permission + TODO: Update read/write permission + + 2013-11-08: This endpoint has not been implemented yet in ver0.0.8, + but it is documented in http://influxdb.org/docs/api/http.html. + See also: src/api/http/api.go:l57 """ raise NotImplementedError() diff --git a/tox.ini b/tox.ini index 237ffa90..f5128281 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py32, py27, flake8 +envlist = py33, py27, flake8 [testenv] commands = From ed17edaebb1fbc53d60ad69205ec65a1cc5e895f Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Fri, 8 Nov 2013 11:20:21 +0900 Subject: [PATCH 19/20] Use six for python3/2 compatibility --- influxdb/client.py | 5 +++-- requirements.txt | 1 + tests/influxdb/client_test.py | 11 ++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/influxdb/client.py b/influxdb/client.py index edaf4c1f..90d1ff3a 100644 --- a/influxdb/client.py +++ b/influxdb/client.py @@ -3,7 +3,8 @@ python client for influxdb """ import json -import urllib + +from six.moves.urllib.parse import urlencode import requests @@ -169,7 +170,7 @@ def query(self, query, time_precision='s', chunked=False): else: chunked_param = 'false' - encoded_query = urllib.urlencode({ + encoded_query = urlencode({ 'q': query}) url_format = "{0}/db/{1}/series?{2}&u={3}&p={4}" diff --git a/requirements.txt b/requirements.txt index f2293605..c7d0ccea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ +six requests diff --git a/tests/influxdb/client_test.py b/tests/influxdb/client_test.py index 987a0605..9adbe4af 100644 --- a/tests/influxdb/client_test.py +++ b/tests/influxdb/client_test.py @@ -2,6 +2,8 @@ """ unit tests """ +import json + import requests from nose.tools import raises from mock import patch @@ -97,7 +99,14 @@ def test_remove_scheduled_delete(self): cli.remove_scheduled_delete(1) def test_query(self): - pass + expected = """[{"name":"foo","columns":["time","sequence_number","column_one"],"points":[[1383876043,16,"2"],[1383876043,15,"1"],[1383876035,14,"2"],[1383876035,13,"1"]]}]""" + with patch.object(requests, 'get') as mocked_get: + mocked_get.return_value = _build_response_object( + status_code=200, + content=expected) + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + result = cli.query('select column_one from foo;') + assert len(json.loads(result)[0]['points']) == 4 def test_create_database(self): with patch.object(requests, 'post') as mocked_post: From e05df22d06a42c1fb68d3546a11a42826a99c5da Mon Sep 17 00:00:00 2001 From: Kohei Ozaki Date: Fri, 8 Nov 2013 11:22:22 +0900 Subject: [PATCH 20/20] Add testcase of query() --- tests/influxdb/client_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/influxdb/client_test.py b/tests/influxdb/client_test.py index 9adbe4af..811548d3 100644 --- a/tests/influxdb/client_test.py +++ b/tests/influxdb/client_test.py @@ -108,6 +108,13 @@ def test_query(self): result = cli.query('select column_one from foo;') assert len(json.loads(result)[0]['points']) == 4 + @raises(Exception) + def test_query_fail(self): + with patch.object(requests, 'get') as mocked_get: + mocked_get.return_value = _build_response_object(status_code=401) + cli = InfluxDBClient('host', 8086, 'username', 'password', 'db') + cli.query('select column_one from foo;') + def test_create_database(self): with patch.object(requests, 'post') as mocked_post: mocked_post.return_value = _build_response_object(status_code=201) 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