Bump to hacking 1.1.0

This brings in a couple of new checks which must be addressed, many of
which involve a rather large amount of changes, so these are ignored for
now. A series of follow-up changes will resolved these.

'pycodestyle' is added as a dependency rather than it being pulled in
transitively. This is necessary since we're using it in tests.

Change-Id: I35c654bd39f343417e0a1124263ff31dcd0b05c9
Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
This commit is contained in:
Stephen Finucane 2019-04-10 10:02:03 +01:00
parent e18b79ef87
commit 3e65f778bd
44 changed files with 171 additions and 147 deletions

View File

@ -101,7 +101,6 @@ paramiko==2.0.0
Paste==2.0.2 Paste==2.0.2
PasteDeploy==1.5.0 PasteDeploy==1.5.0
pbr==2.0.0 pbr==2.0.0
pep8==1.5.7
pluggy==0.6.0 pluggy==0.6.0
ply==3.11 ply==3.11
prettytable==0.7.1 prettytable==0.7.1
@ -113,6 +112,7 @@ pyasn1-modules==0.2.1
pycadf==2.7.0 pycadf==2.7.0
pycparser==2.18 pycparser==2.18
pyflakes==0.8.1 pyflakes==0.8.1
pycodestyle==2.0.0
pyinotify==0.9.6 pyinotify==0.9.6
pyroute2==0.5.4 pyroute2==0.5.4
PyJWT==1.7.0 PyJWT==1.7.0

View File

@ -88,9 +88,11 @@ class AvailabilityZoneController(wsgi.Controller):
hosts[host] = {} hosts[host] = {}
for service in host_services[zone + host]: for service in host_services[zone + host]:
alive = self.servicegroup_api.service_is_up(service) alive = self.servicegroup_api.service_is_up(service)
hosts[host][service['binary']] = {'available': alive, hosts[host][service['binary']] = {
'active': True != service['disabled'], 'available': alive,
'updated_at': service['updated_at']} 'active': service['disabled'] is not True,
'updated_at': service['updated_at']
}
result.append({'zoneName': zone, result.append({'zoneName': zone,
'zoneState': {'available': True}, 'zoneState': {'available': True},
"hosts": hosts}) "hosts": hosts})

View File

@ -190,4 +190,6 @@ def _register_network_quota():
QUOTAS.register_resource(quota.CountableResource('networks', QUOTAS.register_resource(quota.CountableResource('networks',
_network_count, _network_count,
'quota_networks')) 'quota_networks'))
_register_network_quota() _register_network_quota()

View File

@ -19,13 +19,13 @@ from oslo_log import log as logging
import paste.urlmap import paste.urlmap
import six import six
from nova.api.openstack import wsgi
if six.PY2: if six.PY2:
import urllib2 import urllib2
else: else:
from urllib import request as urllib2 from urllib import request as urllib2
from nova.api.openstack import wsgi
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)

View File

@ -164,6 +164,7 @@ def _build_regex_range(ws=True, invert=False, exclude=None):
regex += "-" + re.escape(c) regex += "-" + re.escape(c)
return regex return regex
valid_name_regex_base = '^(?![%s])[%s]*(?<![%s])$' valid_name_regex_base = '^(?![%s])[%s]*(?<![%s])$'

View File

@ -105,6 +105,7 @@ def enrich_help_text(alt_db_opts):
# texts here if needed. # texts here if needed.
alt_db_opt.help = db_opt.help + alt_db_opt.help alt_db_opt.help = db_opt.help + alt_db_opt.help
# NOTE(cdent): See the note above on api_db_group. The same issues # NOTE(cdent): See the note above on api_db_group. The same issues
# apply here. # apply here.

View File

@ -232,7 +232,8 @@ class RequestContext(context.RequestContext):
return context return context
def can(self, action, target=None, fatal=True): def can(self, action, target=None, fatal=True):
"""Verifies that the given action is valid on the target in this context. """Verifies that the given action is valid on the target in this
context.
:param action: string representing the action to be checked. :param action: string representing the action to be checked.
:param target: dictionary representing the object of the action :param target: dictionary representing the object of the action

View File

