Fix py35 and pep8

Distil-UI project is depending on distilclient and now there is a py35
gate failure because disticlient doesn't fully support py3.x. This patch
fixes it and adds some test cases to make sure the change won't break
the functions.

Besides, the patch also fixes some pep8 issues by the way.

Change-Id: Ide043d0fca019cd48796669374dc882311e935a1
This commit is contained in:
Feilong Wang 2017-06-09 17:35:28 +12:00
parent ec5a553c24
commit 57ec3b1dea
11 changed files with 126 additions and 42 deletions

View File

@ -30,8 +30,8 @@ from oslo_utils import strutils
import six import six
from six.moves.urllib import parse from six.moves.urllib import parse
from distilclient.i18n import _
from distilclient.common.apiclient import exceptions from distilclient.common.apiclient import exceptions
from distilclient.i18n import _
def getid(obj): def getid(obj):

View File

@ -36,8 +36,8 @@ except ImportError:
from oslo_utils import importutils from oslo_utils import importutils
import requests import requests
from distilclient.i18n import _
from distilclient.common.apiclient import exceptions from distilclient.common.apiclient import exceptions
from distilclient.i18n import _
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View File

@ -15,8 +15,8 @@ from oslo_utils import encodeutils
from oslo_utils import uuidutils from oslo_utils import uuidutils
import six import six
from distilclient.i18n import _
from distilclient.common.apiclient import exceptions from distilclient.common.apiclient import exceptions
from distilclient.i18n import _
def find_resource(manager, name_or_id, **find_args): def find_resource(manager, name_or_id, **find_args):

View File

@ -12,15 +12,17 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import os
import json
import sys
from client import Client
import exc import exc
import json
import os
import sys
from keystoneauth1.identity import generic from keystoneauth1.identity import generic
from keystoneauth1 import session from keystoneauth1 import session
from client import Client
def main(): def main():
import argparse import argparse
@ -233,19 +235,19 @@ def main():
if args.command == 'collect-usage': if args.command == 'collect-usage':
response = client.collect_usage() response = client.collect_usage()
print json.dumps(response, indent=2) print(json.dumps(response, indent=2))
if args.command == 'last-collected': if args.command == 'last-collected':
response = client.last_collected() response = client.last_collected()
print json.dumps(response, indent=2) print(json.dumps(response, indent=2))
if args.command == 'get-usage': if args.command == 'get-usage':
response = client.get_usage(args.project, args.start, args.end) response = client.get_usage(args.project, args.start, args.end)
print json.dumps(response, indent=2) print(json.dumps(response, indent=2))
if args.command == 'get-rated': if args.command == 'get-rated':
response = client.get_rated(args.project, args.start, args.end) response = client.get_rated(args.project, args.start, args.end)
print json.dumps(response, indent=2) print(json.dumps(response, indent=2))
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -23,7 +23,7 @@ import distilclient.v2.client
@ddt.ddt @ddt.ddt
class ClientTest(utils.TestCase): class ClientTest(utils.TestCase):
@mock.patch.object(distilclient.v1.client, 'Client') @mock.patch("distilclient.v1.client.Client")
def test_init_client_with_string_v1_version(self, mock_client): def test_init_client_with_string_v1_version(self, mock_client):
mock_client('1', 'foo', auth_url='quuz') mock_client('1', 'foo', auth_url='quuz')
mock_client.assert_called_once_with('1', 'foo', auth_url='quuz') mock_client.assert_called_once_with('1', 'foo', auth_url='quuz')

View File

View File

