diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..4074a26 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,99 @@ +# The format of this file isn't really documented; just use --generate-rcfile +[MASTER] +# Add to the black list. It should be a base name, not a +# path. You may set this option multiple times. +ignore=.git,tests + +[MESSAGES CONTROL] +# NOTE: The options which do not need to be suppressed can be removed. +disable= +# "F" Fatal errors that prevent further processing +# "I" Informational noise + c-extension-no-member, + locally-disabled, +# "E" Error for important programming issues (likely bugs) + import-error, + not-callable, + no-member, +# "W" Warnings for stylistic problems or minor programming issues + abstract-method, + anomalous-backslash-in-string, + arguments-differ, + attribute-defined-outside-init, + bad-builtin, + broad-except, + fixme, + global-statement, + no-init, + pointless-string-statement, + protected-access, + redefined-builtin, + redefined-outer-name, + signature-differs, + unidiomatic-typecheck, + unused-argument, + unused-variable, + useless-super-delegation, +# "C" Coding convention violations + bad-continuation, + invalid-name, + line-too-long, + missing-docstring, +# "R" Refactor recommendations + duplicate-code, + interface-not-implemented, + no-self-use, + too-few-public-methods, + too-many-ancestors, + too-many-arguments, + too-many-branches, + too-many-instance-attributes, + too-many-lines, + too-many-locals, + too-many-public-methods, + too-many-return-statements, + too-many-statements, + multiple-statements, + duplicate-except, + keyword-arg-before-vararg, + useless-object-inheritance + +[BASIC] +# Variable names can be 1 to 31 characters long, with lowercase and underscores +variable-rgx=[a-z_][a-z0-9_]{0,30}$ + +# Argument names can be 2 to 31 characters long, with lowercase and underscores +argument-rgx=[a-z_][a-z0-9_]{1,30}$ + +# Method names should be at least 3 characters long +# and be lowercased with underscores +method-rgx=([a-z_][a-z0-9_]{2,}|setUp|tearDown)$ + +# Module names matching +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Don't require docstrings on tests. +no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$ + +[FORMAT] +# Maximum number of characters on a single line. +max-line-length=79 + +[VARIABLES] +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +[CLASSES] + +[IMPORTS] +# Deprecated modules which should not be used, separated by a comma +deprecated-modules= + +[TYPECHECK] +# List of module names for which member attributes should not be checked +ignored-modules=six.moves,_MovedItems + +[REPORTS] +# Tells whether to display a full report or only the messages +reports=no diff --git a/lower-constraints.txt b/lower-constraints.txt index 470073d..f01ab63 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -1,16 +1,19 @@ asn1crypto==0.23.0 Babel==2.3.4 +bandit==1.4.0 cffi==1.7.0 cliff==2.8.0 coverage==4.0 cryptography==2.1 decorator==3.4.0 deprecation==1.0 +doc8==0.6.0 dogpile.cache==0.6.2 extras==1.0.0 fixtures==3.0.0 flake8==2.5.5 -hacking==0.12.0 +flake8-import-order==0.12 +hacking==1.1.0 idna==2.6 jmespath==0.9.0 jsonpatch==1.16 @@ -34,6 +37,7 @@ pep8==1.5.7 positional==1.2.1 pycparser==2.18 pyflakes==0.8.1 +pylint==1.9.2 pyOpenSSL==17.1.0 pyperclip==1.5.27 python-cinderclient==3.3.0 @@ -45,7 +49,7 @@ python-novaclient==9.1.0 python-openstackclient==3.12.0 python-subunit==1.0.0 requests==2.14.2 -requests-mock==1.1.0 +requests-mock==1.2.0 rfc3986==0.3.1 stestr==2.0.0 testscenarios==0.4 diff --git a/octaviaclient/api/exceptions.py b/octaviaclient/api/exceptions.py index df5675a..93fd78d 100644 --- a/octaviaclient/api/exceptions.py +++ b/octaviaclient/api/exceptions.py @@ -18,6 +18,7 @@ class OctaviaClientException(Exception): def __init__(self, code, message=None, request_id=None): self.code = code self.message = message or self.__class__.message + super(OctaviaClientException, self).__init__(self.message) self.request_id = request_id def __str__(self): diff --git a/octaviaclient/api/v2/octavia.py b/octaviaclient/api/v2/octavia.py index 6fa4112..d9abe06 100644 --- a/octaviaclient/api/v2/octavia.py +++ b/octaviaclient/api/v2/octavia.py @@ -10,7 +10,6 @@ # License for the specific language governing permissions and limitations # under the License. # - """Octavia API Library""" import functools @@ -46,8 +45,8 @@ def correct_return_codes(func): _status_dict.get(code, message)) except Exception: message = _status_dict.get(code, message) - elif (isinstance(e, osc_exc.ClientException) - and e.code != e.http_status): + elif (isinstance(e, osc_exc.ClientException) and + e.code != e.http_status): # cover https://review.opendev.org/675328 case code = e.http_status message = e.code diff --git a/octaviaclient/hacking/checks.py b/octaviaclient/hacking/checks.py index f1ec081..5c74a13 100644 --- a/octaviaclient/hacking/checks.py +++ b/octaviaclient/hacking/checks.py @@ -41,7 +41,7 @@ _log_translation_hint = re.compile( assert_trueinst_re = re.compile( r"(.)*assertTrue\(isinstance\((\w|\.|\'|\"|\[|\])+, " - "(\w|\.|\'|\"|\[|\])+\)\)") + r"(\w|\.|\'|\"|\[|\])+\)\)") assert_equal_in_end_with_true_or_false_re = re.compile( r"assertEqual\((\w|[][.'\"])+ in (\w|[][.'\", ])+, (True|False)\)") assert_equal_in_start_with_true_or_false_re = re.compile( diff --git a/octaviaclient/osc/plugin.py b/octaviaclient/osc/plugin.py index ecbb550..bf82de1 100644 --- a/octaviaclient/osc/plugin.py +++ b/octaviaclient/osc/plugin.py @@ -9,14 +9,13 @@ # 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. - """OpenStackClient plugin for Load Balancer service.""" - import logging -from octaviaclient.api.v2 import octavia from osc_lib import utils +from octaviaclient.api.v2 import octavia + LOG = logging.getLogger(__name__) DEFAULT_LOADBALANCER_API_VERSION = '2.0' diff --git a/octaviaclient/osc/v2/amphora.py b/octaviaclient/osc/v2/amphora.py index 387162b..0f5d3e8 100644 --- a/octaviaclient/osc/v2/amphora.py +++ b/octaviaclient/osc/v2/amphora.py @@ -80,8 +80,7 @@ class ListAmphora(lister.Lister): (utils.get_dict_properties( amp, columns, - formatters=formatters, - ) for amp in data['amphorae']), + formatters=formatters) for amp in data['amphorae']), ) diff --git a/octaviaclient/osc/v2/availabilityzone.py b/octaviaclient/osc/v2/availabilityzone.py index 0063961..29e8479 100644 --- a/octaviaclient/osc/v2/availabilityzone.py +++ b/octaviaclient/osc/v2/availabilityzone.py @@ -237,7 +237,7 @@ class UnsetAvailabilityzone(command.Command): def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) - if not len(unset_args): + if not unset_args: return availabilityzone_id = v2_utils.get_resource_id( diff --git a/octaviaclient/osc/v2/flavor.py b/octaviaclient/osc/v2/flavor.py index 84ca398..de60021 100644 --- a/octaviaclient/osc/v2/flavor.py +++ b/octaviaclient/osc/v2/flavor.py @@ -247,7 +247,7 @@ class UnsetFlavor(command.Command): def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) - if not len(unset_args): + if not unset_args: return flavor_id = v2_utils.get_resource_id( diff --git a/octaviaclient/osc/v2/health_monitor.py b/octaviaclient/osc/v2/health_monitor.py index 7fcf105..ed36e3d 100644 --- a/octaviaclient/osc/v2/health_monitor.py +++ b/octaviaclient/osc/v2/health_monitor.py @@ -441,7 +441,7 @@ class UnsetHealthMonitor(command.Command): def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) - if not len(unset_args): + if not unset_args: return hm_id = v2_utils.get_resource_id( diff --git a/octaviaclient/osc/v2/l7policy.py b/octaviaclient/osc/v2/l7policy.py index 0969d76..0ae6258 100644 --- a/octaviaclient/osc/v2/l7policy.py +++ b/octaviaclient/osc/v2/l7policy.py @@ -382,7 +382,7 @@ class UnsetL7Policy(command.Command): def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) - if not len(unset_args): + if not unset_args: return policy_id = v2_utils.get_resource_id( diff --git a/octaviaclient/osc/v2/l7rule.py b/octaviaclient/osc/v2/l7rule.py index 461e2f2..4a60d19 100644 --- a/octaviaclient/osc/v2/l7rule.py +++ b/octaviaclient/osc/v2/l7rule.py @@ -370,7 +370,7 @@ class UnsetL7Rule(command.Command): def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) - if not len(unset_args): + if not unset_args: return policy_id = v2_utils.get_resource_id( diff --git a/octaviaclient/osc/v2/listener.py b/octaviaclient/osc/v2/listener.py index bc4cb45..e12846d 100644 --- a/octaviaclient/osc/v2/listener.py +++ b/octaviaclient/osc/v2/listener.py @@ -589,7 +589,7 @@ class UnsetListener(command.Command): def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) - if not len(unset_args): + if not unset_args: return listener_id = v2_utils.get_resource_id( diff --git a/octaviaclient/osc/v2/load_balancer.py b/octaviaclient/osc/v2/load_balancer.py index d3ead07..3a1353c 100644 --- a/octaviaclient/osc/v2/load_balancer.py +++ b/octaviaclient/osc/v2/load_balancer.py @@ -488,7 +488,7 @@ class UnsetLoadBalancer(command.Command): def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) - if not len(unset_args): + if not unset_args: return lb_id = v2_utils.get_resource_id( diff --git a/octaviaclient/osc/v2/member.py b/octaviaclient/osc/v2/member.py index faa6afe..e359fa1 100644 --- a/octaviaclient/osc/v2/member.py +++ b/octaviaclient/osc/v2/member.py @@ -418,7 +418,7 @@ class UnsetMember(command.Command): def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) - if not len(unset_args): + if not unset_args: return pool_id = v2_utils.get_resource_id( diff --git a/octaviaclient/osc/v2/pool.py b/octaviaclient/osc/v2/pool.py index 081b21d..1366bfe 100644 --- a/octaviaclient/osc/v2/pool.py +++ b/octaviaclient/osc/v2/pool.py @@ -421,7 +421,7 @@ class UnsetPool(command.Command): def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) - if not len(unset_args): + if not unset_args: return pool_id = v2_utils.get_resource_id( diff --git a/octaviaclient/osc/v2/quota.py b/octaviaclient/osc/v2/quota.py index e246561..3a4771c 100644 --- a/octaviaclient/osc/v2/quota.py +++ b/octaviaclient/osc/v2/quota.py @@ -236,7 +236,7 @@ class UnsetQuota(command.Command): def take_action(self, parsed_args): unset_args = v2_utils.get_unsets(parsed_args) - if not len(unset_args): + if not unset_args: return project_id = v2_utils.get_resource_id( diff --git a/octaviaclient/osc/v2/utils.py b/octaviaclient/osc/v2/utils.py index 899d66a..9ff98d5 100644 --- a/octaviaclient/osc/v2/utils.py +++ b/octaviaclient/osc/v2/utils.py @@ -93,35 +93,31 @@ def get_resource_id(resource, resource_name, name): name ).id return project_id - else: - return 'non-uuid' - elif resource_name == 'members': + return 'non-uuid' + if resource_name == 'members': names = [re for re in resource(name['pool_id'])['members'] - if re.get('id') == name['member_id'] - or re.get('name') == name['member_id']] + if re.get('id') == name['member_id'] or + re.get('name') == name['member_id']] name = name['member_id'] if len(names) > 1: msg = ("{0} {1} found with name or ID of {2}. Please try " "again with UUID".format(len(names), resource_name, name)) raise osc_exc.CommandError(msg) - else: - return names[0].get('id') - elif resource_name == 'l7rules': + return names[0].get('id') + if resource_name == 'l7rules': names = [re for re in resource(name['l7policy_id'])['rules'] if re.get('id') == name['l7rule_id']] name = name['l7rule_id'] return names[0].get('id') - else: - names = [re for re in resource()[resource_name] - if re.get('name') == name or re.get('id') == name] - if len(names) > 1: - msg = ("{0} {1} found with name or ID of {2}. Please try " - "again with UUID".format(len(names), resource_name, - name)) - raise osc_exc.CommandError(msg) - else: - return names[0].get(primary_key) + names = [re for re in resource()[resource_name] + if re.get('name') == name or re.get('id') == name] + if len(names) > 1: + msg = ("{0} {1} found with name or ID of {2}. Please try " + "again with UUID".format(len(names), resource_name, + name)) + raise osc_exc.CommandError(msg) + return names[0].get(primary_key) except IndexError: msg = "Unable to locate {0} in {1}".format(name, resource_name) @@ -581,8 +577,7 @@ def format_list_flat(data): def format_hash(data): if data: return '\n'.join('{}={}'.format(k, v) for k, v in data.items()) - else: - return None + return None def _format_kv(data): diff --git a/octaviaclient/tests/functional/base.py b/octaviaclient/tests/functional/base.py index 87a2154..6769741 100644 --- a/octaviaclient/tests/functional/base.py +++ b/octaviaclient/tests/functional/base.py @@ -44,7 +44,7 @@ def execute(cmd, fail_ok=False, merge_stderr=False): class TestCase(utils.TestCase): - delimiter_line = re.compile('^\+\-[\+\-]+\-\+$') + delimiter_line = re.compile(r'^\+\-[\+\-]+\-\+$') @classmethod def openstack(cls, cmd, fail_ok=False): diff --git a/octaviaclient/tests/unit/osc/v2/test_flavor.py b/octaviaclient/tests/unit/osc/v2/test_flavor.py index f5b3487..594b6f9 100644 --- a/octaviaclient/tests/unit/osc/v2/test_flavor.py +++ b/octaviaclient/tests/unit/osc/v2/test_flavor.py @@ -205,7 +205,7 @@ class TestFlavorUnset(TestFlavor): arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) - verifylist = list(zip(self.PARAMETERS, [True]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('flavor', self._flavor.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) @@ -215,7 +215,7 @@ class TestFlavorUnset(TestFlavor): def test_flavor_unset_none(self): self.api_mock.flavor_set.reset_mock() arglist = [self._flavor.id] - verifylist = list(zip(self.PARAMETERS, [False]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('flavor', self._flavor.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) diff --git a/octaviaclient/tests/unit/osc/v2/test_health_monitor.py b/octaviaclient/tests/unit/osc/v2/test_health_monitor.py index 1ec8470..b905d85 100644 --- a/octaviaclient/tests/unit/osc/v2/test_health_monitor.py +++ b/octaviaclient/tests/unit/osc/v2/test_health_monitor.py @@ -335,7 +335,7 @@ class TestHealthMonitorUnset(TestHealthMonitor): arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) - verifylist = list(zip(self.PARAMETERS, [True]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('health_monitor', self._hm.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) @@ -345,7 +345,7 @@ class TestHealthMonitorUnset(TestHealthMonitor): def test_hm_unset_none(self): self.api_mock.health_monitor_set.reset_mock() arglist = [self._hm.id] - verifylist = list(zip(self.PARAMETERS, [False]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('health_monitor', self._hm.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) diff --git a/octaviaclient/tests/unit/osc/v2/test_l7policy.py b/octaviaclient/tests/unit/osc/v2/test_l7policy.py index a49d3c0..798ca31 100644 --- a/octaviaclient/tests/unit/osc/v2/test_l7policy.py +++ b/octaviaclient/tests/unit/osc/v2/test_l7policy.py @@ -333,7 +333,7 @@ class TestL7PolicyUnset(TestL7Policy): arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) - verifylist = list(zip(self.PARAMETERS, [True]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('l7policy', self._l7po.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) @@ -343,7 +343,7 @@ class TestL7PolicyUnset(TestL7Policy): def test_l7policy_unset_none(self): self.api_mock.l7policy_set.reset_mock() arglist = [self._l7po.id] - verifylist = list(zip(self.PARAMETERS, [False]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('l7policy', self._l7po.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) diff --git a/octaviaclient/tests/unit/osc/v2/test_l7rule.py b/octaviaclient/tests/unit/osc/v2/test_l7rule.py index d9b66ca..08e56bd 100644 --- a/octaviaclient/tests/unit/osc/v2/test_l7rule.py +++ b/octaviaclient/tests/unit/osc/v2/test_l7rule.py @@ -364,7 +364,7 @@ class TestL7RuleUnset(TestL7Rule): arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) - verifylist = list(zip(self.PARAMETERS, [True]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('l7rule_id', self._l7ru.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) @@ -374,7 +374,7 @@ class TestL7RuleUnset(TestL7Rule): def test_l7rule_unset_none(self): self.api_mock.l7rule_set.reset_mock() arglist = [self._l7po.id, self._l7ru.id] - verifylist = list(zip(self.PARAMETERS, [False]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('l7rule_id', self._l7ru.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) diff --git a/octaviaclient/tests/unit/osc/v2/test_listener.py b/octaviaclient/tests/unit/osc/v2/test_listener.py index e6d9052..b9acccd 100644 --- a/octaviaclient/tests/unit/osc/v2/test_listener.py +++ b/octaviaclient/tests/unit/osc/v2/test_listener.py @@ -475,7 +475,7 @@ class TestListenerUnset(TestListener): arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) - verifylist = list(zip(self.PARAMETERS, [True]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('listener', self._listener.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) @@ -485,7 +485,7 @@ class TestListenerUnset(TestListener): def test_listener_unset_none(self): self.api_mock.listener_set.reset_mock() arglist = [self._listener.id] - verifylist = list(zip(self.PARAMETERS, [False]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('listener', self._listener.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) diff --git a/octaviaclient/tests/unit/osc/v2/test_load_balancer.py b/octaviaclient/tests/unit/osc/v2/test_load_balancer.py index 2e1ce53..bebd214 100644 --- a/octaviaclient/tests/unit/osc/v2/test_load_balancer.py +++ b/octaviaclient/tests/unit/osc/v2/test_load_balancer.py @@ -363,7 +363,7 @@ class TestLoadBalancerCreate(TestLoadBalancer): # init missing keys attrs_list[a] = '' # verify all valid combinations of args - for n in range(len(args)+1): + for n in range(len(args) + 1): for comb in itertools.combinations(args, n): # subtract comb's keys from attrs_list filtered_attrs = {k: v for k, v in attrs_list.items() if ( @@ -643,7 +643,7 @@ class TestLoadBalancerUnset(TestLoadBalancer): arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) - verifylist = list(zip(self.PARAMETERS, [True]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('loadbalancer', self._lb.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) @@ -653,7 +653,7 @@ class TestLoadBalancerUnset(TestLoadBalancer): def test_load_balancer_unset_none(self): self.api_mock.load_balancer_set.reset_mock() arglist = [self._lb.id] - verifylist = list(zip(self.PARAMETERS, [False]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('loadbalancer', self._lb.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) diff --git a/octaviaclient/tests/unit/osc/v2/test_member.py b/octaviaclient/tests/unit/osc/v2/test_member.py index f048108..7ba06a1 100644 --- a/octaviaclient/tests/unit/osc/v2/test_member.py +++ b/octaviaclient/tests/unit/osc/v2/test_member.py @@ -365,7 +365,7 @@ class TestMemberUnset(TestMember): arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) - verifylist = list(zip(self.PARAMETERS, [True]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('member', self._mem.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) @@ -375,7 +375,7 @@ class TestMemberUnset(TestMember): def test_member_unset_none(self): self.api_mock.pool_set.reset_mock() arglist = [self._mem.pool_id, self._mem.id] - verifylist = list(zip(self.PARAMETERS, [False]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('member', self._mem.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) diff --git a/octaviaclient/tests/unit/osc/v2/test_pool.py b/octaviaclient/tests/unit/osc/v2/test_pool.py index 67e43d3..4cad261 100644 --- a/octaviaclient/tests/unit/osc/v2/test_pool.py +++ b/octaviaclient/tests/unit/osc/v2/test_pool.py @@ -316,7 +316,7 @@ class TestPoolUnset(TestPool): arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) - verifylist = list(zip(self.PARAMETERS, [True]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('pool', self._po.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) @@ -326,7 +326,7 @@ class TestPoolUnset(TestPool): def test_pool_unset_none(self): self.api_mock.pool_set.reset_mock() arglist = [self._po.id] - verifylist = list(zip(self.PARAMETERS, [False]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('pool', self._po.id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) diff --git a/octaviaclient/tests/unit/osc/v2/test_quota.py b/octaviaclient/tests/unit/osc/v2/test_quota.py index 323d8ab..a5b6fb7 100644 --- a/octaviaclient/tests/unit/osc/v2/test_quota.py +++ b/octaviaclient/tests/unit/osc/v2/test_quota.py @@ -249,7 +249,7 @@ class TestQuotaUnset(TestQuota): arg_param = (ref_param.replace('_', '-') if '_' in ref_param else ref_param) arglist.append('--%s' % arg_param) - verifylist = list(zip(self.PARAMETERS, [True]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [True] * len(self.PARAMETERS))) verifylist = [('project', self._qt.project_id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) @@ -259,7 +259,7 @@ class TestQuotaUnset(TestQuota): def test_quota_unset_none(self): self.api_mock.quota_set.reset_mock() arglist = [self._qt.project_id] - verifylist = list(zip(self.PARAMETERS, [False]*len(self.PARAMETERS))) + verifylist = list(zip(self.PARAMETERS, [False] * len(self.PARAMETERS))) verifylist = [('project', self._qt.project_id)] + verifylist parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) diff --git a/octaviaclient/tests/unit/osc/v2/test_validations.py b/octaviaclient/tests/unit/osc/v2/test_validations.py index c0adf78..4c06f5b 100644 --- a/octaviaclient/tests/unit/osc/v2/test_validations.py +++ b/octaviaclient/tests/unit/osc/v2/test_validations.py @@ -25,8 +25,7 @@ class TestValidations(utils.TestCommand): def test_check_l7policy_attrs(self): attrs_dict = { "action": "redirect_to_pool".upper(), - "redirect_pool_id": "id", - } + "redirect_pool_id": "id"} try: validate.check_l7policy_attrs(attrs_dict) except exceptions.CommandError as e: @@ -38,8 +37,7 @@ class TestValidations(utils.TestCommand): attrs_dict = { "action": "redirect_to_url".upper(), - "redirect_url": "url", - } + "redirect_url": "url"} try: validate.check_l7policy_attrs(attrs_dict) except exceptions.CommandError as e: diff --git a/octaviaclient/tests/unit/test_hacking.py b/octaviaclient/tests/unit/test_hacking.py index 064e4fd..0b2903b 100644 --- a/octaviaclient/tests/unit/test_hacking.py +++ b/octaviaclient/tests/unit/test_hacking.py @@ -233,4 +233,4 @@ class HackingTestCase(base.BaseTestCase): return check_fns def test_factory(self): - self.assertTrue(len(self._get_factory_checks(checks.factory)) > 0) + self.assertGreater(len(self._get_factory_checks(checks.factory)), 0) diff --git a/test-requirements.txt b/test-requirements.txt index d335135..ccfa236 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -2,9 +2,13 @@ # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. -hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 -requests-mock>=1.1.0 # Apache-2.0 +hacking>=1.1.0 # Apache-2.0 +requests-mock>=1.2.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 +doc8>=0.6.0 # Apache-2.0 +bandit!=1.6.0,>=1.1.0 # Apache-2.0 +flake8-import-order==0.12 # LGPLv3 +pylint>=2.2.0 # GPLv2 python-subunit>=1.0.0 # Apache-2.0/BSD oslotest>=3.2.0 # Apache-2.0 stestr>=2.0.0 # Apache-2.0 diff --git a/tools/coding-checks.sh b/tools/coding-checks.sh new file mode 100755 index 0000000..e547ab0 --- /dev/null +++ b/tools/coding-checks.sh @@ -0,0 +1,66 @@ +#!/bin/sh +# This script is copied from neutron and adapted for octavia. +set -eu + +usage () { + echo "Usage: $0 [OPTION]..." + echo "Run octavia's coding check(s)" + echo "" + echo " -Y, --pylint [] Run pylint check on the entire octavia module or just files changed in basecommit (e.g. HEAD~1)" + echo " -h, --help Print this usage message" + echo + exit 0 +} + +join_args() { + if [ -z "$scriptargs" ]; then + scriptargs="$opt" + else + scriptargs="$scriptargs $opt" + fi +} + +process_options () { + i=1 + while [ $i -le $# ]; do + eval opt=\$$i + case $opt in + -h|--help) usage;; + -Y|--pylint) pylint=1;; + *) join_args;; + esac + i=$((i+1)) + done +} + +run_pylint () { + local target="${scriptargs:-all}" + + if [ "$target" = "all" ]; then + files="octaviaclient" + else + case "$target" in + *HEAD~[0-9]*) files=$(git diff --diff-filter=AM --name-only $target -- "*.py");; + *) echo "$target is an unrecognized basecommit"; exit 1;; + esac + fi + + echo "Running pylint..." + echo "You can speed this up by running it on 'HEAD~[0-9]' (e.g. HEAD~1, this change only)..." + if [ -n "${files}" ]; then + pylint -j 0 --max-nested-blocks 7 --rcfile=.pylintrc --output-format=colorized ${files} + else + echo "No python changes in this commit, pylint check not required." + exit 0 + fi +} + +scriptargs= +pylint=1 + +process_options $@ + +if [ $pylint -eq 1 ]; then + run_pylint + exit 0 +fi diff --git a/tox.ini b/tox.ini index b40efa1..51db577 100644 --- a/tox.ini +++ b/tox.ini @@ -2,6 +2,7 @@ minversion = 2.5.0 envlist = py37,pep8 skipsdist = True +ignore_basepython_conflict = True [testenv] basepython = python3 @@ -22,7 +23,17 @@ commands = stestr slowest [testenv:pep8] -commands = flake8 {posargs} +commands = flake8 + # RST linter + doc8 --ignore-path doc/source/contributor/modules doc/source \ + octaviaclient HACKING.rst README.rst + # Run security linter + {[testenv:bandit]commands} + {toxinidir}/tools/coding-checks.sh --pylint {posargs} +whitelist_externals = + sh + find + bash [testenv:venv] commands = {posargs} @@ -77,10 +88,32 @@ commands = oslo_debug_helper -t octaviaclient/tests {posargs} [flake8] -ignore = +# [H104]: Empty file with only comments +# [W504]: Line break after binary operator +ignore = H104,W504 show-source = true builtins = _ -exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build +exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build +import-order-style = pep8 +# [H106]: Don't put vim configuration in source files +# [H203]: Use assertIs(Not)None to check for None +# [H204]: Use assert(Not)Equal to check for equality +# [H205]: Use assert(Greater|Less)(Equal) for comparison +# [H904]: Delay string interpolations at logging calls +enable-extensions=H106,H203,H204,H205,H904 + +[testenv:bashate] +envdir = {toxworkdir}/shared +commands = bash -c "find {toxinidir} \ + -not \( -type d -name .tox\* -prune \) \ + -not \( -type d -name .venv\* -prune \) \ + -type f \ + -name \*.sh \ +# [E005]: File does not begin with #! or have a .sh prefix +# [E006]: Check for lines longer than 79 columns +# [E042]: Local declaration hides errors +# [E043]: Arithmetic compound has inconsistent return semantics + -print0 | xargs -0 bashate -v -iE006 -eE005,E042,E043" [hacking] local-check-factory = octaviaclient.hacking.checks.factory @@ -97,3 +130,6 @@ deps = whitelist_externals = sh commands = sh -c '{envdir}/src/openstack-requirements/playbooks/files/project-requirements-change.py --req {envdir}/src/openstack-requirements --local {toxinidir} master' + +[testenv:bandit] +commands = bandit -r octaviaclient -ll -ii -x tests