@ -17,7 +17,6 @@ import ast
import os import os
import re import re
import pep8
import six import six
""" """
@ -122,7 +121,7 @@ class BaseASTChecker(ast.NodeVisitor):
""" """
def __init__(self, tree, filename): def __init__(self, tree, filename):
"""This object is created automatically by pep8. """This object is created automatically by pycodestyle.
:param tree: an AST tree :param tree: an AST tree
:param filename: name of the file being analyzed :param filename: name of the file being analyzed
@ -132,12 +131,12 @@ class BaseASTChecker(ast.NodeVisitor):
self._errors = [] self._errors = []
def run(self): def run(self):
"""Called automatically by pep8.""" """Called automatically by pycodestyle."""
self.visit(self._tree) self.visit(self._tree)
return self._errors return self._errors
def add_error(self, node, message=None): def add_error(self, node, message=None):
"""Add an error caused by a node to the list of errors for pep8.""" """Add an error caused by a node to the list of errors."""
message = message or self.CHECK_DESC message = message or self.CHECK_DESC
error = (node.lineno, node.col_offset, message, self.__class__) error = (node.lineno, node.col_offset, message, self.__class__)
self._errors.append(error) self._errors.append(error)
@ -558,10 +557,10 @@ def assert_equal_in(logical_line):
"contents.") "contents.")
def check_http_not_implemented(logical_line, physical_line, filename): def check_http_not_implemented(logical_line, physical_line, filename, noqa):
msg = ("N339: HTTPNotImplemented response must be implemented with" msg = ("N339: HTTPNotImplemented response must be implemented with"
" common raise_feature_not_supported().") " common raise_feature_not_supported().")
if pep8.noqa(physical_line): if noqa:
return return
if ("nova/api/openstack/compute" not in filename): if ("nova/api/openstack/compute" not in filename):
return return
@ -722,7 +721,7 @@ def no_log_warn(logical_line):
yield (0, msg) yield (0, msg)
def check_context_log(logical_line, physical_line, filename): def check_context_log(logical_line, physical_line, filename, noqa):
"""check whether context is being passed to the logs """check whether context is being passed to the logs
Not correct: LOG.info(_LI("Rebooting instance"), context=context) Not correct: LOG.info(_LI("Rebooting instance"), context=context)
@ -731,10 +730,10 @@ def check_context_log(logical_line, physical_line, filename):
N353 N353
""" """
if "nova/tests" in filename: if noqa:
return return
if pep8.noqa(physical_line): if "nova/tests" in filename:
return return
if log_remove_context.match(logical_line): if log_remove_context.match(logical_line):

View File

@ -88,6 +88,7 @@ def _monkey_patch():
"importing and not executing nova code.", "importing and not executing nova code.",
', '.join(problems)) ', '.join(problems))
# NOTE(mdbooth): This workaround is required to avoid breaking sphinx. See # NOTE(mdbooth): This workaround is required to avoid breaking sphinx. See
# separate comment in doc/source/conf.py. It may also be useful for other # separate comment in doc/source/conf.py. It may also be useful for other
# non-nova utilities. Ideally the requirement for this workaround will be # non-nova utilities. Ideally the requirement for this workaround will be

View File

@ -57,6 +57,7 @@ def get_binary_name():
"""Grab the name of the binary we're running in.""" """Grab the name of the binary we're running in."""
return os.path.basename(inspect.stack()[-1][1])[:16] return os.path.basename(inspect.stack()[-1][1])[:16]
binary_name = get_binary_name() binary_name = get_binary_name()

View File

@ -12,19 +12,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
__all__ = [
'init',
'cleanup',
'set_defaults',
'add_extra_exmods',
'clear_extra_exmods',
'get_allowed_exmods',
'RequestContextSerializer',
'get_client',
'get_server',
'get_notifier',
]
import functools import functools
from oslo_log import log as logging from oslo_log import log as logging
@ -40,6 +27,19 @@ import nova.context
import nova.exception import nova.exception
from nova.i18n import _ from nova.i18n import _
__all__ = [
'init',
'cleanup',
'set_defaults',
'add_extra_exmods',
'clear_extra_exmods',
'get_allowed_exmods',
'RequestContextSerializer',
'get_client',
'get_server',
'get_notifier',
]
profiler = importutils.try_import("osprofiler.profiler") profiler = importutils.try_import("osprofiler.profiler")

View File

@ -255,8 +255,8 @@ class InstanceHelperMixin(object):
retry_count += 1 retry_count += 1
if retry_count == max_retries: if retry_count == max_retries:
self.fail('Wait for state change failed, ' self.fail('Wait for state change failed, '
'expected_params=%s, server=%s' 'expected_params=%s, server=%s' % (
% (expected_params, server)) expected_params, server))
time.sleep(0.5) time.sleep(0.5)
return server return server

View File

@ -75,8 +75,8 @@ def fake_get_flavor_by_flavor_id(context, flavorid):
def _has_flavor_access(flavorid, projectid): def _has_flavor_access(flavorid, projectid):
for access in ACCESS_LIST: for access in ACCESS_LIST:
if access['flavor_id'] == flavorid and \ if (access['flavor_id'] == flavorid and
access['project_id'] == projectid: access['project_id'] == projectid):
return True return True
return False return False