@ -0,0 +1,96 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
from distilclient.tests.unit import utils
from distilclient.v1 import client as v1_client
class FakeResponse(object):
status_code = 200
result = {}
def __init__(self, status_code, result):
self.status_code = status_code
self.result = result
def json(self):
return self.result
class ClientTest(utils.TestCase):
def setUp(self):
super(ClientTest, self).setUp()
self.tenant = 'fake_tenant'
self.start = "2017-01-01"
self.end = "2017-02-01"
self.distil_url = "http://127.0.0.1:9999/v2"
@mock.patch("keystoneauth1.identity.generic.Password.get_token")
@mock.patch("requests.post")
def test_collect_usage(self, mock_post, mock_get_token):
mock_get_token.return_value = 'fake_token'
mock_post.return_value = FakeResponse(200, {})
client = v1_client.HTTPClient(distil_url=self.distil_url)
client.collect_usage()
expect_url = 'http://127.0.0.1:9999/collect_usage'
expect_headers = {'X-Auth-Token': 'fake_token',
'Content-Type': 'application/json'}
mock_post.assert_called_once_with(expect_url,
headers=expect_headers,
verify=True)
@mock.patch("keystoneauth1.identity.generic.Password.get_token")
@mock.patch("requests.get")
def test_last_collected(self, mock_get, mock_get_token):
mock_get_token.return_value = 'fake_token'
mock_get.return_value = FakeResponse(200, {})
client = v1_client.HTTPClient(distil_url=self.distil_url)
client.last_collected()
expect_url = 'http://127.0.0.1:9999/last_collected'
expect_headers = {'X-Auth-Token': 'fake_token',
'Content-Type': 'application/json'}
mock_get.assert_called_once_with(expect_url,
headers=expect_headers,
verify=True)
@mock.patch("keystoneauth1.identity.generic.Password.get_token")
@mock.patch("requests.get")
def test_get_rated(self, mock_get, mock_get_token):
mock_get_token.return_value = 'fake_token'
mock_get.return_value = FakeResponse(200, {})
client = v1_client.HTTPClient(distil_url=self.distil_url)
client.get_rated(self.tenant, self.start, self.end)
mock_get.assert_called_once_with('http://127.0.0.1:9999/get_rated',
headers={'X-Auth-Token':
'fake_token'},
params={'tenant': 'fake_tenant',
'end': '2017-02-01',
'start': '2017-01-01'},
verify=True)
@mock.patch("keystoneauth1.identity.generic.Password.get_token")
@mock.patch("requests.get")
def test_get_usage(self, mock_get, mock_get_token):
mock_get_token.return_value = 'fake_token'
mock_get.return_value = FakeResponse(200, {})
client = v1_client.HTTPClient(distil_url=self.distil_url)
client.get_usage(self.tenant, self.start, self.end)
mock_get.assert_called_once_with('http://127.0.0.1:9999/get_usage',
headers={'X-Auth-Token':
'fake_token'},
params={'tenant': 'fake_tenant',
'end': '2017-02-01',
'start': '2017-01-01'},
verify=True)

View File

@ -14,7 +14,8 @@
import requests import requests
from requests.exceptions import ConnectionError from requests.exceptions import ConnectionError
from urlparse import urljoin
import six.moves.urllib.parse as urlparse
from keystoneauth1 import adapter from keystoneauth1 import adapter
from keystoneauth1.identity import generic from keystoneauth1.identity import generic
@ -138,7 +139,7 @@ class HTTPClient(object):
region_name=os_region_name) region_name=os_region_name)
def collect_usage(self): def collect_usage(self):
url = urljoin(self.endpoint, "collect_usage") url = urlparse.urljoin(self.endpoint, "collect_usage")
headers = {"Content-Type": "application/json", headers = {"Content-Type": "application/json",
"X-Auth-Token": self.auth_token} "X-Auth-Token": self.auth_token}
@ -152,10 +153,10 @@ class HTTPClient(object):
else: else:
return response.json() return response.json()
except ConnectionError as e: except ConnectionError as e:
print e print(e)
def last_collected(self): def last_collected(self):
url = urljoin(self.endpoint, "last_collected") url = urlparse.urljoin(self.endpoint, "last_collected")
headers = {"Content-Type": "application/json", headers = {"Content-Type": "application/json",
"X-Auth-Token": self.auth_token} "X-Auth-Token": self.auth_token}
@ -169,7 +170,7 @@ class HTTPClient(object):
else: else:
return response.json() return response.json()
except ConnectionError as e: except ConnectionError as e:
print e print(e)
def get_usage(self, tenant, start, end): def get_usage(self, tenant, start, end):
return self._query_usage(tenant, start, end, "get_usage") return self._query_usage(tenant, start, end, "get_usage")
@ -178,7 +179,7 @@ class HTTPClient(object):
return self._query_usage(tenant, start, end, "get_rated") return self._query_usage(tenant, start, end, "get_rated")
def _query_usage(self, tenant, start, end, endpoint): def _query_usage(self, tenant, start, end, endpoint):
url = urljoin(self.endpoint, endpoint) url = urlparse.urljoin(self.endpoint, endpoint)
headers = {"X-Auth-Token": self.auth_token} headers = {"X-Auth-Token": self.auth_token}
@ -197,4 +198,4 @@ class HTTPClient(object):
else: else:
return response.json() return response.json()
except ConnectionError as e: except ConnectionError as e:
print e print(e)

