Merge "Update hacking for Python3"
This commit is contained in:
@@ -12,7 +12,6 @@ Tempest Specific Commandments
|
||||
tempest/scenario tests
|
||||
- [T104] Scenario tests require a services decorator
|
||||
- [T105] Tests cannot use setUpClass/tearDownClass
|
||||
- [T106] vim configuration should not be kept in source files.
|
||||
- [T107] Check that a service tag isn't in the module path
|
||||
- [T108] Check no hyphen at the end of rand_name() argument
|
||||
- [T109] Cannot use testtools.skip decorator; instead use
|
||||
|
||||
@@ -23,7 +23,7 @@ CONF = config.CONF
|
||||
# NOTE(zhufl): This inherits from BaseVolumeAdminTest because
|
||||
# it requires force_tenant_isolation=True, which need admin
|
||||
# credentials to create non-admin users for the tests.
|
||||
class AbsoluteLimitsTests(base.BaseVolumeAdminTest): # noqa
|
||||
class AbsoluteLimitsTests(base.BaseVolumeAdminTest): # noqa: T115
|
||||
|
||||
# avoid existing volumes of pre-defined tenant
|
||||
force_tenant_isolation = True
|
||||
|
||||
@@ -109,7 +109,7 @@ class VolumesSnapshotListTestJSON(base.BaseVolumeTest):
|
||||
snap_list = self.snapshots_client.list_snapshots(
|
||||
sort_key=sort_key, sort_dir=sort_dir)['snapshots']
|
||||
self.assertNotEmpty(snap_list)
|
||||
if sort_key is 'display_name':
|
||||
if sort_key == 'display_name':
|
||||
sort_key = 'name'
|
||||
# Note: On Cinder API, 'display_name' works as a sort key
|
||||
# on a request, a volume name appears as 'name' on the response.
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
from hacking import core
|
||||
import pycodestyle
|
||||
|
||||
|
||||
@@ -25,7 +26,6 @@ PYTHON_CLIENT_RE = re.compile('import (%s)client' % '|'.join(PYTHON_CLIENTS))
|
||||
TEST_DEFINITION = re.compile(r'^\s*def test.*')
|
||||
SETUP_TEARDOWN_CLASS_DEFINITION = re.compile(r'^\s+def (setUp|tearDown)Class')
|
||||
SCENARIO_DECORATOR = re.compile(r'\s*@.*services\((.*)\)')
|
||||
VI_HEADER_RE = re.compile(r"^#\s+vim?:.+")
|
||||
RAND_NAME_HYPHEN_RE = re.compile(r".*rand_name\(.+[\-\_][\"\']\)")
|
||||
mutable_default_args = re.compile(r"^\s*def .+\((.+=\{\}|.+=\[\])")
|
||||
TESTTOOLS_SKIP_DECORATOR = re.compile(r'\s*@testtools\.skip\((.*)\)')
|
||||
@@ -39,6 +39,7 @@ NEGATIVE_TEST_DECORATOR = re.compile(
|
||||
_HAVE_NEGATIVE_DECORATOR = False
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def import_no_clients_in_api_and_scenario_tests(physical_line, filename):
|
||||
"""Check for client imports from tempest/api & tempest/scenario tests
|
||||
|
||||
@@ -53,6 +54,7 @@ def import_no_clients_in_api_and_scenario_tests(physical_line, filename):
|
||||
" in tempest/api/* or tempest/scenario/* tests"))
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def scenario_tests_need_service_tags(physical_line, filename,
|
||||
previous_logical):
|
||||
"""Check that scenario tests have service tags
|
||||
@@ -67,6 +69,7 @@ def scenario_tests_need_service_tags(physical_line, filename,
|
||||
"T104: Scenario tests require a service decorator")
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def no_setup_teardown_class_for_tests(physical_line, filename):
|
||||
|
||||
if pycodestyle.noqa(physical_line):
|
||||
@@ -80,20 +83,7 @@ def no_setup_teardown_class_for_tests(physical_line, filename):
|
||||
"T105: (setUp|tearDown)Class can not be used in tests")
|
||||
|
||||
|
||||
def no_vi_headers(physical_line, line_number, lines):
|
||||
"""Check for vi editor configuration in source files.
|
||||
|
||||
By default vi modelines can only appear in the first or
|
||||
last 5 lines of a source file.
|
||||
|
||||
T106
|
||||
"""
|
||||
# NOTE(gilliard): line_number is 1-indexed
|
||||
if line_number <= 5 or line_number > len(lines) - 5:
|
||||
if VI_HEADER_RE.match(physical_line):
|
||||
return 0, "T106: Don't put vi configuration in source files"
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def service_tags_not_in_module_path(physical_line, filename):
|
||||
"""Check that a service tag isn't in the module path
|
||||
|
||||
@@ -117,6 +107,7 @@ def service_tags_not_in_module_path(physical_line, filename):
|
||||
"T107: service tag should not be in path")
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def no_hyphen_at_end_of_rand_name(logical_line, filename):
|
||||
"""Check no hyphen at the end of rand_name() argument
|
||||
|
||||
@@ -127,6 +118,7 @@ def no_hyphen_at_end_of_rand_name(logical_line, filename):
|
||||
return 0, msg
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def no_mutable_default_args(logical_line):
|
||||
"""Check that mutable object isn't used as default argument
|
||||
|
||||
@@ -137,6 +129,7 @@ def no_mutable_default_args(logical_line):
|
||||
yield (0, msg)
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def no_testtools_skip_decorator(logical_line):
|
||||
"""Check that methods do not have the testtools.skip decorator
|
||||
|
||||
@@ -170,7 +163,8 @@ def _common_service_clients_check(logical_line, physical_line, filename,
|
||||
return True
|
||||
|
||||
|
||||
def get_resources_on_service_clients(logical_line, physical_line, filename,
|
||||
@core.flake8ext
|
||||
def get_resources_on_service_clients(physical_line, logical_line, filename,
|
||||
line_number, lines):
|
||||
"""Check that service client names of GET should be consistent
|
||||
|
||||
@@ -197,7 +191,8 @@ def get_resources_on_service_clients(logical_line, physical_line, filename,
|
||||
yield (0, msg)
|
||||
|
||||
|
||||
def delete_resources_on_service_clients(logical_line, physical_line, filename,
|
||||
@core.flake8ext
|
||||
def delete_resources_on_service_clients(physical_line, logical_line, filename,
|
||||
line_number, lines):
|
||||
"""Check that service client names of DELETE should be consistent
|
||||
|
||||
@@ -223,6 +218,7 @@ def delete_resources_on_service_clients(logical_line, physical_line, filename,
|
||||
yield (0, msg)
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def dont_import_local_tempest_into_lib(logical_line, filename):
|
||||
"""Check that tempest.lib should not import local tempest code
|
||||
|
||||
@@ -244,6 +240,7 @@ def dont_import_local_tempest_into_lib(logical_line, filename):
|
||||
yield (0, msg)
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def use_rand_uuid_instead_of_uuid4(logical_line, filename):
|
||||
"""Check that tests use data_utils.rand_uuid() instead of uuid.uuid4()
|
||||
|
||||
@@ -260,6 +257,7 @@ def use_rand_uuid_instead_of_uuid4(logical_line, filename):
|
||||
yield (0, msg)
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def dont_use_config_in_tempest_lib(logical_line, filename):
|
||||
"""Check that tempest.lib doesn't use tempest config
|
||||
|
||||
@@ -277,7 +275,8 @@ def dont_use_config_in_tempest_lib(logical_line, filename):
|
||||
yield(0, msg)
|
||||
|
||||
|
||||
def dont_put_admin_tests_on_nonadmin_path(logical_line, physical_line,
|
||||
@core.flake8ext
|
||||
def dont_put_admin_tests_on_nonadmin_path(logical_line,
|
||||
filename):
|
||||
"""Check admin tests should exist under admin path
|
||||
|
||||
@@ -287,9 +286,6 @@ def dont_put_admin_tests_on_nonadmin_path(logical_line, physical_line,
|
||||
if 'tempest/api/' not in filename:
|
||||
return
|
||||
|
||||
if pycodestyle.noqa(physical_line):
|
||||
return
|
||||
|
||||
if not re.match(r'class .*Test.*\(.*Admin.*\):', logical_line):
|
||||
return
|
||||
|
||||
@@ -298,6 +294,7 @@ def dont_put_admin_tests_on_nonadmin_path(logical_line, physical_line,
|
||||
yield(0, msg)
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def unsupported_exception_attribute_PY3(logical_line):
|
||||
"""Check Unsupported 'message' exception attribute in PY3
|
||||
|
||||
@@ -309,6 +306,7 @@ def unsupported_exception_attribute_PY3(logical_line):
|
||||
yield(0, msg)
|
||||
|
||||
|
||||
@core.flake8ext
|
||||
def negative_test_attribute_always_applied_to_negative_tests(physical_line,
|
||||
filename):
|
||||
"""Check ``@decorators.attr(type=['negative'])`` applied to negative tests.
|
||||
@@ -330,22 +328,3 @@ def negative_test_attribute_always_applied_to_negative_tests(physical_line,
|
||||
" to all negative API tests"
|
||||
)
|
||||
_HAVE_NEGATIVE_DECORATOR = False
|
||||
|
||||
|
||||
def factory(register):
|
||||
register(import_no_clients_in_api_and_scenario_tests)
|
||||
register(scenario_tests_need_service_tags)
|
||||
register(no_setup_teardown_class_for_tests)
|
||||
register(no_vi_headers)
|
||||
register(service_tags_not_in_module_path)
|
||||
register(no_hyphen_at_end_of_rand_name)
|
||||
register(no_mutable_default_args)
|
||||
register(no_testtools_skip_decorator)
|
||||
register(get_resources_on_service_clients)
|
||||
register(delete_resources_on_service_clients)
|
||||
register(dont_import_local_tempest_into_lib)
|
||||
register(dont_use_config_in_tempest_lib)
|
||||
register(use_rand_uuid_instead_of_uuid4)
|
||||
register(dont_put_admin_tests_on_nonadmin_path)
|
||||
register(unsupported_exception_attribute_PY3)
|
||||
register(negative_test_attribute_always_applied_to_negative_tests)
|
||||
|
||||
@@ -684,7 +684,7 @@ class Credentials(object):
|
||||
|
||||
def __str__(self):
|
||||
"""Represent only attributes included in self.ATTRIBUTES"""
|
||||
attrs = [attr for attr in self.ATTRIBUTES if attr is not 'password']
|
||||
attrs = [attr for attr in self.ATTRIBUTES if attr != 'password']
|
||||
_repr = dict((k, getattr(self, k)) for k in attrs)
|
||||
return str(_repr)
|
||||
|
||||
@@ -741,7 +741,7 @@ class KeystoneV2Credentials(Credentials):
|
||||
|
||||
def __str__(self):
|
||||
"""Represent only attributes included in self.ATTRIBUTES"""
|
||||
attrs = [attr for attr in self.ATTRIBUTES if attr is not 'password']
|
||||
attrs = [attr for attr in self.ATTRIBUTES if attr != 'password']
|
||||
_repr = dict((k, getattr(self, k)) for k in attrs)
|
||||
return str(_repr)
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ class TestObjectClient(base.TestCase):
|
||||
|
||||
# If the expected initial status is not 100, then an exception
|
||||
# should be thrown and the connection closed
|
||||
if initial_status is 100:
|
||||
if initial_status == 100:
|
||||
status, reason = \
|
||||
self.object_client.create_object_continue(cnt, obj, req_data)
|
||||
else:
|
||||
@@ -91,7 +91,7 @@ class TestObjectClient(base.TestCase):
|
||||
mock_poc.return_value.endheaders.assert_called_once_with()
|
||||
|
||||
# The following steps are only taken if the initial status is 100
|
||||
if initial_status is 100:
|
||||
if initial_status == 100:
|
||||
# Verify that the method returned what it was supposed to
|
||||
self.assertEqual(status, 201)
|
||||
|
||||
|
||||
@@ -101,17 +101,6 @@ class HackingTestCase(base.TestCase):
|
||||
'def test_fake:', './tempest/scenario/orchestration/test_fake.py',
|
||||
"\n"))
|
||||
|
||||
def test_no_vi_headers(self):
|
||||
# NOTE(mtreinish) The lines parameter is used only for finding the
|
||||
# line location in the file. So these tests just pass a list of an
|
||||
# arbitrary length to use for verifying the check function.
|
||||
self.assertTrue(checks.no_vi_headers(
|
||||
'# vim: tabstop=4 shiftwidth=4 softtabstop=4', 1, range(250)))
|
||||
self.assertTrue(checks.no_vi_headers(
|
||||
'# vim: tabstop=4 shiftwidth=4 softtabstop=4', 249, range(250)))
|
||||
self.assertFalse(checks.no_vi_headers(
|
||||
'# vim: tabstop=4 shiftwidth=4 softtabstop=4', 149, range(250)))
|
||||
|
||||
def test_service_tags_not_in_module_path(self):
|
||||
self.assertTrue(checks.service_tags_not_in_module_path(
|
||||
"@utils.services('compute')",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
hacking>=1.1.0,<1.2.0 # Apache-2.0
|
||||
hacking>=3.0,<3.1.0;python_version>='3.5' # Apache-2.0
|
||||
mock>=2.0.0 # BSD
|
||||
coverage!=4.4,>=4.0 # Apache-2.0
|
||||
oslotest>=3.2.0 # Apache-2.0
|
||||
|
||||
21
tox.ini
21
tox.ini
@@ -313,7 +313,6 @@ commands =
|
||||
check-uuid --fix
|
||||
|
||||
[hacking]
|
||||
local-check-factory = tempest.hacking.checks.factory
|
||||
import_exceptions = tempest.services
|
||||
|
||||
[flake8]
|
||||
@@ -327,6 +326,26 @@ exclude = .git,.venv,.tox,dist,doc,*egg,build
|
||||
enable-extensions = H106,H203,H904
|
||||
import-order-style = pep8
|
||||
|
||||
[flake8:local-plugins]
|
||||
extension =
|
||||
T102 = checks:import_no_clients_in_api_and_scenario_tests
|
||||
T104 = checks:scenario_tests_need_service_tags
|
||||
T105 = checks:no_setup_teardown_class_for_tests
|
||||
T107 = checks:service_tags_not_in_module_path
|
||||
T108 = checks:no_hyphen_at_end_of_rand_name
|
||||
N322 = checks:no_mutable_default_args
|
||||
T109 = checks:no_testtools_skip_decorator
|
||||
T110 = checks:get_resources_on_service_clients
|
||||
T111 = checks:delete_resources_on_service_clients
|
||||
T112 = checks:dont_import_local_tempest_into_lib
|
||||
T113 = checks:use_rand_uuid_instead_of_uuid4
|
||||
T114 = checks:dont_use_config_in_tempest_lib
|
||||
T115 = checks:dont_put_admin_tests_on_nonadmin_path
|
||||
T116 = checks:unsupported_exception_attribute_PY3
|
||||
T117 = checks:negative_test_attribute_always_applied_to_negative_tests
|
||||
paths =
|
||||
./tempest/hacking
|
||||
|
||||
[testenv:releasenotes]
|
||||
deps =
|
||||
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
|
||||
|
||||
Reference in New Issue
Block a user