View File

@ -93,7 +93,8 @@ def fake_instance_get(context, instance_id):
"uuid": uuids.fake, "uuid": uuids.fake,
"name": 'fake', "name": 'fake',
"user_id": 'fakeuser', "user_id": 'fakeuser',
"project_id": '123'}) "project_id": '123'
})
def stub_nw_info(test): def stub_nw_info(test):

View File

@ -152,7 +152,8 @@ class ServerMigrationsTestsV21(test.NoDBTestCase):
def test_force_complete_unexpected_error(self): def test_force_complete_unexpected_error(self):
self._test_force_complete_failed_with_exception( self._test_force_complete_failed_with_exception(
exception.NovaException(), webob.exc.HTTPInternalServerError) exception.NovaException(),
webob.exc.HTTPInternalServerError)
class ServerMigrationsTestsV223(ServerMigrationsTestsV21): class ServerMigrationsTestsV223(ServerMigrationsTestsV21):

View File

@ -292,6 +292,7 @@ class _FakeImageService(object):
return 'fake_location' return 'fake_location'
return None return None
_fakeImageService = _FakeImageService() _fakeImageService = _FakeImageService()

View File

@ -48,6 +48,7 @@ class tzinfo(datetime.tzinfo):
def utcoffset(*args, **kwargs): def utcoffset(*args, **kwargs):
return datetime.timedelta() return datetime.timedelta()
NOW_DATETIME = datetime.datetime(2010, 10, 11, 10, 30, 22, tzinfo=tzinfo()) NOW_DATETIME = datetime.datetime(2010, 10, 11, 10, 30, 22, tzinfo=tzinfo())
@ -67,6 +68,7 @@ class FakeSchema(object):
def raw(self): def raw(self):
return copy.deepcopy(self.raw_schema) return copy.deepcopy(self.raw_schema)
image_fixtures = { image_fixtures = {
'active_image_v1': { 'active_image_v1': {
'checksum': 'eb9139e4942121f22bbc2afc0400b2a4', 'checksum': 'eb9139e4942121f22bbc2afc0400b2a4',

View File

@ -3635,7 +3635,6 @@ class TestNeutronv2WithMock(TestNeutronv2Base):
side_effect=_fake_list_ports), side_effect=_fake_list_ports),
mock.patch.object(client.Client, 'show_quota', mock.patch.object(client.Client, 'show_quota',
return_value={'quota': {'port': 1}})): return_value={'quota': {'port': 1}})):
exc = self.assertRaises(exception.PortLimitExceeded, exc = self.assertRaises(exception.PortLimitExceeded,
self.api.validate_networks, self.api.validate_networks,
self.context, requested_networks, 1) self.context, requested_networks, 1)

View File