View File

@ -19,6 +19,7 @@ class MeasurementManager(base.Manager):
def list(self, project_id, start, end): def list(self, project_id, start, end):
"""Retrieve a list of measurements. """Retrieve a list of measurements.
:returns: A list of measurements. :returns: A list of measurements.
""" """
url = "/v2/measurements?project_id={0}&start={1}&end={2}" url = "/v2/measurements?project_id={0}&start={1}&end={2}"

View File

@ -2,11 +2,10 @@
# of appearance. Changing the order has an impact on the overall integration # of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
hacking>=0.11.0,<0.12 # Apache-2.0 hacking>=0.11.0,<0.12 # Apache-2.0
coverage>=3.6 # Apache-2.0 coverage>=3.6 # Apache-2.0
ddt>=1.0.1 # MIT
discover # BSD discover # BSD
fixtures>=3.0.0 # Apache-2.0/BSD fixtures>=3.0.0 # Apache-2.0/BSD
keyring>=5.5.1 # MIT/PSF
mock>=2.0 # BSD mock>=2.0 # BSD
requests-mock>=0.7.0 # Apache-2.0 requests-mock>=0.7.0 # Apache-2.0
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD
@ -19,6 +18,4 @@ tempest>=11.0.0 # Apache-2.0
os-testr>=0.8.0 # Apache-2.0 os-testr>=0.8.0 # Apache-2.0
# releasenotes # releasenotes
reno>=1.6.2 # Apache2 reno>=1.6.2 # Apache2
ddt>=1.0.1 # MIT

23
tox.ini
View File

@ -1,19 +1,15 @@
[tox] [tox]
minversion = 1.6 minversion = 1.6
envlist = py34,py27,pep8 envlist = py35,py27,pep8
skipsdist = True skipsdist = True
[testenv] [testenv]
usedevelop = True usedevelop = True
# Customize pip command, add -U to force updates. install_command = pip install -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
install_command = pip install -U {opts} {packages}
setenv = VIRTUAL_ENV={envdir} setenv = VIRTUAL_ENV={envdir}
NOSE_WITH_OPENSTACK=1 OS_STDOUT_NOCAPTURE=False
NOSE_OPENSTACK_COLOR=1 OS_STDERR_NOCAPTURE=False
NOSE_OPENSTACK_RED=0.05 PYTHONHASHSEED=0
NOSE_OPENSTACK_YELLOW=0.025
NOSE_OPENSTACK_SHOW_ELAPSED=1
NOSE_OPENSTACK_STDOUT=1
deps = -r{toxinidir}/requirements.txt deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
commands = ostestr {posargs} commands = ostestr {posargs}
@ -36,15 +32,6 @@ commands = {posargs}
commands = python setup.py build_sphinx commands = python setup.py build_sphinx
[flake8] [flake8]
# Following checks should be enabled in the future.
#
# H404 multi line docstring should start without a leading new line
# H405 multi line docstring summary not separated with an empty line
#
# Following checks are ignored on purpose.
#
# Additional checks are also ignored on purpose: F811, F821
ignore = F811,F821,H404,H405,H233,H306,E265,W291,W391,F841
show-source = True show-source = True
exclude=.venv,.git,.tox,dist,*lib/python*,*egg,build,doc/source/conf.py,releasenotes exclude=.venv,.git,.tox,dist,*lib/python*,*egg,build,doc/source/conf.py,releasenotes