Merge "Remove hacking rules for python 2/3 compatibility"
This commit is contained in:
@@ -31,9 +31,7 @@ Nova Specific Commandments
|
|||||||
- [N322] Method's default argument shouldn't be mutable
|
- [N322] Method's default argument shouldn't be mutable
|
||||||
- [N323] Ensure that the _() function is explicitly imported to ensure proper translations.
|
- [N323] Ensure that the _() function is explicitly imported to ensure proper translations.
|
||||||
- [N324] Ensure that jsonutils.%(fun)s must be used instead of json.%(fun)s
|
- [N324] Ensure that jsonutils.%(fun)s must be used instead of json.%(fun)s
|
||||||
- [N325] str() and unicode() cannot be used on an exception. Remove use or use six.text_type()
|
|
||||||
- [N326] Translated messages cannot be concatenated. String should be included in translated message.
|
- [N326] Translated messages cannot be concatenated. String should be included in translated message.
|
||||||
- [N327] Do not use xrange(). xrange() is not compatible with Python 3. Use range() or six.moves.range() instead.
|
|
||||||
- [N332] Check that the api_version decorator is the first decorator on a method
|
- [N332] Check that the api_version decorator is the first decorator on a method
|
||||||
- [N334] Change assertTrue/False(A in/not in B, message) to the more specific
|
- [N334] Change assertTrue/False(A in/not in B, message) to the more specific
|
||||||
assertIn/NotIn(A, B, message)
|
assertIn/NotIn(A, B, message)
|
||||||
@@ -48,9 +46,6 @@ Nova Specific Commandments
|
|||||||
- [N341] contextlib.nested is deprecated
|
- [N341] contextlib.nested is deprecated
|
||||||
- [N342] Config options should be in the central location ``nova/conf/``
|
- [N342] Config options should be in the central location ``nova/conf/``
|
||||||
- [N343] Check for common double word typos
|
- [N343] Check for common double word typos
|
||||||
- [N344] Python 3: do not use dict.iteritems.
|
|
||||||
- [N345] Python 3: do not use dict.iterkeys.
|
|
||||||
- [N346] Python 3: do not use dict.itervalues.
|
|
||||||
- [N348] Deprecated library function os.popen()
|
- [N348] Deprecated library function os.popen()
|
||||||
- [N349] Check for closures in tests which are not used
|
- [N349] Check for closures in tests which are not used
|
||||||
- [N350] Policy registration should be in the central location ``nova/policies/``
|
- [N350] Policy registration should be in the central location ``nova/policies/``
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import os
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from hacking import core
|
from hacking import core
|
||||||
import six
|
|
||||||
|
|
||||||
|
|
||||||
UNDERSCORE_IMPORT_FILES = []
|
UNDERSCORE_IMPORT_FILES = []
|
||||||
@@ -292,13 +291,6 @@ def assert_equal_type(logical_line):
|
|||||||
yield (0, "N317: assertEqual(type(A), B) sentences not allowed")
|
yield (0, "N317: assertEqual(type(A), B) sentences not allowed")
|
||||||
|
|
||||||
|
|
||||||
@core.flake8ext
|
|
||||||
def check_python3_xrange(logical_line):
|
|
||||||
if re.search(r"\bxrange\s*\(", logical_line):
|
|
||||||
yield (0, "N327: Do not use xrange(). 'xrange()' is not compatible "
|
|
||||||
"with Python 3. Use range() or six.moves.range() instead.")
|
|
||||||
|
|
||||||
|
|
||||||
@core.flake8ext
|
@core.flake8ext
|
||||||
def no_translate_logs(logical_line, filename):
|
def no_translate_logs(logical_line, filename):
|
||||||
"""Check for 'LOG.foo(_('
|
"""Check for 'LOG.foo(_('
|
||||||
@@ -400,58 +392,6 @@ def check_api_version_decorator(logical_line, previous_logical, blank_before,
|
|||||||
yield (0, msg)
|
yield (0, msg)
|
||||||
|
|
||||||
|
|
||||||
class CheckForStrUnicodeExc(BaseASTChecker):
|
|
||||||
"""Checks for the use of str() or unicode() on an exception.
|
|
||||||
|
|
||||||
This currently only handles the case where str() or unicode()
|
|
||||||
is used in the scope of an exception handler. If the exception
|
|
||||||
is passed into a function, returned from an assertRaises, or
|
|
||||||
used on an exception created in the same scope, this does not
|
|
||||||
catch it.
|
|
||||||
"""
|
|
||||||
|
|
||||||
name = 'check_for_string_unicode_exc'
|
|
||||||
version = '1.0'
|
|
||||||
|
|
||||||
CHECK_DESC = ('N325 str() and unicode() cannot be used on an '
|
|
||||||
'exception. Remove or use six.text_type()')
|
|
||||||
|
|
||||||
def __init__(self, tree, filename):
|
|
||||||
super(CheckForStrUnicodeExc, self).__init__(tree, filename)
|
|
||||||
self.name = []
|
|
||||||
self.already_checked = []
|
|
||||||
|
|
||||||
# Python 2 produces ast.TryExcept and ast.TryFinally nodes, but Python 3
|
|
||||||
# only produces ast.Try nodes.
|
|
||||||
if six.PY2:
|
|
||||||
def visit_TryExcept(self, node):
|
|
||||||
for handler in node.handlers:
|
|
||||||
if handler.name:
|
|
||||||
self.name.append(handler.name.id)
|
|
||||||
super(CheckForStrUnicodeExc, self).generic_visit(node)
|
|
||||||
self.name = self.name[:-1]
|
|
||||||
else:
|
|
||||||
super(CheckForStrUnicodeExc, self).generic_visit(node)
|
|
||||||
else:
|
|
||||||
def visit_Try(self, node):
|
|
||||||
for handler in node.handlers:
|
|
||||||
if handler.name:
|
|
||||||
self.name.append(handler.name)
|
|
||||||
super(CheckForStrUnicodeExc, self).generic_visit(node)
|
|
||||||
self.name = self.name[:-1]
|
|
||||||
else:
|
|
||||||
super(CheckForStrUnicodeExc, self).generic_visit(node)
|
|
||||||
|
|
||||||
def visit_Call(self, node):
|
|
||||||
if self._check_call_names(node, ['str', 'unicode']):
|
|
||||||
if node not in self.already_checked:
|
|
||||||
self.already_checked.append(node)
|
|
||||||
if isinstance(node.args[0], ast.Name):
|
|
||||||
if node.args[0].id in self.name:
|
|
||||||
self.add_error(node.args[0])
|
|
||||||
super(CheckForStrUnicodeExc, self).generic_visit(node)
|
|
||||||
|
|
||||||
|
|
||||||
class CheckForTransAdd(BaseASTChecker):
|
class CheckForTransAdd(BaseASTChecker):
|
||||||
"""Checks for the use of concatenation on a translated string.
|
"""Checks for the use of concatenation on a translated string.
|
||||||
|
|
||||||
@@ -723,30 +663,6 @@ def check_doubled_words(physical_line, filename):
|
|||||||
return (0, msg % {'word': match.group(1)})
|
return (0, msg % {'word': match.group(1)})
|
||||||
|
|
||||||
|
|
||||||
@core.flake8ext
|
|
||||||
def check_python3_no_iteritems(logical_line):
|
|
||||||
msg = ("N344: Use items() instead of dict.iteritems().")
|
|
||||||
|
|
||||||
if re.search(r".*\.iteritems\(\)", logical_line):
|
|
||||||
yield (0, msg)
|
|
||||||
|
|
||||||
|
|
||||||
@core.flake8ext
|
|
||||||
def check_python3_no_iterkeys(logical_line):
|
|
||||||
msg = ("N345: Use six.iterkeys() instead of dict.iterkeys().")
|
|
||||||
|
|
||||||
if re.search(r".*\.iterkeys\(\)", logical_line):
|
|
||||||
yield (0, msg)
|
|
||||||
|
|
||||||
|
|
||||||
@core.flake8ext
|
|
||||||
def check_python3_no_itervalues(logical_line):
|
|
||||||
msg = ("N346: Use six.itervalues() instead of dict.itervalues().")
|
|
||||||
|
|
||||||
if re.search(r".*\.itervalues\(\)", logical_line):
|
|
||||||
yield (0, msg)
|
|
||||||
|
|
||||||
|
|
||||||
@core.flake8ext
|
@core.flake8ext
|
||||||
def no_os_popen(logical_line):
|
def no_os_popen(logical_line):
|
||||||
"""Disallow 'os.popen('
|
"""Disallow 'os.popen('
|
||||||
|
|||||||
@@ -285,71 +285,6 @@ class HackingTestCase(test.NoDBTestCase):
|
|||||||
def _assert_has_no_errors(self, code, checker, filename=None):
|
def _assert_has_no_errors(self, code, checker, filename=None):
|
||||||
self._assert_has_errors(code, checker, filename=filename)
|
self._assert_has_errors(code, checker, filename=filename)
|
||||||
|
|
||||||
def test_str_unicode_exception(self):
|
|
||||||
|
|
||||||
checker = checks.CheckForStrUnicodeExc
|
|
||||||
code = """
|
|
||||||
def f(a, b):
|
|
||||||
try:
|
|
||||||
p = str(a) + str(b)
|
|
||||||
except ValueError as e:
|
|
||||||
p = str(e)
|
|
||||||
return p
|
|
||||||
"""
|
|
||||||
errors = [(5, 16, 'N325')]
|
|
||||||
self._assert_has_errors(code, checker, expected_errors=errors)
|
|
||||||
|
|
||||||
code = """
|
|
||||||
def f(a, b):
|
|
||||||
try:
|
|
||||||
p = unicode(a) + str(b)
|
|
||||||
except ValueError as e:
|
|
||||||
p = e
|
|
||||||
return p
|
|
||||||
"""
|
|
||||||
self._assert_has_no_errors(code, checker)
|
|
||||||
|
|
||||||
code = """
|
|
||||||
def f(a, b):
|
|
||||||
try:
|
|
||||||
p = str(a) + str(b)
|
|
||||||
except ValueError as e:
|
|
||||||
p = unicode(e)
|
|
||||||
return p
|
|
||||||
"""
|
|
||||||
errors = [(5, 20, 'N325')]
|
|
||||||
self._assert_has_errors(code, checker, expected_errors=errors)
|
|
||||||
|
|
||||||
code = """
|
|
||||||
def f(a, b):
|
|
||||||
try:
|
|
||||||
p = str(a) + str(b)
|
|
||||||
except ValueError as e:
|
|
||||||
try:
|
|
||||||
p = unicode(a) + unicode(b)
|
|
||||||
except ValueError as ve:
|
|
||||||
p = str(e) + str(ve)
|
|
||||||
p = e
|
|
||||||
return p
|
|
||||||
"""
|
|
||||||
errors = [(8, 20, 'N325'), (8, 29, 'N325')]
|
|
||||||
self._assert_has_errors(code, checker, expected_errors=errors)
|
|
||||||
|
|
||||||
code = """
|
|
||||||
def f(a, b):
|
|
||||||
try:
|
|
||||||
p = str(a) + str(b)
|
|
||||||
except ValueError as e:
|
|
||||||
try:
|
|
||||||
p = unicode(a) + unicode(b)
|
|
||||||
except ValueError as ve:
|
|
||||||
p = str(e) + unicode(ve)
|
|
||||||
p = str(e)
|
|
||||||
return p
|
|
||||||
"""
|
|
||||||
errors = [(8, 20, 'N325'), (8, 33, 'N325'), (9, 16, 'N325')]
|
|
||||||
self._assert_has_errors(code, checker, expected_errors=errors)
|
|
||||||
|
|
||||||
def test_api_version_decorator_check(self):
|
def test_api_version_decorator_check(self):
|
||||||
code = """
|
code = """
|
||||||
@some_other_decorator
|
@some_other_decorator
|
||||||
@@ -571,27 +506,6 @@ class HackingTestCase(test.NoDBTestCase):
|
|||||||
code = "'This is the then best comment'\n"
|
code = "'This is the then best comment'\n"
|
||||||
self._assert_has_no_errors(code, checks.check_doubled_words)
|
self._assert_has_no_errors(code, checks.check_doubled_words)
|
||||||
|
|
||||||
def test_dict_iteritems(self):
|
|
||||||
self.assertEqual(1, len(list(checks.check_python3_no_iteritems(
|
|
||||||
"obj.iteritems()"))))
|
|
||||||
|
|
||||||
self.assertEqual(0, len(list(checks.check_python3_no_iteritems(
|
|
||||||
"six.iteritems(ob))"))))
|
|
||||||
|
|
||||||
def test_dict_iterkeys(self):
|
|
||||||
self.assertEqual(1, len(list(checks.check_python3_no_iterkeys(
|
|
||||||
"obj.iterkeys()"))))
|
|
||||||
|
|
||||||
self.assertEqual(0, len(list(checks.check_python3_no_iterkeys(
|
|
||||||
"six.iterkeys(ob))"))))
|
|
||||||
|
|
||||||
def test_dict_itervalues(self):
|
|
||||||
self.assertEqual(1, len(list(checks.check_python3_no_itervalues(
|
|
||||||
"obj.itervalues()"))))
|
|
||||||
|
|
||||||
self.assertEqual(0, len(list(checks.check_python3_no_itervalues(
|
|
||||||
"six.itervalues(ob))"))))
|
|
||||||
|
|
||||||
def test_no_os_popen(self):
|
def test_no_os_popen(self):
|
||||||
code = """
|
code = """
|
||||||
import os
|
import os
|
||||||
@@ -685,13 +599,6 @@ class HackingTestCase(test.NoDBTestCase):
|
|||||||
"""
|
"""
|
||||||
self._assert_has_no_errors(code, checks.check_policy_enforce)
|
self._assert_has_no_errors(code, checks.check_policy_enforce)
|
||||||
|
|
||||||
def test_check_python3_xrange(self):
|
|
||||||
func = checks.check_python3_xrange
|
|
||||||
self.assertEqual(1, len(list(func('for i in xrange(10)'))))
|
|
||||||
self.assertEqual(1, len(list(func('for i in xrange (10)'))))
|
|
||||||
self.assertEqual(0, len(list(func('for i in range(10)'))))
|
|
||||||
self.assertEqual(0, len(list(func('for i in six.moves.range(10)'))))
|
|
||||||
|
|
||||||
def test_log_context(self):
|
def test_log_context(self):
|
||||||
code = """
|
code = """
|
||||||
LOG.info("Rebooting instance",
|
LOG.info("Rebooting instance",
|
||||||
|
|||||||
5
tox.ini
5
tox.ini
@@ -288,7 +288,6 @@ extension =
|
|||||||
N323 = checks:check_explicit_underscore_import
|
N323 = checks:check_explicit_underscore_import
|
||||||
N324 = checks:use_jsonutils
|
N324 = checks:use_jsonutils
|
||||||
N332 = checks:check_api_version_decorator
|
N332 = checks:check_api_version_decorator
|
||||||
N325 = checks:CheckForStrUnicodeExc
|
|
||||||
N326 = checks:CheckForTransAdd
|
N326 = checks:CheckForTransAdd
|
||||||
N334 = checks:assert_true_or_false_with_in
|
N334 = checks:assert_true_or_false_with_in
|
||||||
N336 = checks:dict_constructor_with_list_copy
|
N336 = checks:dict_constructor_with_list_copy
|
||||||
@@ -300,10 +299,6 @@ extension =
|
|||||||
N350 = checks:check_policy_registration_in_central_place
|
N350 = checks:check_policy_registration_in_central_place
|
||||||
N351 = checks:check_policy_enforce
|
N351 = checks:check_policy_enforce
|
||||||
N343 = checks:check_doubled_words
|
N343 = checks:check_doubled_words
|
||||||
N344 = checks:check_python3_no_iteritems
|
|
||||||
N345 = checks:check_python3_no_iterkeys
|
|
||||||
N346 = checks:check_python3_no_itervalues
|
|
||||||
N327 = checks:check_python3_xrange
|
|
||||||
N348 = checks:no_os_popen
|
N348 = checks:no_os_popen
|
||||||
N352 = checks:no_log_warn
|
N352 = checks:no_log_warn
|
||||||
N349 = checks:CheckForUncalledTestClosure
|
N349 = checks:CheckForUncalledTestClosure
|
||||||
|
|||||||
Reference in New Issue
Block a user