@ -364,6 +364,7 @@ class TestNotificationBase(test.NoDBTestCase):
self.assertFalse(payload.populated) self.assertFalse(payload.populated)
self.assertFalse(mock_emit.called) self.assertFalse(mock_emit.called)
notification_object_data = { notification_object_data = {
'AggregateNotification': '1.0-a73147b93b520ff0061865849d3dfa56', 'AggregateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'AggregatePayload': '1.1-1eb9adcc4440d8627de6ec37c6398746', 'AggregatePayload': '1.1-1eb9adcc4440d8627de6ec37c6398746',

View File

@ -56,6 +56,7 @@ def _fake_service(**kwargs):
fake_service.update(kwargs) fake_service.update(kwargs)
return fake_service return fake_service
fake_service = _fake_service() fake_service = _fake_service()
OPTIONAL = ['availability_zone', 'compute_node'] OPTIONAL = ['availability_zone', 'compute_node']

View File

@ -16,7 +16,7 @@ import sys
import textwrap import textwrap
import mock import mock
import pep8 import pycodestyle
import testtools import testtools
from nova.hacking import checks from nova.hacking import checks
@ -25,10 +25,10 @@ from nova import test
class HackingTestCase(test.NoDBTestCase): class HackingTestCase(test.NoDBTestCase):
"""This class tests the hacking checks in nova.hacking.checks by passing """This class tests the hacking checks in nova.hacking.checks by passing
strings to the check methods like the pep8/flake8 parser would. The parser strings to the check methods like the pycodestyle/flake8 parser would. The
loops over each line in the file and then passes the parameters to the parser loops over each line in the file and then passes the parameters to
check method. The parameter names in the check method dictate what type of the check method. The parameter names in the check method dictate what type
object is passed to the check method. The parameter types are:: of object is passed to the check method. The parameter types are::
logical_line: A processed line with the following modifications: logical_line: A processed line with the following modifications:
- Multi-line statements converted to a single line. - Multi-line statements converted to a single line.
@ -45,7 +45,7 @@ class HackingTestCase(test.NoDBTestCase):
indent_level: indentation (with tabs expanded to multiples of 8) indent_level: indentation (with tabs expanded to multiples of 8)
previous_indent_level: indentation on previous line previous_indent_level: indentation on previous line
previous_logical: previous logical line previous_logical: previous logical line
filename: Path of the file being run through pep8 filename: Path of the file being run through pycodestyle
When running a test on a check method the return will be False/None if When running a test on a check method the return will be False/None if
there is no violation in the sample input. If there is an error a tuple is there is no violation in the sample input. If there is an error a tuple is
@ -270,20 +270,20 @@ class HackingTestCase(test.NoDBTestCase):
len(list(checks.use_jsonutils("json.dumb", len(list(checks.use_jsonutils("json.dumb",
"./nova/virt/xenapi/driver.py")))) "./nova/virt/xenapi/driver.py"))))
# We are patching pep8 so that only the check under test is actually # We are patching pycodestyle so that only the check under test is actually
# installed. # installed.
@mock.patch('pep8._checks', @mock.patch('pycodestyle._checks',
{'physical_line': {}, 'logical_line': {}, 'tree': {}}) {'physical_line': {}, 'logical_line': {}, 'tree': {}})
def _run_check(self, code, checker, filename=None): def _run_check(self, code, checker, filename=None):
pep8.register_check(checker) pycodestyle.register_check(checker)
lines = textwrap.dedent(code).strip().splitlines(True) lines = textwrap.dedent(code).strip().splitlines(True)
checker = pep8.Checker(filename=filename, lines=lines) checker = pycodestyle.Checker(filename=filename, lines=lines)
# NOTE(sdague): the standard reporter has printing to stdout # NOTE(sdague): the standard reporter has printing to stdout
# as a normal part of check_all, which bleeds through to the # as a normal part of check_all, which bleeds through to the
# test output stream in an unhelpful way. This blocks that printing. # test output stream in an unhelpful way. This blocks that printing.
with mock.patch('pep8.StandardReport.get_file_results'): with mock.patch('pycodestyle.StandardReport.get_file_results'):
checker.check_all() checker.check_all()
checker.report._deferred_print.sort() checker.report._deferred_print.sort()
return checker.report._deferred_print return checker.report._deferred_print
@ -587,7 +587,7 @@ class HackingTestCase(test.NoDBTestCase):
def test_check_doubled_words(self): def test_check_doubled_words(self):
errors = [(1, 0, "N343")] errors = [(1, 0, "N343")]
# Artificial break to stop pep8 detecting the test ! # Artificial break to stop flake8 detecting the test !
code = "This is the" + " the best comment" code = "This is the" + " the best comment"
self._assert_has_errors(code, checks.check_doubled_words, self._assert_has_errors(code, checks.check_doubled_words,
expected_errors=errors) expected_errors=errors)

View File

@ -103,6 +103,7 @@ def get_test_instance(context=None, flavor=None, obj=False):
instance = db.instance_create(context, test_instance) instance = db.instance_create(context, test_instance)
return instance return instance
FAKE_NETWORK_VLAN = 100 FAKE_NETWORK_VLAN = 100
FAKE_NETWORK_BRIDGE = 'br0' FAKE_NETWORK_BRIDGE = 'br0'
FAKE_NETWORK_INTERFACE = 'eth0' FAKE_NETWORK_INTERFACE = 'eth0'

View File

@ -1034,7 +1034,7 @@ class Domain(object):
<address uuid='%(address_uuid)s'/> <address uuid='%(address_uuid)s'/>
</source> </source>
</hostdev> </hostdev>
''' % hostdev ''' % hostdev # noqa
return '''<domain type='kvm'> return '''<domain type='kvm'>
<name>%(name)s</name> <name>%(name)s</name>

View File

@ -27,9 +27,6 @@ import os
import random import random
import tempfile import tempfile
if os.name != 'nt':
import crypt
from oslo_concurrency import processutils from oslo_concurrency import processutils
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
@ -44,6 +41,9 @@ from nova.virt.disk.vfs import api as vfs
from nova.virt.image import model as imgmodel from nova.virt.image import model as imgmodel
from nova.virt import images from nova.virt import images
if os.name != 'nt':
import crypt
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)

View File

