Adds ability to ignore hacking validations with noqa
Add allownoqa decorator that can be applied to any of the hacking core functions. This allows a using application to bypass that particular hacking validation. The reason this is being introduced is because I need to bypass H231 and H233, both Python 3.x validations. I need to bypass these so we can run pep8 validations on the nova XenServer plugins. XenServer usese Python 2.4 in its environment and therefore the code won't pass those two or future Python 3.x validations. It is understood that a patch to hacking won't be held up or reverted if it breaks anything Python 2.4 related, including breaking of this patch. Change-Id: Iea3867b84212ab30bdd168b5dbd43c11a4dc535e
This commit is contained in:
parent
57e14d627a
commit
ce4f1f35c9
@ -54,6 +54,34 @@ def flake8ext(f):
|
||||
f.version = '0.0.1'
|
||||
return f
|
||||
|
||||
|
||||
class HackingDecoratorError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def allownoqa(f):
|
||||
def wrapper(*args, **kwargs):
|
||||
"""Decorator wrapper function for noqa usage.
|
||||
|
||||
Will send None as result of parent function if parent function has
|
||||
physical_line as one of its arguments and also has '# noqa' in the
|
||||
value of the physical_line argument or it will return
|
||||
the parent function with its original arguments.
|
||||
|
||||
Raises:
|
||||
HackingDecoratorError: if physical_line argument missing from
|
||||
decorated function.
|
||||
"""
|
||||
if 'physical_line' not in f.func_code.co_varnames:
|
||||
raise HackingDecoratorError("Missing physical_line argument "
|
||||
"for decorated function")
|
||||
index = f.func_code.co_varnames.index('physical_line')
|
||||
if pep8.noqa(args[index]):
|
||||
return
|
||||
else:
|
||||
return f(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
# Error code block layout
|
||||
|
||||
#H1xx comments
|
||||
@ -259,7 +287,8 @@ def hacking_except_format_assert(logical_line):
|
||||
|
||||
|
||||
@flake8ext
|
||||
def hacking_python3x_except_compatible(logical_line):
|
||||
@allownoqa
|
||||
def hacking_python3x_except_compatible(logical_line, physical_line):
|
||||
r"""Check for except statements to be Python 3.x compatible
|
||||
|
||||
As of Python 3.x, the construct 'except x,y:' has been removed.
|
||||
@ -268,6 +297,7 @@ def hacking_python3x_except_compatible(logical_line):
|
||||
|
||||
Okay: try:\n pass\nexcept Exception:\n pass
|
||||
Okay: try:\n pass\nexcept (Exception, AttributeError):\n pass
|
||||
Okay: try:\n pass\nexcept AttributeError, e: # noqa\n pass
|
||||
H231: try:\n pass\nexcept AttributeError, e:\n pass
|
||||
"""
|
||||
|
||||
@ -308,7 +338,8 @@ def hacking_python3x_octal_literals(logical_line, tokens):
|
||||
|
||||
|
||||
@flake8ext
|
||||
def hacking_python3x_print_function(logical_line):
|
||||
@allownoqa
|
||||
def hacking_python3x_print_function(logical_line, physical_line):
|
||||
r"""Check that all occurrences look like print functions, not
|
||||
print operator.
|
||||
|
||||
@ -317,6 +348,9 @@ def hacking_python3x_print_function(logical_line):
|
||||
|
||||
Okay: print(msg)
|
||||
Okay: print (msg)
|
||||
Okay: print msg # noqa
|
||||
Okay: print >>sys.stderr, "hello" # noqa
|
||||
Okay: print msg, # noqa
|
||||
H233: print msg
|
||||
H233: print >>sys.stderr, "hello"
|
||||
H233: print msg,
|
||||
@ -334,6 +368,7 @@ RE_RELATIVE_IMPORT = re.compile('^from\s*[.]')
|
||||
|
||||
|
||||
@flake8ext
|
||||
@allownoqa
|
||||
def hacking_import_rules(logical_line, physical_line, filename):
|
||||
r"""Check for imports.
|
||||
|
||||
@ -369,9 +404,6 @@ def hacking_import_rules(logical_line, physical_line, filename):
|
||||
#TODO(mordred: We need to split this into 4 different checks so that they
|
||||
# can be disabled by command line switches properly
|
||||
|
||||
if pep8.noqa(physical_line):
|
||||
return
|
||||
|
||||
def is_module_for_sure(mod, search_path=sys.path):
|
||||
mod = mod.replace('(', '') # Ignore parentheses
|
||||
try:
|
||||
@ -603,6 +635,7 @@ def hacking_docstring_multiline_start(physical_line, previous_logical, tokens):
|
||||
|
||||
|
||||
@flake8ext
|
||||
@allownoqa
|
||||
def hacking_no_locals(logical_line, physical_line, tokens):
|
||||
"""Do not use locals() for string formatting.
|
||||
|
||||
@ -613,8 +646,6 @@ def hacking_no_locals(logical_line, physical_line, tokens):
|
||||
H501: print("%(something)" % locals())
|
||||
Okay: print("%(something)" % locals()) # noqa
|
||||
"""
|
||||
if pep8.noqa(physical_line):
|
||||
return
|
||||
for_formatting = False
|
||||
for token_type, text, start, _, _ in tokens:
|
||||
if text == "%" and token_type == tokenize.OP:
|
||||
|
40
hacking/tests/test_noqa_decorator.py
Normal file
40
hacking/tests/test_noqa_decorator.py
Normal file
@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from hacking.core import allownoqa, HackingDecoratorError
|
||||
from testtools import ExpectedException
|
||||
|
||||
import hacking.tests
|
||||
|
||||
|
||||
@allownoqa
|
||||
def method_with_physical_line_argument(physical_line):
|
||||
return "method_with_physical_line_argument"
|
||||
|
||||
|
||||
@allownoqa
|
||||
def method_without_physical_line_argument():
|
||||
return "method_without_physical_line_argument"
|
||||
|
||||
|
||||
class NoqaDecoratorTestCase(hacking.tests.TestCase):
|
||||
def test_with_physical_line_argument(self):
|
||||
result = method_with_physical_line_argument("blah")
|
||||
self.assertEqual(result, "method_with_physical_line_argument")
|
||||
|
||||
def test_without_physical_line_argument(self):
|
||||
with ExpectedException(HackingDecoratorError, "Missing physical_line "
|
||||
"argument for decorated function"):
|
||||
method_without_physical_line_argument()
|
Loading…
Reference in New Issue
Block a user