@ -164,6 +164,7 @@ class InjectionInfo(collections.namedtuple(
return ('InjectionInfo(network_info=%r, files=%r, ' return ('InjectionInfo(network_info=%r, files=%r, '
'admin_pass=<SANITIZED>)') % (self.network_info, self.files) 'admin_pass=<SANITIZED>)') % (self.network_info, self.files)
libvirt_volume_drivers = [ libvirt_volume_drivers = [
'iscsi=nova.virt.libvirt.volume.iscsi.LibvirtISCSIVolumeDriver', 'iscsi=nova.virt.libvirt.volume.iscsi.LibvirtISCSIVolumeDriver',
'iser=nova.virt.libvirt.volume.iser.LibvirtISERVolumeDriver', 'iser=nova.virt.libvirt.volume.iser.LibvirtISERVolumeDriver',

View File

@ -145,6 +145,7 @@ def vm_ref_cache_from_name(func):
return _vm_ref_cache(id, func, session, name) return _vm_ref_cache(id, func, session, name)
return wrapper return wrapper
# the config key which stores the VNC port # the config key which stores the VNC port
VNC_CONFIG_KEY = 'config.extraConfig["RemoteDisplay.vnc.port"]' VNC_CONFIG_KEY = 'config.extraConfig["RemoteDisplay.vnc.port"]'

View File

@ -424,7 +424,8 @@ def translate_volume_exception(method):
def translate_attachment_exception(method): def translate_attachment_exception(method):
"""Transforms the exception for the attachment but keeps its traceback intact. """Transforms the exception for the attachment but keeps its traceback
intact.
""" """
def wrapper(self, ctx, attachment_id, *args, **kwargs): def wrapper(self, ctx, attachment_id, *args, **kwargs):
try: try:

View File

@ -2,7 +2,7 @@
# 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.13.0,<0.14,>=0.12.0 # Apache-2.0 hacking>=1.1.0,<1.2.0 # Apache-2.0
coverage!=4.4,>=4.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0
ddt>=1.0.1 # MIT ddt>=1.0.1 # MIT
fixtures>=3.0.0 # Apache-2.0/BSD fixtures>=3.0.0 # Apache-2.0/BSD
@ -10,6 +10,7 @@ mock>=2.0.0 # BSD
mox3>=0.20.0 # Apache-2.0 mox3>=0.20.0 # Apache-2.0
psycopg2>=2.7 # LGPL/ZPL psycopg2>=2.7 # LGPL/ZPL
PyMySQL>=0.7.6 # MIT License PyMySQL>=0.7.6 # MIT License
pycodestyle>=2.0.0 # MIT License
python-barbicanclient>=4.5.2 # Apache-2.0 python-barbicanclient>=4.5.2 # Apache-2.0
python-ironicclient>=2.7.0 # Apache-2.0 python-ironicclient>=2.7.0 # Apache-2.0
requests-mock>=1.2.0 # Apache-2.0 requests-mock>=1.2.0 # Apache-2.0

11
tox.ini
View File

@ -250,14 +250,19 @@ commands = bandit -r nova -x tests -n 5 -ll
# line. Rejecting code for this reason is wrong. # line. Rejecting code for this reason is wrong.
# #
# E251 Skipped due to https://github.com/jcrocholl/pep8/issues/301 # E251 Skipped due to https://github.com/jcrocholl/pep8/issues/301
#
# W504 skipped since you must choose either W503 or W504 (they conflict)
#
# W503, W605, E731, and E741 temporarily skipped because of the number of
# these that have to be fixed
enable-extensions = H106,H203,H904 enable-extensions = H106,H203,H904
ignore = E121,E122,E123,E124,E125,E126,E127,E128,E129,E131,E251,H405 ignore = E121,E122,E123,E124,E125,E126,E127,E128,E129,E131,E251,H405,W504,W605,W503,E731,E741
exclude = .venv,.git,.tox,dist,*lib/python*,*egg,build,tools/xenserver*,releasenotes exclude = .venv,.git,.tox,dist,*lib/python*,*egg,build,tools/xenserver*,releasenotes
# To get a list of functions that are more complex than 25, set max-complexity # To get a list of functions that are more complex than 25, set max-complexity
# to 25 and run 'tox -epep8'. # to 25 and run 'tox -epep8'.
# 34 is currently the most complex thing we have # 39 is currently the most complex thing we have
# TODO(jogo): get this number down to 25 or so # TODO(jogo): get this number down to 25 or so
max-complexity=35 max-complexity=40
[hacking] [hacking]
local-check-factory = nova.hacking.checks.factory local-check-factory = nova.hacking.checks.factory